228 Commits

Author SHA1 Message Date
Alex Hoppen
425e1322a1 Explicitly close the index when shutting down SourceKit-LSP
`IndexStoreDB` moves its index to the `saved` directory when it is deallocated. Because `IndexStoreDB` is primarily owned by `UncheckedIndex`, we rely on deallocating this object to save the index store. This is fairly brittle because various parts of the codebase may hold transient references to that object as reported in https://github.com/swiftlang/sourcekit-lsp/issues/2455#issuecomment-3873561003.

Explicitly remove the reference from `UncheckedIndex` to `IndexStoreDB`. While this still isn’t perfect because other parts of the code base may hold references to `IndexStoreDB` but those should be a lot rarer, resulting in a more consistent closing of the index.
2026-02-15 18:02:53 +01:00
Bruno Rocha
282e7745ee Fix inverted log check when updating the index store 2026-02-04 11:21:56 +01:00
Alex Hoppen
d449cb78be Merge pull request #2294 from josh-arnold-1/preparation-batch-size 2025-12-06 10:04:55 +01:00
Ben Barham
9c145fd9a2 Merge pull request #2375 from bnbarham/pass-toolset-through
Pass toolsets through to preparation for the SwiftPM build server
2025-12-04 07:46:36 +10:00
Josh Arnold
668aab32ac Support custom preparationBatchSize defined via SourceKit's options 2025-12-03 13:37:25 -06:00
Ben Barham
9952a11f4b Pass toolsets through to preparation for the SwiftPM build server
Also adds some logging to the synchronize request so that it's obvious
when background indexing is being skipped.

Fixes #2373
Resolves rdar://165519940
2025-12-03 10:19:49 +10:00
Anthony Latsis
d1b9c27b95 Merge pull request #2366 from AnthonyLatsis/jepa
Enable some Swift 7 mode features
2025-12-02 17:37:01 +00:00
Anthony Latsis
6b19657739 Enable ExistentialAny 2025-12-02 12:27:27 +00:00
Alex Hoppen
f9f13a4105 Don’t use Optional.map or Optional.flatMap
Replace usages of `Optional.map` and `Optional.flatMap` by if expressions or other expressions.

I personally find `Optional.map` to be hard to read because `map` implies mapping a collection to me. Usually the alternative constructs seem clearer to me.
2025-11-20 09:47:21 +01:00
Mishal Shah
0876b7d403 Merge pull request #2324 from owenv/owenv/adopt-swift-tools-protocols
Adopt swift-tools-protocols
2025-11-05 09:02:00 -08:00
Michael Gottesman
43dd488d00 Add [weak self] in two places.
The reason why I am making the first change is because in a separate PR in
swiftlang I am fixing a bug that caused certain captured parameters to be
treated as sending parameters incorrectly. This allowed for parameters to
incorrectly be allowed to be sent from one isolation domain to another.

The specific problem here can be seen with the following swift code:

```swift
actor B {
  init(callback: @escaping @Sendable () -> Void) async {}
}

actor A {
  private func poke() {}
  func schedule() async {
    _ = await B(
      callback: { [weak self] in // closure 1
        Task.detached { // closure 2
          await self?.poke()
        }
      })
  }
}
```

When we capture the weak self from closure 1 in closure 2, we are not actually
capturing self directly. Instead we are capturing the var box which contains the
weak self. The box (unlike self) is actually non-Sendable. Since closure 2 is
not call(once), the compiler must assume semantically that the closure can be
invoked potentially multiple times meaning that it cannot allow for self to be
used in Task.detached. The fix for this is to perform an inner [weak self]
capture. As follows:

```swift
actor A {
  private func poke() {}
  func schedule() async {
    _ = await B(
      callback: { [weak self] in // closure 1
        Task.detached { [weak self] // closure 2
          await self?.poke()
        }
      })
  }
}
```

The reason why this works is that when we form the second weak self binding, we
perform a load from the outer weak self giving us an Optional<A>. Then we store
that optional value back into a new weak box. Since Optional<A> is Sendable, we
know that the two non-Sendable weak var boxes are completely unrelated, so we
can send that new var box into the new Task.detached safely.

The second `[weak self]` is just something I noticed later in the function. The
`[weak self]` just makes the detached function safer.
2025-10-31 14:52:37 -07:00
Owen Voorhees
f04b971726 Adopt swift-tools-protocols 2025-10-31 14:11:11 -07:00
Alex Hoppen
95538e7de9 Migrate appendingPathComponent to appending(component:)
`appending(component:)` is the more modern API and can take multiple path components at the same time.
2025-09-23 16:57:56 +02:00
Alex Hoppen
32e919c0cd Merge pull request #2302 from ahoppen/multi-file-indexing-batch-size
Match the batch size for multi-file indexing to the driver's batch size
2025-09-23 16:53:57 +02:00
Alex Hoppen
05c04decf2 Match the batch size for multi-file indexing to the driver's batch size
Until we have better measurements that would motivate a different batching strategy, copying the driver’s batch size seems like the most reasonable thing to do.
2025-09-22 09:52:44 +02:00
Alex Hoppen
4fe68eebfb Use activeProcessorCount instead of processorCount in short-lived use-cases
According to https://developer.apple.com/documentation/foundation/processinfo/activeprocessorcount

> Whereas the processorCount property reports the number of advertised processing cores, the activeProcessorCount property reflects the actual number of active processing cores on the system. There are a number of different factors that may cause a core to not be active, including boot arguments, thermal throttling, or a manufacturing defect.

For short-lived workloads like `concurrentMap` we want to parallelize across the number of cores that are currently active, so use `activeProcessorCount` instead. The only case where we want to continue using `processorCount` is the computation of concurrent tasks for `TaskScheduler` because the value is stored for the lifetime of the SourceKit-LSP process and we don’t want to limit parallelism if SourceKit-LSP was launched during a time of thermal throttling.

I stumbled across this while working on #2302
2025-09-22 09:51:41 +02:00
Alex Hoppen
078a996dac Merge pull request #2293 from ahoppen/multi-file-indexing
Support indexing of mulitple Swift files within the same compiler invocation
2025-09-22 09:02:03 +02:00
Alex Hoppen
d1981debec Do not cancel update index store tasks in favor of a task with fewer files
We should not take the number of files in an `UpdateIndexStoreTaskDescription` as an indication on how important the task is. If we do need this functionality, eg. because we want to update the index of files with syntactic matches for a rename term, this should be communicated using a specific purpose similar to `TargetPreparationPurpose`. Since the only reason we update the index store for a file right now is background indexing, such a check is not needed.
2025-09-20 16:26:26 +02:00
Alex Hoppen
a005021666 Support indexing of mulitple Swift files within the same compiler invocation
Fixes #1268
2025-09-20 16:26:26 +02:00
Alex Hoppen
fa67c22235 Merge pull request #2277 from ahoppen/bsp-timeouts
Add a timeout for `workspace/buildTargets` and `buildTarget/sources` requests
2025-09-20 13:13:40 +02:00
Alex Hoppen
e60894c482 Pass multiple URIs to updateIndexStore(forSwiftFiles:) 2025-09-13 12:44:05 +02:00
Alex Hoppen
78608933ba Guarantee that all files in a UpdateIndexStoreTaskDescription have the same language
It doesn’t make sense to try and index files with different langauges in a single compiler invocation.
2025-09-03 17:51:18 +02:00
Alex Hoppen
5c4f1ca93c Make UpdateIndexStoreTaskDescription.updateIndexStore handle mulitple files
This pushes multi-file indexing one level closer to the actual compiler invocation.
2025-09-03 08:58:01 +02:00
Alex Hoppen
690fd9288f Extract target out of the FileIndexInfo used by UpdateIndexStoreTaskDescription
This way we can guarantee that all files passed to `UpdateIndexStoreTaskDescription` belong to the same target, which will simplify multi-file indexing.
2025-09-03 08:45:04 +02:00
Alex Hoppen
dddc983dd2 Make BuildServerManager.toolchain only take a target, no document
The document wasn’t used in here.
2025-09-03 08:39:59 +02:00
Alex Hoppen
d73433128d Make the build/logMessage conform to the BSP spec
When I added the log structure to `build/logMessage` in #2022 I must have assumed that the entire BSP notifciation was an extension defined by SourceKit-LSP and didn’t realized that this was actually a change that made the notification non-compliant with BSP. Change it up a little bit to make it compliant again.
2025-09-02 20:41:40 +02:00
Alex Hoppen
56fa14a687 Merge pull request #2274 from ahoppen/empty-target
Fix issue that caused the index progress indicator to get stuck if there are no sources in a target
2025-09-01 17:16:29 +02:00
Alex Hoppen
8b20ce734e Merge pull request #2273 from ahoppen/determining-files
Improve `Indexing: Scheduling tasks` message
2025-09-01 17:16:19 +02:00
Alex Hoppen
c142b601ff Add a timeout for workspace/buildTargets and buildTarget/sources requests
This allows us to provide functionality based on fallback settings for unresponsive BSP servers.

Fixes #2252
2025-09-01 16:12:41 +02:00
Alex Hoppen
e758b5711b Fix issue that caused the index progress indicator to get stuck if there are no sources in a target 2025-08-31 08:54:36 +02:00
Alex Hoppen
131dc69c79 Improve Indexing: Scheduling tasks message
The majority of the work here is getting the list of files to index from the build server. Let’s rename the message to reflect that.
2025-08-31 08:21:54 +02:00
Alex Hoppen
d9046e4737 Fix issue that caused targets to be sorted top-down instead of bottom-up for background indexing
This sign flip slipped in with https://github.com/swiftlang/sourcekit-lsp/pull/1674.

There was also a non-determinism in the prepration schedule order.
2025-08-30 20:49:55 +02:00
Alex Hoppen
3762e7a2a4 Fix all warnings
Fixes all warnings when building on macOS and Linux using Swift 6.1, Swift 6.2 and SDKs from Xcode 16.2 and Xcode 16.3
2025-08-25 14:40:16 +02:00
Alex Hoppen
98cd30bb1c Apply exhaustive swift-format configuration from swift-syntax
Apply the exhaustive swift-format configuration from https://github.com/swiftlang/swift-syntax/pull/3117 to sourcekit-lsp. Also apply all automatic formattings.
2025-08-11 09:23:39 +02:00
Alex Hoppen
7f4f92e5bd Rename build system to build server in most cases
The term *build system* predated our wide-spread adoption of BSP for communicating between SourceKit-LSP to the build system and was never really the correct term anyway – ie. a `JSONCompilationDatabaseBuildSystem` never really sounded right. We now have a correct term for the communication layer between SourceKit-LSP: A build server. Rename most occurrences of *build system* to *build server* to reflect this. There are unfortunately a couple lingering instances of *build system* that we can’t change, most notably: `fallbackBuildSystem` in the config file, the `workspace/waitForBuildSystemUpdates` BSP extension request and the `synchronize-for-build-system-updates` experimental feature.
2025-08-02 08:45:01 +02:00
Ben Barham
d5926bf69f Run formatting after swift-format changes 2025-06-30 17:08:05 -07:00
Alex Hoppen
be5ae8cf1c Merge pull request #2153 from ahoppen/check-shutdown
Do not schedule any new tasks in `TaskScheduler` if it has been shut down
2025-05-14 19:12:41 +02:00
Alex Hoppen
ba1fb5de07 Do not schedule any new tasks in TaskScheduler if it has been shut down
This is what `shutDown()` is documented to do. I also remember having this check before, it might have gotten lost during a rebase when I was working on https://github.com/swiftlang/sourcekit-lsp/pull/2081.

I noticed this while investigating https://github.com/swiftlang/sourcekit-lsp/pull/2152: In this case `buildTarget/prepare` was cancelled because the SourceKit-LSP server was shut down but indexing of a file was still started after the shutdown now that preparation had finished (because it was cancelled).
2025-05-13 17:29:44 +02:00
Alex Hoppen
47a940d8bd Fix race condition that causes task cancellation to be missed in TaskScheduler
A queued task might have been cancelled after the execution ask was started but before the task was yielded to `executionTaskCreatedContinuation`. In that case the result task will simply cancel the await on the `executionTaskCreatedStream` and hence not call `valuePropagatingCancellation` on the execution task. This means that the queued task cancellation wouldn't be propagated to the execution task. To address this, check if `resultTaskCancelled` was  set and, if so, explicitly cancel the execution task here.

Fixes an issue I saw in CI during PR testing.
2025-05-13 17:24:45 +02:00
Matthew Bastien
39bf4852b0 handle Markdown and Tutorial files in textDocument/doccDocumentation 2025-04-16 14:44:11 -04:00
Alex Hoppen
e474354bca Merge pull request #2051 from ahoppen/build-graph-generation
Don't wait for build graph generation when file is changed
2025-03-26 14:40:06 -07:00
Alex Hoppen
3bb4690db4 Terminate pending background indexing and preparation tasks when shutting down SourceKit-LSP
When SourceKit-LSP is shut down, we should make sure that we don’t leave behind child processes, which will become orphans after SourceKit-LSP has terminated. What’s worse, when SourceKit-LSP has exited, these processes might not have any process to read their stdout/stderr, which can lead to them running indefinitely.

This change does not cover the termination of subprocess trees. For example, if we launch `swift build` and need to kill it because it doesn’t honor SIGINT, its child processes will still live on. Similarly, if we kill a BSP server, its child processes might live on. Fixing this is a drastically bigger endeavor, likely requiring changes to Foundation and/or TSC. I filed https://github.com/swiftlang/sourcekit-lsp/issues/2080 for it.
2025-03-25 14:10:38 -07:00
Alex Hoppen
e28c460f6d Merge pull request #2079 from ahoppen/dependent-targets
Move `targets(dependingOn:)` call out of the changed files loop
2025-03-24 13:27:41 -07:00
Alex Hoppen
54ac721f7e Merge pull request #2072 from ahoppen/update-index-store-db-during-indexing
Ensure that unit file generated by background indexing are immediately loaded into indextore-db
2025-03-24 13:27:23 -07:00
Alex Hoppen
2ddacb1c9f Move targets(dependingOn:) call out of the changed files loop
We can call this function once we have gathered all changed targets instead of once for each changed file, which should be slightly more performant.
2025-03-21 16:33:47 -07:00
Alex Hoppen
fa32cbc8b0 Do not re-index deleted files
This wasn’t an issue when we were always waiting for an up-to-date build graph before indexing files but now we could still have an old build graph that contains the deleted files and thus start an indexing process for a file that doesn’t exist anymore on disk. And it’s cleaner anyway.
2025-03-20 10:32:52 -07:00
Alex Hoppen
8b2727f9f9 Ensure that unit file generated by background indexing are immediately loaded into indextore-db
Otherwise, we can end up in a situation where we declare indexing as done but haven’t loaded the new units into indexstore-db yet.
2025-03-19 07:24:16 -07:00
Alex Hoppen
a76f57202e Don’t enter an infinite loop when a circular symlink is added to a project 2025-03-18 14:18:25 -07:00
Alex Hoppen
dcad3f4fd6 Don't wait for build graph generation when file is changed
Since we re-index source files if the build server sends us a `buildTarget/didChange` notification, we no longer need to wait for an up-to-date build graph when a file is modified. This resolves an issue that causes a `Scheduling tasks` progress to appear in the status bar whenever a file in the project is changed. Before https://github.com/swiftlang/sourcekit-lsp/pull/1973, this happened fairly frequently during the initial indexing when a header file was written into the build directory. After that PR the `Scheduling Indexing` status appears a lot more frequently, namely every time the index’s database is modified, which happens quite all the time during indexing...
2025-03-18 14:03:42 -07:00
Alex Hoppen
77b39200dc Fix typos 2025-03-17 17:10:00 -07:00