Commit Graph

47 Commits

Author SHA1 Message Date
Alex Hoppen
d8651a3b73 Fix a compilation issue caused by #1533 and #1524 racing 2024-06-28 22:57:48 +02:00
Alex Hoppen
68bff7f216 Make background indexing a proper option in SourceKitLSPOptions
This allows us to flip the default in the future more easily. It also allows users to disable background indexing when it’s enabled by default.

rdar://130280855

# Conflicts:
#	Tests/SourceKitLSPTests/BackgroundIndexingTests.swift
2024-06-28 22:36:11 +02:00
Alex Hoppen
3e9c682cc9 Allow configuring of SourceKit-LSP’s options using .sourcekit-lsp configuration files
The idea here is to unify the different ways in which we can currently set options on SourceKit-LSP in a scalable way: Environment variables, command line arguments to `sourcekit-lsp` and initialization options.

The idea is that a user can define a `~/.sourcekit-lsp/.sourcekit-lsp` file (we store logs in `~/.sourcekit-lsp/logs` on non-Darwin platforms), which will be used as the default configuration for all SourceKit-LSP instances. They can also place a `.sourcekit-lsp` file in the root of a workspace to configure SourceKit-LSP for that project specifically, eg. setting arguments that need to be passed to `swift build` for that project and which thus also need to be set on SourceKit-LSP.

For compatibility reasons, I’m mapping the existing command line options into the new options structure for now. I hope to delete the command line arguments in the future and solely rely on `.sourcekit-lsp` configuration files.

Environment variable will be migrated to `.sourcekit-lsp` in a follow-up commit.

# Conflicts:
#	Sources/SourceKitLSP/SourceKitLSPServer+Options.swift
#	Sources/SourceKitLSP/Swift/SwiftLanguageService.swift
#	Sources/sourcekit-lsp/SourceKitLSP.swift
#	Tests/SourceKitLSPTests/BackgroundIndexingTests.swift
#	Tests/SourceKitLSPTests/ExecuteCommandTests.swift
2024-06-28 22:35:15 +02:00
Alex Hoppen
8642768902 Fix a few Swift concurrency warnings 2024-06-18 18:07:22 -07:00
Alex Hoppen
c43cffd044 Change all variables that are Atomic* types to not be nonisolated(unsafe)
Since the `Atomic*` types can not be marked as `Sendable` (because they aren’t C structs), we can change the variables to constants and can remove `nonisolated(unsafe)`.
2024-06-07 08:49:10 -07:00
Alex Hoppen
556fd333b5 Heap allocate our atomics
We used C atomics but these were allocated as Swift variables. Even thought they were atomic, concurrent accesses to them could violate Swift’s exclusivity laws, raising thread sanitizer errors.

Allocate the C atomics using malloc to fix this problem.

rdar://129170128
2024-06-05 23:27:47 -07:00
Alex Hoppen
b479b2e874 Create a SwiftExtensions module
This allows us to share common Swift utility functions between SourceKit-LSP and LSPLogging.
2024-06-04 07:06:44 -07:00
Alex Hoppen
fff9eb569e Merge pull request #1382 from ahoppen/stream-index-log
Instead of sending a message to the index log when an indexing task finishes, stream results as they come in
2024-06-03 19:33:29 -07:00
Alex Hoppen
f98da773a9 Make passing --experimental-prepare-for-indexing to swift build an experimental feature
I’d like to qualify `--experimental-prepare-for-indexing` independently of background indexing using `swift build`. Because of this, I think there is value in using SourceKit-LSP using background indexing but without `--experimental-prepare-for-indexing`. It could also be useful to determine if bugs we may find are due to `--experimental-prepare-for-indexing` or also occur when running plain `swift build` commands.
2024-06-03 15:22:00 -07:00
Alex Hoppen
09ad77ba8d Instead of sending a message to the index log when an indexing task finishes, stream results as they come in
This also means that you can use the index log to view which tasks are currently being executed.

Since we only have a single log stream we can write to, I decided to prefix every line in the index log with two colored emojis that an easy visual association of every log line to the task that generated them.
2024-06-03 13:21:54 -07:00
Alex Hoppen
3b68f15bc4 Merge pull request #1394 from ahoppen/thread-safe-box-sendable
Require `ThreadSafeBox.T` to be Sendable
2024-06-03 13:13:57 -07:00
Alex Hoppen
c7bf59e2ee Require ThreadSafeBox.T to be Sendable
Otherwise, I think `ThreadSafeBox` might still have data races. This also requires us to make `TestSourceKitLSPClient.RequestHandler` sendable.

rdar://128572489
2024-06-03 10:23:13 -07:00
Alex Hoppen
259d49e12c Share module cache between test projects
This improves serial test execution time of eg. `DocumentTestDiscoveryTests` from 36s to 22s because we don’t need to re-build the XCTest module from its interface when using an open source toolchain.

This also uncovered that we weren‘t passing the build setup flags to the prepare command.

rdar://126493151
2024-06-03 09:29:16 -07:00
Alex Hoppen
2258a6c815 Merge pull request #1389 from ahoppen/experimental-features
Add a general notion of experimental features to sourcekit-lsp
2024-06-01 22:30:52 -07:00
Alex Hoppen
eb304c4759 Add a general notion of experimental features to sourcekit-lsp
Background indexing probably won’t be the last experimental feature in sourcekit-lsp that we want to gate behind a feature flag. Instead of adding new parameters ad-hoc, introduce a general notion of experimental features.
2024-06-01 08:35:31 -07:00
Alex Hoppen
e56c71f4b3 Don’t run a swift build command to prepare a package manifest
Package manifests don’t have an associated target to prepare and are represented by a `ConfiguredTarget` with an empty target ID. We were mistakingly running `swift build` with an empty target name to prepare them, which failed. There is nothing to prepare.
2024-05-31 21:45:12 -07:00
Alex Hoppen
2beae820b3 Don’t catch CancellationError for document diagnostics
We were catching errors during diagnostic generation because VS Code will not request diagnostics again if SourceKit-LSP returns an error to any diagnostic request. We were, however, a little over-eager when doing this and also caught cancellation errors, which means that if the user made multiple edits in quick succession (which would cancel the diagnostics request from the first edit), we would return empty diagnostics, clearing the displayed diagnostics.
2024-05-31 07:59:47 -07:00
Alex Hoppen
05dd10257d Wait for target to be prepared before returning diagnostics
Diagnostics are usually not helpful if the file’s target hasn’t been prepared yet. We should await the target’s preparation before returning diagnostics.

rdar://128645617
2024-05-26 18:55:15 -07:00
Alex Hoppen
1ea20eb28f Show a work done progress while the semantic index is rebuilding a build graph
Rebuilding the build graph can take a while (initial loading of the build graph takes ~7s for sourcekit-lsp) and it’s good to show some progress during this time.
2024-05-24 11:23:15 -07:00
Alex Hoppen
3f7d9a7b76 Fix a non-deterministic test failure in testPrepareTargetAfterEditToDependency
We could get a `DiagnosticsRefreshRequest` before the modified target had been re-prepared.
2024-05-22 14:46:03 -07:00
Alex Hoppen
9e49f67455 Rename TestSourceKitLSPClient.handleNextRequest to handleSingleRequest
Since `handleNextRequest` handling doesn’t have to be in the order that the request handlers were specified anymore, the naming was misleading.
2024-05-22 13:31:58 -07:00
Alex Hoppen
da96d45443 Add a development subcommand to index a project
This allows us to run `sourcekit-lsp index --project /path/to/project` to index a project. Intended to debugging purposes, eg.
- Profile the time it takes to index a project
- See if the project can be indexed successfully
- Look at signposts generated during indexing in Instruments to see whether indexing or preparation is the bottleneck and how well we can parallelize tasks.
2024-05-21 22:29:52 -07:00
Alex Hoppen
3e6319c3b9 Produce an index log for the client
This allows a user of SourceKit-LSP to inspect the result of background indexing. This allows a user of SourceKit-LSP to inspect the result of background indexing. I think this gives useful insights into what SourceKit-LSP is indexing and why/how it fails, if it fails, also for users of SourceKit-LSP.

rdar://127474136
Fixes #1265
2024-05-21 22:18:06 -07:00
Alex Hoppen
195d3af74e Move LocalConnection to LSPTestSupport
We weren’t logging requests sent to a `TestSourceKitLSPClient` because we were assuming that `JSONRPCConnection` logs those requests in `SourceKitLSPServer`. But no logging happens in `LocalConnection`, which `TestSourceKitLSPClient` uses.

Since `LangaugeServerProtcol` can’t depend on `LSPLogging`, move the type to `LSPTestsSupport`.
2024-05-17 11:59:40 -07:00
Alex Hoppen
fae712b278 Make SKTestSupport build in Swift 6 mode 2024-05-14 15:04:33 -07:00
Alex Hoppen
66ecdd35b7 Make SKSwiftPMWorkspaceTests build in Swift 6 mode 2024-05-14 15:00:43 -07:00
Alex Hoppen
c9b51f9b34 Allow client request handlers specified on TestSourceKitLSPClient to be executed in any order 2024-05-14 06:38:22 -07:00
Alex Hoppen
eaa378f390 Plumb capabilities to SwiftPMTestProject and add a closure that can be executed before SourceKit-LSP is initialized 2024-05-14 06:38:22 -07:00
Alex Hoppen
fd7b268431 Reload a file when other files within the same module or a .swiftmodule file has been changed
When the client sends us `workspace/didChangeWatchedFiles` notification of an updated `.swift` file, we should refresh the other open files in that module since they might be referencing functions from that updated file.

If a `.swiftmodule` file has been updated, we refresh all the files within the package since they might import that module. Technically, we would only need to refresh files that are in module that are downstream of the updated module but we don’t currently have that information easily available from SwiftPM. Also, usually, if the client has a file from a low-level module open, he’ll be working on that module which means that such an optimization won’t help. The real solution here is to wait for us to finish preparation (which we would exactly know when it finishes since sourcekit-lsp would schedule it) but for that we need to implement background preparation.

Fixes #620
Fixes #1116
rdar://99329579
rdar://123971779
2024-04-23 09:34:20 -07:00
Alex Hoppen
08f1595b5b Never return nil for position conversions
Instead of returning `nil` to indicate that the position conversion failed, log a fault and perform a best-effort recovery.

I think this allows us to perform better recovery and also makes code calling these position conversions a lot simpler because it doesn’t need to make decisions about what to do if position conversions fail.
2024-04-11 13:59:17 -07:00
Alex Hoppen
161171668c Rename test projects for consistency
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
2024-03-20 22:50:34 +01:00
Alex Hoppen
4b5f7ffd90 Rename SourceKitServer -> SourceKitLSPServer
This avoid ambiguities whether `SourceKitServer` handles sourcekitd or `sourcekit-lsp`.
2024-03-20 22:50:34 +01:00
Alex Hoppen
3007d9f392 Naming improvements, added comments and typo fixes in connection related code
This should make the code easier to understand. No functionality change.
2024-03-20 08:30:16 +01:00
Alex Hoppen
7c46df3abe Remove clientID from request handling
The client ID was needed when a `MessageHandler` could handle messages from multiple connections. We don’t support this anymore (because it wasn’t needed) and so the client ID doesn’t need to get passed through as well.
2024-03-20 08:28:26 +01:00
Alex Hoppen
1877d470a3 Use pull diagnostics by default in tests
Currently, all tests send publish diagnostics notifications, which is noise in the logs for most tests. Change the tests to use the pull diagnostics model by default and make the push diagnostic model opt-in.

rdar://123241539
2024-02-27 19:06:20 -08:00
Alex Hoppen
a60690858c Show message in the client if no compiler arguments could be found for a file
This should help users debug issues when functionality is not working because compiler arguments are missing.

Note that when opening a standalone Swift file, we consider that file as having non-fallback build settings, even though the build settings are synthesized from the fallback build system. Thus, this will only pop up when the user is in a context that has some build system (like a compilation database or a Swift package) but the current file isn’t handled by that.

rdar://119741960
2024-02-23 23:46:49 -08:00
Alex Hoppen
6505ec8f7e Make ToolchainRegistry initializer synchronous
This requires a bit of a restructuring of `ToolchainRegistry` because calling `scanForToolchain` on `self` is a suspension point. Instead, we need to implement the entire toolchain discovery in the initializer itself, which really isn’t that bad anyway.

This allows us to make the `SourceKitLSP.run` function synchronous again.

Fixes #1023
rdar://120976054
2024-01-18 15:25:00 -08:00
Alex Hoppen
6f342e2b82 Remove static shared toolchain registry
Global state is never a good thing and we needed to modify it in tests. The design becomes a lot cleaner if we explicitly pass the toolchain registry around.
2024-01-09 17:17:31 -08:00
Alex Hoppen
3e73f11de0 Migrate ToolchainRegistry to be an actor 2024-01-09 17:17:31 -08:00
Alex Hoppen
2b9a99e3cb Increase test coverage of rename
- Invoke the rename request from multiple marker locations within a test file
- Add more test cases to test compound decl name references
2023-12-12 17:34:34 -08:00
Alex Hoppen
9c424d8740 Define sources of implementation tests inline with the test cases
Also split them up for better readability.
2023-10-26 18:23:41 -07:00
Alex Hoppen
9391d24b95 Add infrastructure to define indexed single-file workspaces inside the tests
The new approach has a few advantages over the olde TIBS-based approach:
1. The source file being tested is defined within the test case itself and not in a separate file, which makes it easier to understand the test case since the auxiliaury file doesn’t need to be opened. Finding it inside `Sources/SKTestSupport/INPUTS` is already hard for people that are not familiar with the codebase.
2. The build setup is significantly simpler since it doesn’t rely on `ninja`. It is thus easier to understand what is run during the test.
3. We can use the emoji location markers to refer to test locations, like we do for files that are opened using `TestSourceKitLSPClient.openDocument`.

This commit only migrates call hierarchy testing to the new design. If we like it, I’ll migrate the other test workspaces as well.
2023-10-24 08:42:05 -07:00
Alex Hoppen
70997dbf13 Automatically initialize the SourceKit-LSP server when creating a TestSourceKitLSPClient
Sending the `InitializeRequest` was always unnecessarily verbose. If we automatically initialize the server when creating the test client, the code becomes sufficiently concise that we can set up the client + server in the test method itself and no longer need the `setUp` methods, making the tests easier to read.
2023-10-19 17:13:49 -07:00
Alex Hoppen
ea6b8375ee Open documents using testClient.openDocument instead of constructing a DidOpenDocumentNotification
This removes a lot of boilerplate and makes the tests easier to read.
2023-10-18 17:15:03 -07:00
Alex Hoppen
4086874cf3 Implement push diagnostics in terms of DocumentDiagnosticsRequest
Instead of listening for document updates sent from `sourcekitd` and sending a `PublishDiagnosticsNotification` based on the `sourcekitd` notification, wait for a little while and then execute an internal `DocumentDiagnosticsRequest` to load diagnostics and send them to the client.

This has two advantages:
- It unifies the two diagnostic implementations
- It removes the need to keep track of semantic diagnostics in `SwiftLanguageServer`
- It gets us one step closed to opening and editing documents in `syntactic_only` mode. The only thing that is left now are semantic tokens.
2023-10-18 13:48:23 -07:00
Alex Hoppen
64ba40e5cc Make TestSourceKitLSPClient.serverOptions a static member on SourceKitServer.Options
Really, these options had nothing to do with `TestSourceKitLSPClient`, they are just the defaults that are used for all the tests.
2023-10-12 08:28:06 -07:00
Alex Hoppen
2120d124f7 Rename TestSourceKitServer to TestSourceKitClient
Really, what the class was mocking is a SourceKit-LSP client.
2023-10-12 08:28:06 -07:00