From 5fba1699bda29551b4534c9d6cf667a232a3023b Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 12 Mar 2025 14:18:43 -0700 Subject: [PATCH] Generalize `PollIndexRequest` and `BarrierRequest` into a single `SynchronizeRequest` This new request also allows us to wait for build system updates without waiting for background indexing to finish. --- Contributor Documentation/LSP Extensions.md | 41 ++++++++++++------- Documentation/Configuration File.md | 2 +- .../ConfigSchemaGen/OptionSchema.swift | 8 +++- Sources/Diagnose/IndexCommand.swift | 2 +- Sources/LanguageServerProtocol/CMakeLists.txt | 3 +- Sources/LanguageServerProtocol/Messages.swift | 3 +- .../Requests/BarrierRequest.swift | 20 --------- .../Requests/PollIndexRequest.swift | 20 --------- .../Requests/SynchronizeRequest.swift | 33 +++++++++++++++ Sources/SKOptions/ExperimentalFeatures.swift | 13 ++++++ .../IndexedSingleSwiftFileTestProject.swift | 2 +- .../SKTestSupport/MultiFileTestProject.swift | 2 +- .../SKTestSupport/SwiftPMTestProject.swift | 2 +- .../TestSourceKitLSPClient.swift | 4 +- .../MessageHandlingDependencyTracker.swift | 6 +-- Sources/SourceKitLSP/SourceKitLSPServer.swift | 21 ++++++---- .../BackgroundIndexingTests.swift | 41 ++++++++++--------- Tests/SourceKitLSPTests/DefinitionTests.swift | 2 +- .../DocumentTestDiscoveryTests.swift | 2 +- Tests/SourceKitLSPTests/RenameTests.swift | 2 +- .../SwiftPMIntegrationTests.swift | 8 ++-- .../WorkspaceSymbolsTests.swift | 2 +- .../WorkspaceTestDiscoveryTests.swift | 2 +- Tests/SourceKitLSPTests/WorkspaceTests.swift | 18 ++++---- config.schema.json | 12 +----- 25 files changed, 144 insertions(+), 127 deletions(-) delete mode 100644 Sources/LanguageServerProtocol/Requests/BarrierRequest.swift delete mode 100644 Sources/LanguageServerProtocol/Requests/PollIndexRequest.swift create mode 100644 Sources/LanguageServerProtocol/Requests/SynchronizeRequest.swift diff --git a/Contributor Documentation/LSP Extensions.md b/Contributor Documentation/LSP Extensions.md index 1c603302c..d15f3899f 100644 --- a/Contributor Documentation/LSP Extensions.md +++ b/Contributor Documentation/LSP Extensions.md @@ -546,20 +546,6 @@ export interface StructuredLogEnd { } ``` -## `workspace/_pollIndex` - -New request to wait until the index is up-to-date. - -> [!IMPORTANT] -> This request is experimental and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. - -- params: `PollIndexParams` -- result: `void` - -```ts -export interface PollIndexParams {} -``` - ## `workspace/_setOptions` New request to modify runtime options of SourceKit-LSP. @@ -678,6 +664,33 @@ export interface SourceKitOptionsResult { } ``` +## `workspace/_synchronize` + +New request from the client to the server to wait for SourceKit-LSP to handle all ongoing requests and, optionally, wait for background activity to finish. + +> [!IMPORTANT] +> This request is experimental, guarded behind the `synchronize-request` experimental feature and may be modified or removed in future versions of SourceKit-LSP without notice. Do not rely on it. + +- params: `SynchronizeParams` +- result: `void` + +```ts +export interface SynchronizeParams { + /** + * Wait for the build server to have an up-to-date build graph by sending a `workspace/waitForBuildSystemUpdates` to + * it. + */ + buildServerUpdates?: bool + + /** + * Wait for background indexing to finish and all index unit files to be loaded into indexstore-db. + * + * Implies `buildServerUpdates = true`. + */ + index?: bool +} +``` + ## `workspace/_outputPaths` New request from the client to the server to retrieve the output paths of a target (see the `buildTarget/outputPaths` BSP request). diff --git a/Documentation/Configuration File.md b/Documentation/Configuration File.md index ef10626d8..fedc0b746 100644 --- a/Documentation/Configuration File.md +++ b/Documentation/Configuration File.md @@ -54,7 +54,7 @@ The structure of the file is currently not guaranteed to be stable. Options may - `noLazy`: Prepare a target without generating object files but do not do lazy type checking and function body skipping. This uses SwiftPM's `--experimental-prepare-for-indexing-no-lazy` flag. - `enabled`: Prepare a target without generating object files. - `cancelTextDocumentRequestsOnEditAndClose: boolean`: Whether sending a `textDocument/didChange` or `textDocument/didClose` notification for a document should cancel all pending requests for that document. -- `experimentalFeatures: ("on-type-formatting"|"set-options-request"|"sourcekit-options-request"|"is-indexing-request"|"structured-logs"|"output-paths-request")[]`: Experimental features that are enabled. +- `experimentalFeatures: ("on-type-formatting"|"structured-logs")[]`: Experimental features that are enabled. - `swiftPublishDiagnosticsDebounceDuration: number`: The time that `SwiftLanguageService` should wait after an edit before starting to compute diagnostics and sending a `PublishDiagnosticsNotification`. - `workDoneProgressDebounceDuration: number`: When a task is started that should be displayed to the client as a work done progress, how many milliseconds to wait before actually starting the work done progress. This prevents flickering of the work done progress in the client for short-lived index tasks which end within this duration. - `sourcekitdRequestTimeout: number`: The maximum duration that a sourcekitd request should be allowed to execute before being declared as timed out. In general, editors should cancel requests that they are no longer interested in, but in case editors don't cancel requests, this ensures that a long-running non-cancelled request is not blocking sourcekitd and thus most semantic functionality. In particular, VS Code does not cancel the semantic tokens request, which can cause a long-running AST build that blocks sourcekitd. diff --git a/SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionSchema.swift b/SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionSchema.swift index 2ab55bd2e..64876c1db 100644 --- a/SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionSchema.swift +++ b/SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionSchema.swift @@ -150,7 +150,7 @@ struct OptionSchemaContext { guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else { return [] } - return try caseDecl.elements.map { + return try caseDecl.elements.compactMap { guard $0.parameterClause == nil else { throw ConfigSchemaGenError("Associated values in enum cases are not supported: \(caseDecl)") } @@ -168,7 +168,11 @@ struct OptionSchemaContext { } else { name = $0.name.text } - return OptionTypeSchama.Case(name: name, description: Self.extractDocComment(caseDecl.leadingTrivia)) + let description = Self.extractDocComment(caseDecl.leadingTrivia) + if description?.contains("- Note: Internal option") ?? false { + return nil + } + return OptionTypeSchama.Case(name: name, description: description) } } let typeName = node.name.text diff --git a/Sources/Diagnose/IndexCommand.swift b/Sources/Diagnose/IndexCommand.swift index 8bb52051a..20edf8b69 100644 --- a/Sources/Diagnose/IndexCommand.swift +++ b/Sources/Diagnose/IndexCommand.swift @@ -103,7 +103,7 @@ package struct IndexCommand: AsyncParsableCommand { messageHandler: messageHandler ) let start = ContinuousClock.now - _ = try await inProcessClient.send(PollIndexRequest()) + _ = try await inProcessClient.send(SynchronizeRequest(index: true)) print("Indexing finished in \(start.duration(to: .now))") if await messageHandler.hasSeenError { throw ExitCode(1) diff --git a/Sources/LanguageServerProtocol/CMakeLists.txt b/Sources/LanguageServerProtocol/CMakeLists.txt index ae9c63709..9c05561bd 100644 --- a/Sources/LanguageServerProtocol/CMakeLists.txt +++ b/Sources/LanguageServerProtocol/CMakeLists.txt @@ -27,7 +27,6 @@ add_library(LanguageServerProtocol STATIC Notifications/WorkDoneProgress.swift Requests/ApplyEditRequest.swift - Requests/BarrierRequest.swift Requests/CallHierarchyIncomingCallsRequest.swift Requests/CallHierarchyOutgoingCallsRequest.swift Requests/CallHierarchyPrepareRequest.swift @@ -72,7 +71,6 @@ add_library(LanguageServerProtocol STATIC Requests/MonikersRequest.swift Requests/OutputPathsRequest.swift Requests/PeekDocumentsRequest.swift - Requests/PollIndexRequest.swift Requests/PrepareRenameRequest.swift Requests/ReferencesRequest.swift Requests/RegisterCapabilityRequest.swift @@ -85,6 +83,7 @@ add_library(LanguageServerProtocol STATIC Requests/SignatureHelpRequest.swift Requests/SourceKitOptionsRequest.swift Requests/SymbolInfoRequest.swift + Requests/SynchronizeRequest.swift Requests/TriggerReindexRequest.swift Requests/TypeDefinitionRequest.swift Requests/TypeHierarchyPrepareRequest.swift diff --git a/Sources/LanguageServerProtocol/Messages.swift b/Sources/LanguageServerProtocol/Messages.swift index cd40db034..6318d6a08 100644 --- a/Sources/LanguageServerProtocol/Messages.swift +++ b/Sources/LanguageServerProtocol/Messages.swift @@ -17,7 +17,6 @@ /// `MessageRegistry._register()` which allows you to avoid bloating the real server implementation. public let builtinRequests: [_RequestType.Type] = [ ApplyEditRequest.self, - BarrierRequest.self, CallHierarchyIncomingCallsRequest.self, CallHierarchyOutgoingCallsRequest.self, CallHierarchyPrepareRequest.self, @@ -63,7 +62,7 @@ public let builtinRequests: [_RequestType.Type] = [ MonikersRequest.self, OutputPathsRequest.self, PeekDocumentsRequest.self, - PollIndexRequest.self, + SynchronizeRequest.self, PrepareRenameRequest.self, ReferencesRequest.self, RegisterCapabilityRequest.self, diff --git a/Sources/LanguageServerProtocol/Requests/BarrierRequest.swift b/Sources/LanguageServerProtocol/Requests/BarrierRequest.swift deleted file mode 100644 index 7e69a7492..000000000 --- a/Sources/LanguageServerProtocol/Requests/BarrierRequest.swift +++ /dev/null @@ -1,20 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -/// A no-op request that ensures all previous notifications and requests have been handled before any message -/// after the barrier request is handled. -public struct BarrierRequest: RequestType { - public static let method: String = "workspace/_barrier" - public typealias Response = VoidResponse - - public init() {} -} diff --git a/Sources/LanguageServerProtocol/Requests/PollIndexRequest.swift b/Sources/LanguageServerProtocol/Requests/PollIndexRequest.swift deleted file mode 100644 index 52f18a737..000000000 --- a/Sources/LanguageServerProtocol/Requests/PollIndexRequest.swift +++ /dev/null @@ -1,20 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -/// Poll the index for unit changes and wait for them to be registered. -/// **LSP Extension, For Testing**. -public struct PollIndexRequest: RequestType { - public static let method: String = "workspace/_pollIndex" - public typealias Response = VoidResponse - - public init() {} -} diff --git a/Sources/LanguageServerProtocol/Requests/SynchronizeRequest.swift b/Sources/LanguageServerProtocol/Requests/SynchronizeRequest.swift new file mode 100644 index 000000000..98f8101d1 --- /dev/null +++ b/Sources/LanguageServerProtocol/Requests/SynchronizeRequest.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +/// Wait for SourceKit-LSP to handle all ongoing requests and, optionally, wait for background activity to finish. +/// +/// **LSP Extension, For Testing**. +public struct SynchronizeRequest: RequestType { + public static let method: String = "workspace/_synchronize" + public typealias Response = VoidResponse + + /// Wait for the build server to have an up-to-date build graph by sending a `workspace/waitForBuildSystemUpdates` to + /// it. + public var buildServerUpdates: Bool? + + /// Wait for background indexing to finish and all index unit files to be loaded into indexstore-db. + /// + /// Implies `buildServerUpdates = true`. + public var index: Bool? + + public init(buildServerUpdates: Bool? = nil, index: Bool? = nil) { + self.buildServerUpdates = buildServerUpdates + self.index = index + } +} diff --git a/Sources/SKOptions/ExperimentalFeatures.swift b/Sources/SKOptions/ExperimentalFeatures.swift index b1ca8700e..4575940dd 100644 --- a/Sources/SKOptions/ExperimentalFeatures.swift +++ b/Sources/SKOptions/ExperimentalFeatures.swift @@ -18,17 +18,30 @@ public enum ExperimentalFeature: String, Codable, Sendable, CaseIterable { case onTypeFormatting = "on-type-formatting" /// Enable support for the `workspace/_setOptions` request. + /// + /// - Note: Internal option case setOptionsRequest = "set-options-request" /// Enable the `workspace/_sourceKitOptions` request. + /// + /// - Note: Internal option case sourceKitOptionsRequest = "sourcekit-options-request" /// Enable the `sourceKit/_isIndexing` request. + /// + /// - Note: Internal option case isIndexingRequest = "is-indexing-request" /// Indicate that the client can handle the experimental `structure` field in the `window/logMessage` notification. case structuredLogs = "structured-logs" /// Enable the `workspace/_outputPaths` request. + /// + /// - Note: Internal option case outputPathsRequest = "output-paths-request" + + /// Enable the `workspace/_synchronize` request. + /// + /// - Note: Internal option, for testing only + case synchronizeRequest = "synchronize-request" } diff --git a/Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift b/Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift index 16b241be7..d55c4e193 100644 --- a/Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift +++ b/Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift @@ -148,7 +148,7 @@ package struct IndexedSingleSwiftFileTestProject { ) // Wait for the indexstore-db to finish indexing - try await testClient.send(PollIndexRequest()) + try await testClient.send(SynchronizeRequest(index: true)) // Open the document self.fileURI = DocumentURI(testFileURL) diff --git a/Sources/SKTestSupport/MultiFileTestProject.swift b/Sources/SKTestSupport/MultiFileTestProject.swift index eaecfc842..b0e3c0d6e 100644 --- a/Sources/SKTestSupport/MultiFileTestProject.swift +++ b/Sources/SKTestSupport/MultiFileTestProject.swift @@ -244,7 +244,7 @@ package class MultiFileTestProject { } testClient.send(DidChangeWatchedFilesNotification(changes: [FileEvent(uri: uri, type: changeType)])) // Ensure that we handle the `DidChangeWatchedFilesNotification`. - try await testClient.send(BarrierRequest()) + try await testClient.send(SynchronizeRequest()) return (uri, positions) } diff --git a/Sources/SKTestSupport/SwiftPMTestProject.swift b/Sources/SKTestSupport/SwiftPMTestProject.swift index d49938f38..781a2b87c 100644 --- a/Sources/SKTestSupport/SwiftPMTestProject.swift +++ b/Sources/SKTestSupport/SwiftPMTestProject.swift @@ -237,7 +237,7 @@ package class SwiftPMTestProject: MultiFileTestProject { if pollIndex { // Wait for the indexstore-db to finish indexing - try await testClient.send(PollIndexRequest()) + try await testClient.send(SynchronizeRequest(index: true)) } } diff --git a/Sources/SKTestSupport/TestSourceKitLSPClient.swift b/Sources/SKTestSupport/TestSourceKitLSPClient.swift index b91713b87..152ddc0c1 100644 --- a/Sources/SKTestSupport/TestSourceKitLSPClient.swift +++ b/Sources/SKTestSupport/TestSourceKitLSPClient.swift @@ -27,7 +27,7 @@ import XCTest extension SourceKitLSPOptions { package static func testDefault( backgroundIndexing: Bool = true, - experimentalFeatures: Set? = nil + experimentalFeatures: Set = [], ) async throws -> SourceKitLSPOptions { let pluginPaths = try await sourceKitPluginPaths return SourceKitLSPOptions( @@ -36,7 +36,7 @@ extension SourceKitLSPOptions { servicePlugin: try pluginPaths.servicePlugin.filePath ), backgroundIndexing: backgroundIndexing, - experimentalFeatures: experimentalFeatures, + experimentalFeatures: experimentalFeatures.union([.synchronizeRequest]), swiftPublishDiagnosticsDebounceDuration: 0, workDoneProgressDebounceDuration: 0 ) diff --git a/Sources/SourceKitLSP/MessageHandlingDependencyTracker.swift b/Sources/SourceKitLSP/MessageHandlingDependencyTracker.swift index 0988f6784..4960cb9be 100644 --- a/Sources/SourceKitLSP/MessageHandlingDependencyTracker.swift +++ b/Sources/SourceKitLSP/MessageHandlingDependencyTracker.swift @@ -168,8 +168,6 @@ package enum MessageHandlingDependencyTracker: QueueBasedMessageHandlerDependenc switch request { case is ApplyEditRequest: self = .freestanding - case is BarrierRequest: - self = .globalConfigurationChange case is CallHierarchyIncomingCallsRequest: self = .freestanding case is CallHierarchyOutgoingCallsRequest: @@ -208,8 +206,6 @@ package enum MessageHandlingDependencyTracker: QueueBasedMessageHandlerDependenc self = .freestanding case is OutputPathsRequest: self = .freestanding - case is PollIndexRequest: - self = .globalConfigurationChange case is RenameRequest: // Rename might touch multiple files. Make it a global configuration change so that edits to all files that might // be affected have been processed. @@ -226,6 +222,8 @@ package enum MessageHandlingDependencyTracker: QueueBasedMessageHandlerDependenc self = .globalConfigurationChange case is SourceKitOptionsRequest: self = .freestanding + case is SynchronizeRequest: + self = .globalConfigurationChange case is TriggerReindexRequest: self = .globalConfigurationChange case is TypeHierarchySubtypesRequest: diff --git a/Sources/SourceKitLSP/SourceKitLSPServer.swift b/Sources/SourceKitLSP/SourceKitLSPServer.swift index bebe7c089..274c420f9 100644 --- a/Sources/SourceKitLSP/SourceKitLSPServer.swift +++ b/Sources/SourceKitLSP/SourceKitLSPServer.swift @@ -742,8 +742,6 @@ extension SourceKitLSPServer: QueueBasedMessageHandler { } switch request { - case let request as RequestAndReply: - await request.reply { VoidResponse() } case let request as RequestAndReply: await request.reply { try await incomingCalls(request.params) } case let request as RequestAndReply: @@ -812,8 +810,6 @@ extension SourceKitLSPServer: QueueBasedMessageHandler { await request.reply { try await self.isIndexing(request.params) } case let request as RequestAndReply: await request.reply { try await outputPaths(request.params) } - case let request as RequestAndReply: - await request.reply { try await pollIndex(request.params) } case let request as RequestAndReply: await self.handleRequest(for: request, requestHandler: self.prepareRename) case let request as RequestAndReply: @@ -828,6 +824,8 @@ extension SourceKitLSPServer: QueueBasedMessageHandler { await request.reply { try await shutdown(request.params) } case let request as RequestAndReply: await self.handleRequest(for: request, requestHandler: self.symbolInfo) + case let request as RequestAndReply: + await request.reply { try await synchronize(request.params) } case let request as RequestAndReply: await request.reply { try await triggerReindex(request.params) } case let request as RequestAndReply: @@ -2540,11 +2538,18 @@ extension SourceKitLSPServer { return types.sorted { $0.name < $1.name } } - func pollIndex(_ req: PollIndexRequest) async throws -> VoidResponse { + func synchronize(_ req: SynchronizeRequest) async throws -> VoidResponse { + guard self.options.hasExperimentalFeature(.synchronizeRequest) else { + throw ResponseError.unknown("\(SynchronizeRequest.method) indexing is an experimental request") + } for workspace in workspaces { - await workspace.buildSystemManager.waitForUpToDateBuildGraph() - await workspace.semanticIndexManager?.waitForUpToDateIndex() - workspace.uncheckedIndex?.pollForUnitChangesAndWait() + if req.buildServerUpdates ?? false || req.index ?? false { + await workspace.buildSystemManager.waitForUpToDateBuildGraph() + } + if req.index ?? false { + await workspace.semanticIndexManager?.waitForUpToDateIndex() + workspace.uncheckedIndex?.pollForUnitChangesAndWait() + } } return VoidResponse() } diff --git a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift index 6a63064e2..d7a82a76b 100644 --- a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift +++ b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift @@ -203,7 +203,7 @@ final class BackgroundIndexingTests: XCTestCase { let testClient = project.testClient Task(priority: .low) { await assertNoThrow { - try await testClient.send(PollIndexRequest()) + try await testClient.send(SynchronizeRequest(index: true)) } semaphore.signal() } @@ -438,7 +438,7 @@ final class BackgroundIndexingTests: XCTestCase { } """ ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let callsAfterEdit = try await project.testClient.send( CallHierarchyIncomingCallsRequest(item: try XCTUnwrap(prepare?.only)) @@ -498,7 +498,7 @@ final class BackgroundIndexingTests: XCTestCase { }; """ ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let callsAfterEdit = try await project.testClient.send( CallHierarchyIncomingCallsRequest(item: try XCTUnwrap(prepare?.only)) @@ -681,7 +681,7 @@ final class BackgroundIndexingTests: XCTestCase { DidChangeWatchedFilesNotification(changes: [FileEvent(uri: try project.uri(for: "LibA.swift"), type: .changed)]) ) // Ensure that we handle the `DidChangeWatchedFilesNotification`. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) // Quickly flip through all files. The way the test is designed to work is as follows: // - LibB.swift gets opened and prepared. Preparation is simulated to take a long time until both LibC.swift and @@ -701,11 +701,11 @@ final class BackgroundIndexingTests: XCTestCase { // Ensure that LibC gets opened before LibD, so that LibD is the latest document. Two open requests don't have // dependencies between each other, so SourceKit-LSP is free to execute them in parallel or re-order them without // the barrier. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) _ = try project.openDocument("LibD.swift") // Send a barrier request to ensure we have finished opening LibD before allowing the preparation of LibB to finish. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) allDocumentsOpened.signal() try libDPreparedForEditing.waitOrThrow() @@ -876,7 +876,7 @@ final class BackgroundIndexingTests: XCTestCase { WorkspaceFolder(uri: DocumentURI(project.scratchDirectory)) ] ) - try await otherClient.send(PollIndexRequest()) + try await otherClient.send(SynchronizeRequest(index: true)) } func testOpeningFileThatIsNotPartOfThePackageDoesntGenerateABuildFolderThere() async throws { @@ -919,7 +919,7 @@ final class BackgroundIndexingTests: XCTestCase { return VoidResponse() } _ = try project.openDocument("Lib.swift") - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) } func testImportPreparedModuleWithFunctionBodiesSkipped() async throws { @@ -1328,7 +1328,7 @@ final class BackgroundIndexingTests: XCTestCase { FileEvent(uri: DocumentURI(project.scratchDirectory.appendingPathComponent("Package.resolved")), type: .changed) ]) ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) XCTAssertEqual(try String(contentsOf: packageResolvedURL, encoding: .utf8), originalPackageResolvedContents) // Simulate a package update which goes as follows: @@ -1349,7 +1349,7 @@ final class BackgroundIndexingTests: XCTestCase { FileEvent(uri: DocumentURI(project.scratchDirectory.appendingPathComponent("Package.resolved")), type: .changed) ]) ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) project.testClient.send( DidChangeWatchedFilesNotification( changes: FileManager.default.findFiles( @@ -1388,7 +1388,7 @@ final class BackgroundIndexingTests: XCTestCase { FileEvent(uri: DocumentURI(project.scratchDirectory.appendingPathComponent("random.swift")), type: .created) ]) ) - _ = try await project.testClient.send(PollIndexRequest()) + _ = try await project.testClient.send(SynchronizeRequest(index: true)) } func testManualReindex() async throws { @@ -1464,7 +1464,7 @@ final class BackgroundIndexingTests: XCTestCase { ) ) project.testClient.send(DidChangeWatchedFilesNotification(changes: [FileEvent(uri: uri, type: .changed)])) - _ = try await project.testClient.send(PollIndexRequest()) + _ = try await project.testClient.send(SynchronizeRequest(index: true)) // The USR of `getInt` has changed but LibB.swift has not been re-indexed due to // https://github.com/apple/sourcekit-lsp/issues/1264. We expect to get an empty call hierarchy. @@ -1478,7 +1478,7 @@ final class BackgroundIndexingTests: XCTestCase { // After re-indexing, we expect to get a full call hierarchy again. _ = try await project.testClient.send(TriggerReindexRequest()) - _ = try await project.testClient.send(PollIndexRequest()) + _ = try await project.testClient.send(SynchronizeRequest(index: true)) let prepareAfterReindex = try await project.testClient.send( CallHierarchyPrepareRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"]) @@ -1590,7 +1590,7 @@ final class BackgroundIndexingTests: XCTestCase { project.testClient.send( DidChangeWatchedFilesNotification(changes: [FileEvent(uri: DocumentURI(symlink), type: .changed)]) ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let callsAfterRedirect = try await project.testClient.send(CallHierarchyIncomingCallsRequest(item: initialItem)) XCTAssertEqual(callsAfterRedirect?.only?.from.name, "updated()") @@ -1624,7 +1624,8 @@ final class BackgroundIndexingTests: XCTestCase { ) """, options: SourceKitLSPOptions( - backgroundPreparationMode: .enabled + backgroundPreparationMode: .enabled, + experimentalFeatures: [.synchronizeRequest] ), enableBackgroundIndexing: true ) @@ -1807,7 +1808,7 @@ final class BackgroundIndexingTests: XCTestCase { } } - func testBackgroundIndexingRunsOnPollIndexRequestEvenIfPaused() async throws { + func testBackgroundIndexingRunsOnSynchronizeRequestEvenIfPaused() async throws { let backgroundIndexingPaused = WrappedSemaphore(name: "Background indexing was paused") let hooks = Hooks( buildSystemHooks: BuildSystemHooks( @@ -1834,10 +1835,10 @@ final class BackgroundIndexingTests: XCTestCase { try await project.testClient.send(SetOptionsRequest(backgroundIndexingPaused: true)) backgroundIndexingPaused.signal() - // Running a `PollIndexRequests` elevates the background indexing tasks to `medium` priority. We thus no longer + // Running a `SynchronizeRequest` elevates the background indexing tasks to `medium` priority. We thus no longer // consider the indexing to happen in the background and hence it is not affected by the paused background indexing // state. - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let workspaceSymbolsAfterPollIndex = try await project.testClient.send(WorkspaceSymbolsRequest(query: "foo")) XCTAssertNotEqual(workspaceSymbolsAfterPollIndex, []) @@ -1891,7 +1892,7 @@ final class BackgroundIndexingTests: XCTestCase { let (uri, positions) = try project.openDocument("LibB.swift") // Even with background indexing disabled, we should prepare LibB and eventually get hover results for it. - // We shouldn't use `PollIndexRequest` here because that elevates the background indexing priority and thereby + // We shouldn't use `SynchronizeRequest` here because that elevates the background indexing priority and thereby // unpauses background indexing. try await repeatUntilExpectedResult { return try await project.testClient.send( @@ -2136,7 +2137,7 @@ final class BackgroundIndexingTests: XCTestCase { buildServer: BuildServer.self, enableBackgroundIndexing: true ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let symbols = try await project.testClient.send(WorkspaceSymbolsRequest(query: "myTestFunc")) XCTAssertEqual( diff --git a/Tests/SourceKitLSPTests/DefinitionTests.swift b/Tests/SourceKitLSPTests/DefinitionTests.swift index 6f06c0d8b..9f9d037cc 100644 --- a/Tests/SourceKitLSPTests/DefinitionTests.swift +++ b/Tests/SourceKitLSPTests/DefinitionTests.swift @@ -496,7 +496,7 @@ class DefinitionTests: XCTestCase { ) // Ensure that the DidChangeWatchedFilesNotification is handled before we continue. - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let resultAfterFileMove = try await project.testClient.send( DefinitionRequest(textDocument: TextDocumentIdentifier(callerUri), position: callerPositions["2️⃣"]) diff --git a/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift b/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift index af95cfc8d..6a9e44ddb 100644 --- a/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift +++ b/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift @@ -157,7 +157,7 @@ final class DocumentTestDiscoveryTests: XCTestCase { ) try await SwiftPMTestProject.build(at: project.scratchDirectory) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) // After indexing, we know that `LooksLikeTestCaseButIsNot` does not inherit from `XCTestCase` and we don't report any tests. let indexBasedTests = try await project.testClient.send( diff --git a/Tests/SourceKitLSPTests/RenameTests.swift b/Tests/SourceKitLSPTests/RenameTests.swift index bd210209a..82e0bde8d 100644 --- a/Tests/SourceKitLSPTests/RenameTests.swift +++ b/Tests/SourceKitLSPTests/RenameTests.swift @@ -1140,7 +1140,7 @@ final class RenameTests: XCTestCase { ]) ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let resultAfterFileMove = try await project.testClient.send( RenameRequest(textDocument: TextDocumentIdentifier(callerUri), position: callerPositions["3️⃣"], newName: "bar") diff --git a/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift b/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift index d1e6294ab..e864b6e90 100644 --- a/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift +++ b/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift @@ -142,7 +142,7 @@ final class SwiftPMIntegrationTests: XCTestCase { ) // Ensure that the DidChangeWatchedFilesNotification is handled before we continue. - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let completions = try await project.testClient.send( CompletionRequest(textDocument: TextDocumentIdentifier(newFileUri), position: newFilePositions["2️⃣"]) @@ -220,7 +220,7 @@ final class SwiftPMIntegrationTests: XCTestCase { let (uri, positions) = try project.openDocument("b.swift") - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let result = try await project.testClient.send( CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"]) @@ -531,7 +531,7 @@ final class SwiftPMIntegrationTests: XCTestCase { let topGenerated = 2 """ ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) // Expect that the position has been updated in the dependency try await repeatUntilExpectedResult { @@ -550,7 +550,7 @@ final class SwiftPMIntegrationTests: XCTestCase { let targetGenerated = 2 """ ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) // Expect that the position has been updated in the dependency try await repeatUntilExpectedResult { diff --git a/Tests/SourceKitLSPTests/WorkspaceSymbolsTests.swift b/Tests/SourceKitLSPTests/WorkspaceSymbolsTests.swift index bc35bd036..6b9fd2c61 100644 --- a/Tests/SourceKitLSPTests/WorkspaceSymbolsTests.swift +++ b/Tests/SourceKitLSPTests/WorkspaceSymbolsTests.swift @@ -64,7 +64,7 @@ class WorkspaceSymbolsTests: XCTestCase { enableBackgroundIndexing: true ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let response = try await project.testClient.send(WorkspaceSymbolsRequest(query: "funcFrom")) // Ideally, the item from the current package (PackageB) should be returned before the item from PackageA diff --git a/Tests/SourceKitLSPTests/WorkspaceTestDiscoveryTests.swift b/Tests/SourceKitLSPTests/WorkspaceTestDiscoveryTests.swift index 02b87793c..9b68c01e7 100644 --- a/Tests/SourceKitLSPTests/WorkspaceTestDiscoveryTests.swift +++ b/Tests/SourceKitLSPTests/WorkspaceTestDiscoveryTests.swift @@ -934,7 +934,7 @@ final class WorkspaceTestDiscoveryTests: XCTestCase { DidChangeWatchedFilesNotification(changes: [FileEvent(uri: project.fileURI, type: .changed)]) ) // Ensure that we handle the `DidChangeWatchedFilesNotification`. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) let testsAfterEdit = try await project.testClient.send(WorkspaceTestsRequest()) // We know from the semantic index that NotQuiteTest does not inherit from XCTestCase, so we should not include it. diff --git a/Tests/SourceKitLSPTests/WorkspaceTests.swift b/Tests/SourceKitLSPTests/WorkspaceTests.swift index e8b750c6e..427cbc12c 100644 --- a/Tests/SourceKitLSPTests/WorkspaceTests.swift +++ b/Tests/SourceKitLSPTests/WorkspaceTests.swift @@ -83,7 +83,7 @@ final class WorkspaceTests: XCTestCase { }, enableBackgroundIndexing: true ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let (bUri, bPositions) = try project.openDocument("execB.swift") @@ -276,7 +276,7 @@ final class WorkspaceTests: XCTestCase { let (uri, positions) = try project.openDocument("execA.swift") - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let otherCompletions = try await project.testClient.send( CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"]) @@ -367,7 +367,7 @@ final class WorkspaceTests: XCTestCase { enableBackgroundIndexing: true ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let (bUri, bPositions) = try project.openDocument("execB.swift") @@ -407,7 +407,7 @@ final class WorkspaceTests: XCTestCase { let (aUri, aPositions) = try project.openDocument("execA.swift") - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let otherCompletions = try await project.testClient.send( CompletionRequest(textDocument: TextDocumentIdentifier(aUri), position: aPositions["1️⃣"]) @@ -557,7 +557,7 @@ final class WorkspaceTests: XCTestCase { ]) ) // Ensure that the DidChangeWatchedFilesNotification is handled before we continue. - _ = try await project.testClient.send(BarrierRequest()) + _ = try await project.testClient.send(SynchronizeRequest()) // After updating PackageB/Package.swift, PackageB can provide proper build settings for MyExec/main.swift and // thus workspace membership should switch to PackageB. @@ -707,7 +707,7 @@ final class WorkspaceTests: XCTestCase { ) ) - try await project.testClient.send(PollIndexRequest()) + try await project.testClient.send(SynchronizeRequest(index: true)) let postChangeWorkspaceResponse = try await project.testClient.send( CompletionRequest( @@ -1161,7 +1161,7 @@ final class WorkspaceTests: XCTestCase { project.testClient.send(DidChangeWatchedFilesNotification(changes: [FileEvent(uri: baseLibUri, type: .changed)])) // Ensure that we handle the `DidChangeWatchedFilesNotification`. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) didChangeBaseLib.value = true project.testClient.send( @@ -1280,7 +1280,7 @@ final class WorkspaceTests: XCTestCase { project.testClient.send(DidChangeWatchedFilesNotification(changes: [FileEvent(uri: baseLibUri, type: .changed)])) // Ensure that we handle the `DidChangeWatchedFilesNotification`. - try await project.testClient.send(BarrierRequest()) + try await project.testClient.send(SynchronizeRequest()) didChangeBaseLib.value = true let triggerPrepare = try await project.testClient.send( @@ -1357,7 +1357,7 @@ final class WorkspaceTests: XCTestCase { options: .testDefault(experimentalFeatures: [.sourceKitOptionsRequest]), workspaceFolders: [WorkspaceFolder(uri: DocumentURI(scratchDirectory), name: nil)] ) - try await testClient.send(PollIndexRequest()) + try await testClient.send(SynchronizeRequest(index: true)) // Check that we can infer build settings for the header from its main file. indexstore-db stores this main file // path as `/private/tmp` while the build system only knows about it as `/tmp`. diff --git a/config.schema.json b/config.schema.json index 317a528bd..2fb4b7ba7 100644 --- a/config.schema.json +++ b/config.schema.json @@ -70,19 +70,11 @@ "items" : { "enum" : [ "on-type-formatting", - "set-options-request", - "sourcekit-options-request", - "is-indexing-request", - "structured-logs", - "output-paths-request" + "structured-logs" ], "markdownEnumDescriptions" : [ "Enable support for the `textDocument/onTypeFormatting` request.", - "Enable support for the `workspace/_setOptions` request.", - "Enable the `workspace/_sourceKitOptions` request.", - "Enable the `sourceKit/_isIndexing` request.", - "Indicate that the client can handle the experimental `structure` field in the `window/logMessage` notification.", - "Enable the `workspace/_outputPaths` request." + "Indicate that the client can handle the experimental `structure` field in the `window/logMessage` notification." ], "type" : "string" },