Sometimes file writes fail on Windows because another process (like sourcekitd or clangd) still has exclusive access to the file but releases it soon after. Retry to save the file if this happens. This matches what a user would do.
I feel like the implementations are actually simpler if we split them. This will also allow us to add more advanced logic to the JSON compilation database build system in the future, such as inferring the toolchain from the compile command.
There were a few places that options only took place *after* determining
a build system, even though we have multiple that impact the search (eg.
`defaultBuildSystem` and `searchPaths`).
Additionally track project root and configuration paths separately, so
that when searching for implicit workspaces we can make sure to skip
creating duplicates.
If a BSP server crashes, we should try to relaunch it. Use a similar relaunch logic as the one we use for `clangd`: Try restarting immediately unless the BSP server has crashed within the last 30 seconds, in which case we delay the restart by 10s.
rdar://136311009
Fixes#1686
Now that all the types that model test projects are suffixed `Project` instead of `Workspace`, the `ws` abbreviation doesn‘t make sense. It also never really fit with the new style of avoiding abbreviations. Rename all occurrences to `project`.
rdar://124727401
Rename all the classes that write files to disk to create a test project that we can open in sourcekit-lsp to end with `TestProject`. This is better than the old `Workspace` suffix because it avoids ambiguities with the `Workspace` type inside sourcekit-lsp.
- IndexedSingleSwiftFileWorkspace -> IndexedSingleSwiftFileTestProject
- MultiFileTestWorkspace -> MultiFileTestProject
- SwiftPMTestWorkspace -> SwiftPMTestProject
We could get into a race condition in `testAddFile` where the `DidChangeWatchedFilesNotification` would get handled after we try getting completion results that rely on it.
In a real-world use case, this is OK. Completion might still be incorrect until `DidChangeWatchedFilesNotification` gets handled but it will catch up eventually - usually earlier than later because in real-world scenarios the `DidChangeWatchedFilesNotification` and completion request are more than a few milliseconds apart.
In test, however, we need to guarantee deterministic ordering. Introduce a `BarrierRequest` that has `TaskMetadata.globalConfigurationChange` and thus ensures that all notifications and requests before it have finished before returning. We can run this fake request after sending the `DidChangeWatchedFilesNotification` to make sure that it is handled.
An alternative would be to mark `DidChangeWatchedFilesNotification` as `TaskMetadata.globalConfigurationChange`. But I would really like to avoid introducing a global ordering barrier between requests for a notification that is, for example, sent whenever a `.swift` file in the `.build` directory changes (e.g. on every package update).
- Remove the JSONRPC connection kind between `TestSourceKitServer` and `SourceKitServer`
- It wasn’t actually used and the connection abstraction just made things more complicated than they needed to be
- Send requests and notifications to `SourceKitServer` by directly calling into `SourceKitServer.handle` instead of going through a `Connection`. This makes the code a lot easier to understand statically
- Make `TestSourceKitServer` conform to `MessageHandler` instead of going through `TestClient`
- IMO this centralizes all the handling and makes it a lot easier to follow. `TestClient` didn’t do a whole bunch anyway.
- Allow async awaiting of next notifications instead of having to register a `handleNextNotification` handler before expecting the notification to be emitted.
- This allows us to remove quite a few `XCTExpectation`s in test cases
- Change `sendSync` function that sends a request and returns the result to be `async`
Add `.swift-format` to the repo and format the repo with `swift-format`.
This commit does not add any automation to enforce formatting of sourcekit-lsp in CI. The goal of this commit is to get the majority of source changes out of the way so that the diff of actually enforcing formatting will have fewer changes or conflicts.
The core idea here is that the toolchain language servers always call into `BuildSystemManager` and `BuildSystemManager` will always reply with build settings. If it hasn’t computed them yet, it will reply with fallback settings.
With that assumption, we can remove the `documentToPendingQueue` from `SourceKitServer` since there are no longer any documents that are pending – everything has a build settings immediately.
Similarly, `BuildSystemManager.mainFileStatuses` also isn’t needed anymore.
And lastly, since we know that `BuildSystemManager.buildSettings` will always return a value `registerForChangeNotifications` is changed not call `fileBuildSettingsChanged` immediately. Instead, it will only cause `fileBuildSettingsChanged` to be called when the file’s build settings change after the `registerForChangeNotifications` call.
Unfortuantely, we have a few potential out-of-order exeuction possibilities while we migrate everything else to also be asyncronous. But those should be low-probability issues that we can fix in follow-up commits, so I think it’s fine for now. All of these places are marked with `FIXME: (async)`
The asyncification changes caused some non-deterministic test failures. I believe that some of these are due to race conditions that are the result of the partial transition to actors.
Instead of merging the asyncification piece by piece, I will collect the changes asyncification changes in a branch and then qualify that branch througougly (running CI multiple times) before merging it into `main`.
Unfortuantely, we have a few potential out-of-order exeuction possibilities while we migrate everything else to also be asyncronous. But those should be low-probability issues that we can fix in follow-up commits, so I think it’s fine for now. All of these places are marked with `FIXME: (async)`
Replace the use of `sleep` which is a POSIX construct for the portable
`Thread.sleep(forTimeInterval:)` which has similar semantics but allows
the code to be built for other platforms. This allows us to finally
build the test suite for Windows.
Similar to how we reload the package if Package.swift is changed, we also watch `compilation_database.json` and `compile_flags.txt` and notify the build system delegate that build settings changed if these files are modified.
rdar://92388223 [#486]