We previously waited for the initialization response from the build server during the creation of a `Workspace` so that we could create a `SemanticIndexManager` with the index store path etc. that was returned by the `build/initialize` response. This caused all functionality (including syntactic) of SourceKit-LSP to be blocked until the build server was initialized.
Change the computation of the `SemanticIndexManager` and related types to happen in the background so that we can provide functionality that doesn’t rely on the build server immediately.
Fixes#2304
Absolute search paths were being ignored without logging, which makes it
somewhat difficult to diagnose. Log when they're skipped.
Also remove a duplicate options merging block - both
`createWorkspaceWithInferredBuildServer` and `findImplicitWorkspace`
(the only callers of `createWorkspace`) already merge in the workspace
options.
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
Depends on https://github.com/swiftlang/swift/pull/83378
---
Adds support for the LSP signature help request.
> [!NOTE]
> As of https://github.com/swiftlang/swift/pull/83378, SourceKitD still
doesn't separate parameter documentation from the signature
documentation and thus parameters don't have their own separate
documentation. This should just work once SourceKitD implements this
functionality and we'll only need to modify the tests.
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.
If a build server copies files (eg. header) to the build directory during preparation and those copied files are referenced for semantic functionality, we would currently jump to the file in the build directory. Teach SourceKit-LSP about files that are copied during preparation and if we detect that we are jumping to such a file, jump to the original file instead.
So far only the definition request checks the copied file paths. Adding support for copied file paths in the other requests will be a follow-up change.
There's been a couple issue where it is clear from the log of the global
configuration that options are being set *somewhere*, but users then
have to go searching in all the paths we lookup (which is quite a few).
Log each config we read so it's easy to see where the options are coming
from.
Clang’s `textDocument/symbolInfo` request does not return a `kind` field. We were thus filtering all symbols from clang, which left us with no USR that could be used for the type hierarchy.
With the introduction of secondary language services, we don’t expect every language service to implement every request anymore. To simplify the addition of language services like `DocumentationLanguageService` add default implementations for methods that satisfy the following criteria:
- `SourceKitLSPServer` does not expect side effects to happen when they are called
- The method can throw or there is a reasonable default value
- It is reasonable to expect that not all language services need to implement it
If a language service fails to start, don't try starting language services with lower precedence. Otherwise we get into a situation where eg. `SwiftLanguageService`` fails to start (eg. because the toolchain doesn't contain sourcekitd) and the `DocumentationLanguageService` now becomes the primary language service for the document, trying to serve documentation, completion etc. which is not intended.
This allows us to implement all of `doccDocumentation` in `DocumentationLanguageService`. `DocumentationLanguageService` will be a secondary language service for Swift files and can also provide the docc documentation support that’s currently in `SwiftLangaugeService`.
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.
The motivation for this is that I noticed that the `workspace/peekDocuments` request only allows the specification of a document to peek but not the location to peek within it. The fix is to change the `location` parameter from `DocumentUri` to `Location`, but this is a protocol-breaking change, so the client needs to communicate that it can support locations in the `workspace/peekDocuments` request.
The client currently communicates that it supports peeking documents by passing `workspace/peekDocuments: true` in the experimental client capabilities. We could just add another option to the experimental client capabilities like `workspace/peekDocuments.supportsLocations` but this seems a little hacky. Instead, what I propose is that we
1. Allow enabling experimental capabilities as `"<capability name>": { "supported": true }`
2. Switch the VS Code Swift extension to enable client capabilities using a dictionary if it discovers that it uses SourceKit-LSP ≥6.3 (older SourceKit-LSP don’t recogize a dictionary as enabling a capability)
3. Expanding the options to `"workspace/peekDocuments": { "supported" true, "supportsLocation": true }` to communicate that location-based peeking is supported
This pattern will also support experimental capability changes like this in the future.
Use cases that might lack because of this are:
1. Using an old Swift 6.3 toolchain that doesn’t support dictionary-based capabilities with the VS Code Swift extension. In that case macro expansion will work in the fallback mode that we have for other editors and active editor tracking (which cancels target preparation when a file is switched) is disabled. I think this is acceptable.
2. If there are other editors that support these experimental capabilities, they will continue to work just fine by passing the boolen value to enable the option. If they want to support one of the options (eg. location-based peeking), they will need to switch to dictinary-based enabling and thus check the SourceKit-LSP version prior to startup. This might be mildly annoying on their side but since the number of client that support these capabilities should be very small (I am not aware of any) and they need to explicitly opt-in to the new behavior, I think this is also acceptable.
This request is generally useful, not only for tests within SourceKit-LSP but also:
- In editor tests that want to test the integration with SourceKit-LSP
- In code analysis tools that want to gather project information using SourceKit-LSP and need an up-to-date index for that.
Remove the experimental feature guard from `workspace/_synchronize`, consequently rename it to `workspace/synchronize` and only guard the `buildServerUpdates` option on the synchronize request by an experimental feature because its long-term usefulness is still not fully understood yet.
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.
If a source file is part of multiple targets, we should index it in the context of all of those targets because the different targets may produce different USRs since they might use different build settings to interpret the file.