From 31b1909ce1c7302244eb822a043aed5ed6895de4 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Wed, 15 Jan 2025 15:57:21 -0800 Subject: [PATCH] Allow injection of build systems into `SourceKitLSP` This allows us to clean up the creation of `TestBuildSystem` a little bit because the tests can create `TestBuildSystem` instead of retrieving it from the `BuildSystemManager`. rdar://142906050 --- .../BuildSystemManager.swift | 37 +++++--------- .../BuildSystemTestHooks.swift | 20 ++++++-- .../BuiltInBuildSystemAdapter.swift | 17 ++----- .../DetermineBuildSystem.swift | 7 ++- .../InProcessSourceKitLSPClient.swift | 21 +++----- .../SKTestSupport/MultiFileTestProject.swift | 4 +- .../SKTestSupport/SwiftPMTestProject.swift | 4 +- .../TestSourceKitLSPClient.swift | 4 +- .../Clang/ClangLanguageService.swift | 2 +- .../DocumentationLanguageService.swift | 2 +- Sources/SourceKitLSP/LanguageService.swift | 2 +- Sources/SourceKitLSP/SourceKitLSPServer.swift | 33 ++++++++----- .../Swift/SwiftLanguageService.swift | 6 +-- Sources/SourceKitLSP/TestHooks.swift | 16 +++---- Sources/SourceKitLSP/Workspace.swift | 14 +++--- Sources/sourcekit-lsp/SourceKitLSP.swift | 2 +- .../BuildSystemManagerTests.swift | 48 ++++++++++++------- .../FallbackBuildSettingsTests.swift | 6 +-- .../SwiftPMBuildSystemTests.swift | 34 ++++++------- .../BackgroundIndexingTests.swift | 34 ++++++------- .../SourceKitLSPTests/BuildSystemTests.swift | 20 ++++++-- .../PullDiagnosticsTests.swift | 10 ++-- .../SemanticTokensTests.swift | 4 +- .../SwiftPMIntegrationTests.swift | 8 ++-- .../PluginSwiftPMTestProject.swift | 2 +- 25 files changed, 192 insertions(+), 165 deletions(-) diff --git a/Sources/BuildSystemIntegration/BuildSystemManager.swift b/Sources/BuildSystemIntegration/BuildSystemManager.swift index 6f764203..8d8030c1 100644 --- a/Sources/BuildSystemIntegration/BuildSystemManager.swift +++ b/Sources/BuildSystemIntegration/BuildSystemManager.swift @@ -145,7 +145,7 @@ private extension BuildSystemSpec { private static func createBuiltInBuildSystemAdapter( projectRoot: URL, messagesToSourceKitLSPHandler: any MessageHandler, - buildSystemTestHooks: BuildSystemTestHooks, + buildSystemHooks: BuildSystemHooks, _ createBuildSystem: @Sendable (_ connectionToSourceKitLSP: any Connection) async throws -> BuiltInBuildSystem? ) async -> BuildSystemAdapter? { let connectionToSourceKitLSP = LocalConnection( @@ -164,7 +164,7 @@ private extension BuildSystemSpec { let buildSystemAdapter = BuiltInBuildSystemAdapter( underlyingBuildSystem: buildSystem, connectionToSourceKitLSP: connectionToSourceKitLSP, - buildSystemTestHooks: buildSystemTestHooks + buildSystemHooks: buildSystemHooks ) let connectionToBuildSystem = LocalConnection( receiverName: "\(type(of: buildSystem)) for \(projectRoot.lastPathComponent)" @@ -178,7 +178,7 @@ private extension BuildSystemSpec { func createBuildSystemAdapter( toolchainRegistry: ToolchainRegistry, options: SourceKitLSPOptions, - buildSystemTestHooks testHooks: BuildSystemTestHooks, + buildSystemHooks: BuildSystemHooks, messagesToSourceKitLSPHandler: any MessageHandler ) async -> BuildSystemAdapter? { switch self.kind { @@ -199,7 +199,7 @@ private extension BuildSystemSpec { return await Self.createBuiltInBuildSystemAdapter( projectRoot: projectRoot, messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler, - buildSystemTestHooks: testHooks + buildSystemHooks: buildSystemHooks ) { connectionToSourceKitLSP in CompilationDatabaseBuildSystem( projectRoot: projectRoot, @@ -214,26 +214,26 @@ private extension BuildSystemSpec { return await Self.createBuiltInBuildSystemAdapter( projectRoot: projectRoot, messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler, - buildSystemTestHooks: testHooks + buildSystemHooks: buildSystemHooks ) { connectionToSourceKitLSP in try await SwiftPMBuildSystem( projectRoot: projectRoot, toolchainRegistry: toolchainRegistry, options: options, connectionToSourceKitLSP: connectionToSourceKitLSP, - testHooks: testHooks.swiftPMTestHooks + testHooks: buildSystemHooks.swiftPMTestHooks ) } #else return nil #endif - case .testBuildSystem: + case .injected(let injector): return await Self.createBuiltInBuildSystemAdapter( projectRoot: projectRoot, messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler, - buildSystemTestHooks: testHooks + buildSystemHooks: buildSystemHooks ) { connectionToSourceKitLSP in - TestBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP) + await injector.createBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP) } } } @@ -275,19 +275,6 @@ package actor BuildSystemManager: QueueBasedMessageHandler { } } - /// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil` - /// - /// - Important: For testing purposes only. - package var testBuildSystem: TestBuildSystem? { - get async { - switch buildSystemAdapter { - case .builtIn(let builtInBuildSystemAdapter, _): return await builtInBuildSystemAdapter.testBuildSystem - case .external: return nil - case nil: return nil - } - } - } - /// Provider of file to main file mappings. private var mainFilesProvider: MainFilesProvider? @@ -367,7 +354,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler { toolchainRegistry: ToolchainRegistry, options: SourceKitLSPOptions, connectionToClient: BuildSystemManagerConnectionToClient, - buildSystemTestHooks: BuildSystemTestHooks + buildSystemHooks: BuildSystemHooks ) async { self.toolchainRegistry = toolchainRegistry self.options = options @@ -376,7 +363,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler { self.buildSystemAdapter = await buildSystemSpec?.createBuildSystemAdapter( toolchainRegistry: toolchainRegistry, options: options, - buildSystemTestHooks: buildSystemTestHooks, + buildSystemHooks: buildSystemHooks, messagesToSourceKitLSPHandler: WeakMessageHandler(self) ) @@ -432,7 +419,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler { let adapter = BuiltInBuildSystemAdapter( underlyingBuildSystem: legacyBuildServer, connectionToSourceKitLSP: legacyBuildServer.connectionToSourceKitLSP, - buildSystemTestHooks: buildSystemTestHooks + buildSystemHooks: buildSystemHooks ) let connectionToBuildSystem = LocalConnection(receiverName: "Legacy BSP server") connectionToBuildSystem.start(handler: adapter) diff --git a/Sources/BuildSystemIntegration/BuildSystemTestHooks.swift b/Sources/BuildSystemIntegration/BuildSystemTestHooks.swift index 4b469906..45a3d177 100644 --- a/Sources/BuildSystemIntegration/BuildSystemTestHooks.swift +++ b/Sources/BuildSystemIntegration/BuildSystemTestHooks.swift @@ -12,8 +12,10 @@ #if compiler(>=6) package import LanguageServerProtocol +package import Foundation #else import LanguageServerProtocol +import Foundation #endif package struct SwiftPMTestHooks: Sendable { @@ -29,19 +31,29 @@ package struct SwiftPMTestHooks: Sendable { } } -package struct BuildSystemTestHooks: Sendable { +/// When running SourceKit-LSP in-process, allows the creator of `SourceKitLSPServer` to create the build system instead +/// of SourceKit-LSP creating build systems as needed. +package protocol BuildSystemInjector: Sendable { + func createBuildSystem(projectRoot: URL, connectionToSourceKitLSP: any Connection) async -> BuiltInBuildSystem +} + +package struct BuildSystemHooks: Sendable { package var swiftPMTestHooks: SwiftPMTestHooks /// A hook that will be executed before a request is handled by a `BuiltInBuildSystem`. /// /// This allows requests to be artificially delayed. - package var handleRequest: (@Sendable (any RequestType) async -> Void)? + package var preHandleRequest: (@Sendable (any RequestType) async -> Void)? + + package var buildSystemInjector: BuildSystemInjector? package init( swiftPMTestHooks: SwiftPMTestHooks = SwiftPMTestHooks(), - handleRequest: (@Sendable (any RequestType) async -> Void)? = nil + preHandleRequest: (@Sendable (any RequestType) async -> Void)? = nil, + buildSystemInjector: BuildSystemInjector? = nil ) { self.swiftPMTestHooks = swiftPMTestHooks - self.handleRequest = handleRequest + self.preHandleRequest = preHandleRequest + self.buildSystemInjector = buildSystemInjector } } diff --git a/Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift b/Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift index 8c86974c..eed4460e 100644 --- a/Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift +++ b/Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift @@ -30,7 +30,7 @@ package struct BuildSystemSpec { case buildServer case compilationDatabase case swiftPM - case testBuildSystem + case injected(BuildSystemInjector) } package var kind: Kind @@ -59,25 +59,18 @@ actor BuiltInBuildSystemAdapter: QueueBasedMessageHandler { /// The connection with which messages are sent to `BuildSystemManager`. private let connectionToSourceKitLSP: LocalConnection - private let buildSystemTestHooks: BuildSystemTestHooks - - /// If the underlying build system is a `TestBuildSystem`, return it. Otherwise, `nil` - /// - /// - Important: For testing purposes only. - var testBuildSystem: TestBuildSystem? { - return underlyingBuildSystem as? TestBuildSystem - } + private let buildSystemHooks: BuildSystemHooks /// Create a `BuiltInBuildSystemAdapter` form an existing `BuiltInBuildSystem` and connection to communicate messages /// from the build system to SourceKit-LSP. init( underlyingBuildSystem: BuiltInBuildSystem, connectionToSourceKitLSP: LocalConnection, - buildSystemTestHooks: BuildSystemTestHooks + buildSystemHooks: BuildSystemHooks ) { self.underlyingBuildSystem = underlyingBuildSystem self.connectionToSourceKitLSP = connectionToSourceKitLSP - self.buildSystemTestHooks = buildSystemTestHooks + self.buildSystemHooks = buildSystemHooks } deinit { @@ -124,7 +117,7 @@ actor BuiltInBuildSystemAdapter: QueueBasedMessageHandler { reply: @Sendable @escaping (LSPResult) -> Void ) async { let request = RequestAndReply(request, reply: reply) - await buildSystemTestHooks.handleRequest?(request.params) + await buildSystemHooks.preHandleRequest?(request.params) switch request { case let request as RequestAndReply: await request.reply { VoidResponse() } diff --git a/Sources/BuildSystemIntegration/DetermineBuildSystem.swift b/Sources/BuildSystemIntegration/DetermineBuildSystem.swift index 7dd35706..69d3eb96 100644 --- a/Sources/BuildSystemIntegration/DetermineBuildSystem.swift +++ b/Sources/BuildSystemIntegration/DetermineBuildSystem.swift @@ -36,8 +36,13 @@ import struct TSCBasic.AbsolutePath /// Returns `nil` if no build system can handle this workspace folder. package func determineBuildSystem( forWorkspaceFolder workspaceFolder: DocumentURI, - options: SourceKitLSPOptions + options: SourceKitLSPOptions, + hooks: BuildSystemHooks ) -> BuildSystemSpec? { + if let workspaceURL = workspaceFolder.fileURL, let buildSystemInjector = hooks.buildSystemInjector { + return BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: workspaceURL) + } + var buildSystemPreference: [WorkspaceType] = [ .buildServer, .swiftPM, .compilationDatabase, ] diff --git a/Sources/InProcessClient/InProcessSourceKitLSPClient.swift b/Sources/InProcessClient/InProcessSourceKitLSPClient.swift index 52b6ca34..3c8cd3ab 100644 --- a/Sources/InProcessClient/InProcessSourceKitLSPClient.swift +++ b/Sources/InProcessClient/InProcessSourceKitLSPClient.swift @@ -10,30 +10,22 @@ // //===----------------------------------------------------------------------===// -#if compiler(>=6) import BuildSystemIntegration public import Foundation public import LanguageServerProtocol import LanguageServerProtocolExtensions -package import SKOptions -import SourceKitLSP import SwiftExtensions -import ToolchainRegistry import TSCExtensions +import ToolchainRegistry import struct TSCBasic.AbsolutePath + +#if compiler(>=6) +package import SKOptions +package import SourceKitLSP #else -import BuildSystemIntegration -import Foundation -import LanguageServerProtocol -import LanguageServerProtocolExtensions import SKOptions import SourceKitLSP -import SwiftExtensions -import ToolchainRegistry -import TSCExtensions - -import struct TSCBasic.AbsolutePath #endif /// Launches a `SourceKitLSPServer` in-process and allows sending messages to it. @@ -63,6 +55,7 @@ public final class InProcessSourceKitLSPClient: Sendable { package init( toolchainPath: URL?, options: SourceKitLSPOptions = SourceKitLSPOptions(), + hooks: Hooks = Hooks(), capabilities: ClientCapabilities = ClientCapabilities(), workspaceFolders: [WorkspaceFolder], messageHandler: any MessageHandler @@ -72,7 +65,7 @@ public final class InProcessSourceKitLSPClient: Sendable { client: serverToClientConnection, toolchainRegistry: ToolchainRegistry(installPath: toolchainPath), options: options, - testHooks: TestHooks(), + hooks: hooks, onExit: { serverToClientConnection.close() } diff --git a/Sources/SKTestSupport/MultiFileTestProject.swift b/Sources/SKTestSupport/MultiFileTestProject.swift index 2f5ecb23..c921bfaf 100644 --- a/Sources/SKTestSupport/MultiFileTestProject.swift +++ b/Sources/SKTestSupport/MultiFileTestProject.swift @@ -133,7 +133,7 @@ package class MultiFileTestProject { initializationOptions: LSPAny? = nil, capabilities: ClientCapabilities = ClientCapabilities(), options: SourceKitLSPOptions = .testDefault(), - testHooks: TestHooks = TestHooks(), + hooks: Hooks = Hooks(), enableBackgroundIndexing: Bool = false, usePullDiagnostics: Bool = true, preInitialization: ((TestSourceKitLSPClient) -> Void)? = nil, @@ -145,7 +145,7 @@ package class MultiFileTestProject { self.testClient = try await TestSourceKitLSPClient( options: options, - testHooks: testHooks, + hooks: hooks, initializationOptions: initializationOptions, capabilities: capabilities, usePullDiagnostics: usePullDiagnostics, diff --git a/Sources/SKTestSupport/SwiftPMTestProject.swift b/Sources/SKTestSupport/SwiftPMTestProject.swift index a582a862..1d88b6e9 100644 --- a/Sources/SKTestSupport/SwiftPMTestProject.swift +++ b/Sources/SKTestSupport/SwiftPMTestProject.swift @@ -197,7 +197,7 @@ package class SwiftPMTestProject: MultiFileTestProject { initializationOptions: LSPAny? = nil, capabilities: ClientCapabilities = ClientCapabilities(), options: SourceKitLSPOptions = .testDefault(), - testHooks: TestHooks = TestHooks(), + hooks: Hooks = Hooks(), enableBackgroundIndexing: Bool = false, usePullDiagnostics: Bool = true, pollIndex: Bool = true, @@ -238,7 +238,7 @@ package class SwiftPMTestProject: MultiFileTestProject { initializationOptions: initializationOptions, capabilities: capabilities, options: options, - testHooks: testHooks, + hooks: hooks, enableBackgroundIndexing: enableBackgroundIndexing, usePullDiagnostics: usePullDiagnostics, preInitialization: preInitialization, diff --git a/Sources/SKTestSupport/TestSourceKitLSPClient.swift b/Sources/SKTestSupport/TestSourceKitLSPClient.swift index fc31ce7b..3b1ee898 100644 --- a/Sources/SKTestSupport/TestSourceKitLSPClient.swift +++ b/Sources/SKTestSupport/TestSourceKitLSPClient.swift @@ -146,7 +146,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable { /// needed. package init( options: SourceKitLSPOptions = .testDefault(), - testHooks: TestHooks = TestHooks(), + hooks: Hooks = Hooks(), initialize: Bool = true, initializationOptions: LSPAny? = nil, capabilities: ClientCapabilities = ClientCapabilities(), @@ -177,7 +177,7 @@ package final class TestSourceKitLSPClient: MessageHandler, Sendable { client: serverToClientConnection, toolchainRegistry: ToolchainRegistry.forTesting, options: options, - testHooks: testHooks, + hooks: hooks, onExit: { serverToClientConnection.close() } diff --git a/Sources/SourceKitLSP/Clang/ClangLanguageService.swift b/Sources/SourceKitLSP/Clang/ClangLanguageService.swift index 3a713c99..4271a3f8 100644 --- a/Sources/SourceKitLSP/Clang/ClangLanguageService.swift +++ b/Sources/SourceKitLSP/Clang/ClangLanguageService.swift @@ -113,7 +113,7 @@ actor ClangLanguageService: LanguageService, MessageHandler { sourceKitLSPServer: SourceKitLSPServer, toolchain: Toolchain, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, workspace: Workspace ) async throws { guard let clangdPath = toolchain.clangd else { diff --git a/Sources/SourceKitLSP/Documentation/DocumentationLanguageService.swift b/Sources/SourceKitLSP/Documentation/DocumentationLanguageService.swift index e1aa6afd..0803acf4 100644 --- a/Sources/SourceKitLSP/Documentation/DocumentationLanguageService.swift +++ b/Sources/SourceKitLSP/Documentation/DocumentationLanguageService.swift @@ -29,7 +29,7 @@ package actor DocumentationLanguageService: LanguageService, Sendable { sourceKitLSPServer: SourceKitLSPServer, toolchain: Toolchain, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, workspace: Workspace ) async throws {} diff --git a/Sources/SourceKitLSP/LanguageService.swift b/Sources/SourceKitLSP/LanguageService.swift index aecc2c55..643c531f 100644 --- a/Sources/SourceKitLSP/LanguageService.swift +++ b/Sources/SourceKitLSP/LanguageService.swift @@ -109,7 +109,7 @@ package protocol LanguageService: AnyObject, Sendable { sourceKitLSPServer: SourceKitLSPServer, toolchain: Toolchain, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, workspace: Workspace ) async throws diff --git a/Sources/SourceKitLSP/SourceKitLSPServer.swift b/Sources/SourceKitLSP/SourceKitLSPServer.swift index 3bf25270..708403bd 100644 --- a/Sources/SourceKitLSP/SourceKitLSPServer.swift +++ b/Sources/SourceKitLSP/SourceKitLSPServer.swift @@ -82,7 +82,7 @@ package actor SourceKitLSPServer { var options: SourceKitLSPOptions - let testHooks: TestHooks + let hooks: Hooks let toolchainRegistry: ToolchainRegistry @@ -154,12 +154,12 @@ package actor SourceKitLSPServer { client: Connection, toolchainRegistry: ToolchainRegistry, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, onExit: @escaping () -> Void = {} ) { self.toolchainRegistry = toolchainRegistry self.options = options - self.testHooks = testHooks + self.hooks = hooks self.onExit = onExit self.client = client @@ -218,7 +218,13 @@ package actor SourceKitLSPServer { // was added to it and thus currently doesn't know that it can handle that file. In that case, we shouldn't open // a new workspace for the same root. Instead, the existing workspace's build system needs to be reloaded. let uri = DocumentURI(url) - guard let buildSystemSpec = determineBuildSystem(forWorkspaceFolder: uri, options: self.options) else { + guard + let buildSystemSpec = determineBuildSystem( + forWorkspaceFolder: uri, + options: self.options, + hooks: hooks.buildSystemHooks + ) + else { continue } guard !projectRoots.contains(buildSystemSpec.projectRoot) else { @@ -442,12 +448,12 @@ package actor SourceKitLSPServer { } // Start a new service. - return await orLog("failed to start language service", level: .error) { [options = workspace.options, testHooks] in + return await orLog("failed to start language service", level: .error) { [options = workspace.options, hooks] in let service = try await serverType.serverType.init( sourceKitLSPServer: self, toolchain: toolchain, options: options, - testHooks: testHooks, + hooks: hooks, workspace: workspace ) @@ -656,7 +662,7 @@ extension SourceKitLSPServer: QueueBasedMessageHandler { } } - await self.testHooks.handleRequest?(params) + await self.hooks.preHandleRequest?(params) let startDate = Date() @@ -826,7 +832,6 @@ extension SourceKitLSPServer { logger.log("Cannot open workspace before server is initialized") throw NoCapabilityRegistryError() } - let testHooks = self.testHooks let options = SourceKitLSPOptions.merging( base: self.options, override: SourceKitLSPOptions( @@ -846,7 +851,7 @@ extension SourceKitLSPServer { buildSystemSpec: buildSystemSpec, toolchainRegistry: self.toolchainRegistry, options: options, - testHooks: testHooks, + hooks: hooks, indexTaskScheduler: indexTaskScheduler ) return workspace @@ -857,7 +862,11 @@ extension SourceKitLSPServer { private func createWorkspaceWithInferredBuildSystem(workspaceFolder: DocumentURI) async throws -> Workspace { return try await self.createWorkspace( workspaceFolder: workspaceFolder, - buildSystemSpec: determineBuildSystem(forWorkspaceFolder: workspaceFolder, options: self.options) + buildSystemSpec: determineBuildSystem( + forWorkspaceFolder: workspaceFolder, + options: options, + hooks: hooks.buildSystemHooks + ) ) } @@ -917,7 +926,7 @@ extension SourceKitLSPServer { logger.log("Initialized SourceKit-LSP") logger.logFullObjectInMultipleLogMessages(header: "SourceKit-LSP Options", options.loggingProxy) - await workspaceQueue.async { [testHooks] in + await workspaceQueue.async { [hooks] in if let workspaceFolders = req.workspaceFolders { self.workspacesAndIsImplicit += await workspaceFolders.asyncCompactMap { workspaceFolder in await orLog("Creating workspace from workspaceFolders") { @@ -954,7 +963,7 @@ extension SourceKitLSPServer { buildSystemSpec: nil, toolchainRegistry: self.toolchainRegistry, options: options, - testHooks: testHooks, + hooks: hooks, indexTaskScheduler: self.indexTaskScheduler ) diff --git a/Sources/SourceKitLSP/Swift/SwiftLanguageService.swift b/Sources/SourceKitLSP/Swift/SwiftLanguageService.swift index 515ffd95..56a1cfb3 100644 --- a/Sources/SourceKitLSP/Swift/SwiftLanguageService.swift +++ b/Sources/SourceKitLSP/Swift/SwiftLanguageService.swift @@ -129,7 +129,7 @@ package actor SwiftLanguageService: LanguageService, Sendable { let capabilityRegistry: CapabilityRegistry - let testHooks: TestHooks + let hooks: Hooks let options: SourceKitLSPOptions @@ -217,7 +217,7 @@ package actor SwiftLanguageService: LanguageService, Sendable { sourceKitLSPServer: SourceKitLSPServer, toolchain: Toolchain, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, workspace: Workspace ) async throws { guard let sourcekitd = toolchain.sourcekitd else { return nil } @@ -240,7 +240,7 @@ package actor SwiftLanguageService: LanguageService, Sendable { ) self.capabilityRegistry = workspace.capabilityRegistry self.semanticIndexManager = workspace.semanticIndexManager - self.testHooks = testHooks + self.hooks = hooks self.state = .connected self.options = options diff --git a/Sources/SourceKitLSP/TestHooks.swift b/Sources/SourceKitLSP/TestHooks.swift index 15ba6074..c2259820 100644 --- a/Sources/SourceKitLSP/TestHooks.swift +++ b/Sources/SourceKitLSP/TestHooks.swift @@ -31,27 +31,27 @@ import struct TSCBasic.RelativePath #endif /// Closures can be used to inspect or modify internal behavior in SourceKit-LSP. -public struct TestHooks: Sendable { +public struct Hooks: Sendable { package var indexTestHooks: IndexTestHooks - package var buildSystemTestHooks: BuildSystemTestHooks + package var buildSystemHooks: BuildSystemHooks /// A hook that will be executed before a request is handled. /// /// This allows requests to be artificially delayed. - package var handleRequest: (@Sendable (any RequestType) async -> Void)? + package var preHandleRequest: (@Sendable (any RequestType) async -> Void)? public init() { - self.init(indexTestHooks: IndexTestHooks(), buildSystemTestHooks: BuildSystemTestHooks(), handleRequest: nil) + self.init(indexTestHooks: IndexTestHooks(), buildSystemHooks: BuildSystemHooks()) } package init( indexTestHooks: IndexTestHooks = IndexTestHooks(), - buildSystemTestHooks: BuildSystemTestHooks = BuildSystemTestHooks(), - handleRequest: (@Sendable (any RequestType) async -> Void)? = nil + buildSystemHooks: BuildSystemHooks = BuildSystemHooks(), + preHandleRequest: (@Sendable (any RequestType) async -> Void)? = nil ) { self.indexTestHooks = indexTestHooks - self.buildSystemTestHooks = buildSystemTestHooks - self.handleRequest = handleRequest + self.buildSystemHooks = buildSystemHooks + self.preHandleRequest = preHandleRequest } } diff --git a/Sources/SourceKitLSP/Workspace.swift b/Sources/SourceKitLSP/Workspace.swift index dba6ec9e..f8e522b9 100644 --- a/Sources/SourceKitLSP/Workspace.swift +++ b/Sources/SourceKitLSP/Workspace.swift @@ -161,7 +161,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { rootUri: DocumentURI?, capabilityRegistry: CapabilityRegistry, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, buildSystemManager: BuildSystemManager, index uncheckedIndex: UncheckedIndex?, indexDelegate: SourceKitIndexDelegate?, @@ -183,7 +183,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { index: uncheckedIndex, buildSystemManager: buildSystemManager, updateIndexStoreTimeout: options.indexOrDefault.updateIndexStoreTimeoutOrDefault, - testHooks: testHooks.indexTestHooks, + testHooks: hooks.indexTestHooks, indexTaskScheduler: indexTaskScheduler, logMessageToIndexLog: { [weak sourceKitLSPServer] in sourceKitLSPServer?.logMessageToIndexLog(taskID: $0, message: $1) @@ -227,7 +227,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { buildSystemSpec: BuildSystemSpec?, toolchainRegistry: ToolchainRegistry, options: SourceKitLSPOptions, - testHooks: TestHooks, + hooks: Hooks, indexTaskScheduler: TaskScheduler ) async { struct ConnectionToClient: BuildSystemManagerConnectionToClient { @@ -278,7 +278,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { toolchainRegistry: toolchainRegistry, options: options, connectionToClient: ConnectionToClient(sourceKitLSPServer: sourceKitLSPServer), - buildSystemTestHooks: testHooks.buildSystemTestHooks + buildSystemHooks: hooks.buildSystemHooks ) logger.log( @@ -323,7 +323,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { rootUri: rootUri, capabilityRegistry: capabilityRegistry, options: options, - testHooks: testHooks, + hooks: hooks, buildSystemManager: buildSystemManager, index: UncheckedIndex(index), indexDelegate: indexDelegate, @@ -334,7 +334,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { package static func forTesting( options: SourceKitLSPOptions, - testHooks: TestHooks, + testHooks: Hooks, buildSystemManager: BuildSystemManager, indexTaskScheduler: TaskScheduler ) async -> Workspace { @@ -343,7 +343,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate { rootUri: nil, capabilityRegistry: CapabilityRegistry(clientCapabilities: ClientCapabilities()), options: options, - testHooks: testHooks, + hooks: testHooks, buildSystemManager: buildSystemManager, index: nil, indexDelegate: nil, diff --git a/Sources/sourcekit-lsp/SourceKitLSP.swift b/Sources/sourcekit-lsp/SourceKitLSP.swift index fc8abf12..9b79a880 100644 --- a/Sources/sourcekit-lsp/SourceKitLSP.swift +++ b/Sources/sourcekit-lsp/SourceKitLSP.swift @@ -309,7 +309,7 @@ struct SourceKitLSP: AsyncParsableCommand { client: clientConnection, toolchainRegistry: ToolchainRegistry(installPath: Bundle.main.bundleURL), options: globalConfigurationOptions, - testHooks: TestHooks(), + hooks: Hooks(), onExit: { clientConnection.close() } diff --git a/Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift b/Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift index c71f90c9..d4537bc0 100644 --- a/Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift +++ b/Tests/BuildSystemIntegrationTests/BuildSystemManagerTests.swift @@ -27,6 +27,17 @@ fileprivate extension BuildSystemManager { } } +private actor TestBuildSystemInjector: BuildSystemInjector { + var testBuildSystem: TestBuildSystem? = nil + + func createBuildSystem(projectRoot: URL, connectionToSourceKitLSP: any Connection) -> any BuiltInBuildSystem { + assert(testBuildSystem == nil, "TestBuildSystemInjector can only create a single TestBuildSystem") + let buildSystem = TestBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP) + testBuildSystem = buildSystem + return buildSystem + } +} + final class BuildSystemManagerTests: XCTestCase { func testMainFiles() async throws { let a = try DocumentURI(string: "bsm:a") @@ -48,7 +59,7 @@ final class BuildSystemManagerTests: XCTestCase { toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. @@ -102,15 +113,16 @@ final class BuildSystemManagerTests: XCTestCase { func testSettingsMainFile() async throws { let a = try DocumentURI(string: "bsm:a.swift") let mainFiles = ManualMainFilesProvider([a: [a]]) + let buildSystemInjector = TestBuildSystemInjector() let bsm = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) - let bs = try await unwrap(bsm.testBuildSystem) + let bs = try await unwrap(buildSystemInjector.testBuildSystem) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. let del = await BSMDelegate(bsm) @@ -135,15 +147,16 @@ final class BuildSystemManagerTests: XCTestCase { func testSettingsMainFileInitialNil() async throws { let a = try DocumentURI(string: "bsm:a.swift") let mainFiles = ManualMainFilesProvider([a: [a]]) + let buildSystemInjector = TestBuildSystemInjector() let bsm = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) - let bs = try await unwrap(bsm.testBuildSystem) + let bs = try await unwrap(buildSystemInjector.testBuildSystem) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. let del = await BSMDelegate(bsm) await bsm.registerForChangeNotifications(for: a, language: .swift) @@ -157,15 +170,16 @@ final class BuildSystemManagerTests: XCTestCase { func testSettingsMainFileWithFallback() async throws { let a = try DocumentURI(string: "bsm:a.swift") let mainFiles = ManualMainFilesProvider([a: [a]]) + let buildSystemInjector = TestBuildSystemInjector() let bsm = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) - let bs = try await unwrap(bsm.testBuildSystem) + let bs = try await unwrap(buildSystemInjector.testBuildSystem) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. let del = await BSMDelegate(bsm) let fallbackSettings = fallbackBuildSettings(for: a, language: .swift, options: .init()) @@ -201,15 +215,16 @@ final class BuildSystemManagerTests: XCTestCase { ] ) + let buildSystemInjector = TestBuildSystemInjector() let bsm = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) - let bs = try await unwrap(bsm.testBuildSystem) + let bs = try await unwrap(buildSystemInjector.testBuildSystem) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. let del = await BSMDelegate(bsm) @@ -265,15 +280,16 @@ final class BuildSystemManagerTests: XCTestCase { ] ) + let buildSystemInjector = TestBuildSystemInjector() let bsm = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: ToolchainRegistry.forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await bsm.setMainFilesProvider(mainFiles) - let bs = try await unwrap(bsm.testBuildSystem) + let bs = try await unwrap(buildSystemInjector.testBuildSystem) defer { withExtendedLifetime(bsm) {} } // Keep BSM alive for callbacks. let del = await BSMDelegate(bsm) diff --git a/Tests/BuildSystemIntegrationTests/FallbackBuildSettingsTests.swift b/Tests/BuildSystemIntegrationTests/FallbackBuildSettingsTests.swift index f7b3dd45..a92705a9 100644 --- a/Tests/BuildSystemIntegrationTests/FallbackBuildSettingsTests.swift +++ b/Tests/BuildSystemIntegrationTests/FallbackBuildSettingsTests.swift @@ -169,9 +169,9 @@ final class FallbackBuildSystemTests: XCTestCase { let x: 1️⃣String2️⃣ = 1 """ ], - testHooks: TestHooks( - buildSystemTestHooks: BuildSystemTestHooks( - handleRequest: { request in + hooks: Hooks( + buildSystemHooks: BuildSystemHooks( + preHandleRequest: { request in if request is TextDocumentSourceKitOptionsRequest { fallbackResultsReceived.waitOrXCTFail() } diff --git a/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift b/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift index 05616f9e..b92e240d 100644 --- a/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift +++ b/Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift @@ -146,7 +146,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -218,7 +218,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -290,7 +290,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(swiftPM: options), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -375,7 +375,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -415,7 +415,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -480,7 +480,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -559,7 +559,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -624,7 +624,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -725,7 +725,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -787,7 +787,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -875,7 +875,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -917,7 +917,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -997,7 +997,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() @@ -1070,8 +1070,8 @@ final class SwiftPMBuildSystemTests: XCTestCase { "MyLibrary/Test.swift": "" ], capabilities: ClientCapabilities(window: WindowClientCapabilities(workDoneProgress: true)), - testHooks: TestHooks( - buildSystemTestHooks: BuildSystemTestHooks( + hooks: Hooks( + buildSystemHooks: BuildSystemHooks( swiftPMTestHooks: SwiftPMTestHooks(reloadPackageDidStart: { didReceiveWorkDoneProgressNotification.waitOrXCTFail() }) @@ -1124,7 +1124,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() let settings = await buildSystemManager.buildSettingsInferredFromMainFile( @@ -1157,7 +1157,7 @@ final class SwiftPMBuildSystemTests: XCTestCase { toolchainRegistry: .forTesting, options: SourceKitLSPOptions(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) await buildSystemManager.waitForUpToDateBuildGraph() let settings = await buildSystemManager.buildSettingsInferredFromMainFile( diff --git a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift index 340c5ea1..a8b5d71f 100644 --- a/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift +++ b/Tests/SourceKitLSPTests/BackgroundIndexingTests.swift @@ -164,7 +164,7 @@ final class BackgroundIndexingTests: XCTestCase { } func testBackgroundIndexingHappensWithLowPriority() async throws { - var testHooks = TestHooks() + var testHooks = Hooks() testHooks.indexTestHooks.preparationTaskDidFinish = { taskDescription in XCTAssert(Task.currentPriority == .low, "\(taskDescription) ran with priority \(Task.currentPriority)") } @@ -192,7 +192,7 @@ final class BackgroundIndexingTests: XCTestCase { ] ) """, - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, pollIndex: false ) @@ -335,7 +335,7 @@ final class BackgroundIndexingTests: XCTestCase { let receivedReportProgressNotification = WrappedSemaphore( name: "Received work done progress saying indexing" ) - var testHooks = TestHooks() + var testHooks = Hooks() testHooks.indexTestHooks = IndexTestHooks( buildGraphGenerationDidFinish: { receivedBeginProgressNotification.waitOrXCTFail() @@ -354,7 +354,7 @@ final class BackgroundIndexingTests: XCTestCase { """ ], capabilities: ClientCapabilities(window: WindowClientCapabilities(workDoneProgress: true)), - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, pollIndex: false, preInitialization: { testClient in @@ -550,7 +550,7 @@ final class BackgroundIndexingTests: XCTestCase { func testPrepareTargetAfterEditToDependency() async throws { try await SkipUnless.swiftPMSupportsExperimentalPrepareForIndexing() - var testHooks = TestHooks() + var testHooks = Hooks() let expectedPreparationTracker = ExpectedIndexTaskTracker(expectedPreparations: [ [ try ExpectedPreparation(target: "LibA", destination: .target), @@ -582,7 +582,7 @@ final class BackgroundIndexingTests: XCTestCase { ) """, capabilities: ClientCapabilities(window: WindowClientCapabilities(workDoneProgress: true)), - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, cleanUp: { expectedPreparationTracker.keepAlive() } ) @@ -655,7 +655,7 @@ final class BackgroundIndexingTests: XCTestCase { let libBStartedPreparation = WrappedSemaphore(name: "LibB started preparing") let libDPreparedForEditing = WrappedSemaphore(name: "LibD prepared for editing") - var testHooks = TestHooks() + var testHooks = Hooks() let expectedPreparationTracker = ExpectedIndexTaskTracker(expectedPreparations: [ // Preparation of targets during the initial of the target [ @@ -702,7 +702,7 @@ final class BackgroundIndexingTests: XCTestCase { ] ) """, - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, cleanUp: { expectedPreparationTracker.keepAlive() } ) @@ -747,7 +747,7 @@ final class BackgroundIndexingTests: XCTestCase { // Block the index tasks until we have received a log notification to make sure we stream out results as they come // in and not only when the indexing task has finished - var testHooks = TestHooks() + var testHooks = Hooks() testHooks.indexTestHooks.preparationTaskDidFinish = { _ in didReceivePreparationIndexLogMessage.waitOrXCTFail() } @@ -760,7 +760,7 @@ final class BackgroundIndexingTests: XCTestCase { files: [ "MyFile.swift": "" ], - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, pollIndex: false ) @@ -785,7 +785,7 @@ final class BackgroundIndexingTests: XCTestCase { let fileAIndexingStarted = WrappedSemaphore(name: "FileA indexing started") let fileBIndexingStarted = WrappedSemaphore(name: "FileB indexing started") - var testHooks = TestHooks() + var testHooks = Hooks() let expectedIndexTaskTracker = ExpectedIndexTaskTracker( expectedIndexStoreUpdates: [ [ @@ -817,7 +817,7 @@ final class BackgroundIndexingTests: XCTestCase { "FileA.swift": "", "FileB.swift": "", ], - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, cleanUp: { expectedIndexTaskTracker.keepAlive() } ) @@ -848,7 +848,7 @@ final class BackgroundIndexingTests: XCTestCase { enableBackgroundIndexing: true ) - var otherClientOptions = TestHooks() + var otherClientOptions = Hooks() otherClientOptions.indexTestHooks = IndexTestHooks( preparationTaskDidStart: { taskDescription in XCTFail("Did not expect any target preparation, got \(taskDescription.targetsToPrepare)") @@ -858,7 +858,7 @@ final class BackgroundIndexingTests: XCTestCase { } ) let otherClient = try await TestSourceKitLSPClient( - testHooks: otherClientOptions, + hooks: otherClientOptions, enableBackgroundIndexing: true, workspaceFolders: [ WorkspaceFolder(uri: DocumentURI(project.scratchDirectory)) @@ -1278,15 +1278,15 @@ final class BackgroundIndexingTests: XCTestCase { func testAddingRandomSwiftFileDoesNotTriggerPackageReload() async throws { let packageInitialized = AtomicBool(initialValue: false) - var testHooks = TestHooks() - testHooks.buildSystemTestHooks.swiftPMTestHooks.reloadPackageDidStart = { + var testHooks = Hooks() + testHooks.buildSystemHooks.swiftPMTestHooks.reloadPackageDidStart = { if packageInitialized.value { XCTFail("Build graph should not get reloaded when random file gets added") } } let project = try await SwiftPMTestProject( files: ["Test.swift": ""], - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true ) packageInitialized.value = true diff --git a/Tests/SourceKitLSPTests/BuildSystemTests.swift b/Tests/SourceKitLSPTests/BuildSystemTests.swift index ed86baa3..81095f15 100644 --- a/Tests/SourceKitLSPTests/BuildSystemTests.swift +++ b/Tests/SourceKitLSPTests/BuildSystemTests.swift @@ -22,6 +22,17 @@ import TSCBasic import ToolchainRegistry import XCTest +private actor TestBuildSystemInjector: BuildSystemInjector { + var testBuildSystem: TestBuildSystem? = nil + + func createBuildSystem(projectRoot: URL, connectionToSourceKitLSP: any Connection) -> any BuiltInBuildSystem { + assert(testBuildSystem == nil, "TestBuildSystemInjector can only create a single TestBuildSystem") + let buildSystem = TestBuildSystem(projectRoot: projectRoot, connectionToSourceKitLSP: connectionToSourceKitLSP) + testBuildSystem = buildSystem + return buildSystem + } +} + final class BuildSystemTests: XCTestCase { /// The mock client used to communicate with the SourceKit-LSP server.p /// @@ -48,18 +59,19 @@ final class BuildSystemTests: XCTestCase { let server = testClient.server + let buildSystemInjector = TestBuildSystemInjector() let buildSystemManager = await BuildSystemManager( - buildSystemSpec: BuildSystemSpec(kind: .testBuildSystem, projectRoot: URL(fileURLWithPath: "/")), + buildSystemSpec: BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: URL(fileURLWithPath: "/")), toolchainRegistry: .forTesting, options: .testDefault(), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) - buildSystem = try await unwrap(buildSystemManager.testBuildSystem) + buildSystem = try await unwrap(buildSystemInjector.testBuildSystem) self.workspace = await Workspace.forTesting( options: SourceKitLSPOptions.testDefault(), - testHooks: TestHooks(), + testHooks: Hooks(), buildSystemManager: buildSystemManager, indexTaskScheduler: .forTesting ) diff --git a/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift b/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift index da9bd6f8..49c474e6 100644 --- a/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift +++ b/Tests/SourceKitLSPTests/PullDiagnosticsTests.swift @@ -285,7 +285,7 @@ final class PullDiagnosticsTests: XCTestCase { func testDiagnosticsWaitForDocumentToBePrepared() async throws { let diagnosticRequestSent = AtomicBool(initialValue: false) - var testHooks = TestHooks() + var testHooks = Hooks() testHooks.indexTestHooks.preparationTaskDidStart = { @Sendable taskDescription in // Only start preparation after we sent the diagnostic request. In almost all cases, this should not give // preparation enough time to finish before the diagnostic request is handled unless we wait for preparation in @@ -322,7 +322,7 @@ final class PullDiagnosticsTests: XCTestCase { ] ) """, - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, pollIndex: false ) @@ -343,8 +343,8 @@ final class PullDiagnosticsTests: XCTestCase { func testDontReturnEmptyDiagnosticsIfDiagnosticRequestIsCancelled() async throws { let diagnosticRequestCancelled = self.expectation(description: "diagnostic request cancelled") let packageLoadingDidFinish = self.expectation(description: "Package loading did finish") - var testHooks = TestHooks() - testHooks.buildSystemTestHooks.swiftPMTestHooks.reloadPackageDidFinish = { + var testHooks = Hooks() + testHooks.buildSystemHooks.swiftPMTestHooks.reloadPackageDidFinish = { packageLoadingDidFinish.fulfill() } testHooks.indexTestHooks.preparationTaskDidStart = { _ in @@ -365,7 +365,7 @@ final class PullDiagnosticsTests: XCTestCase { files: [ "Lib.swift": "let x: String = 1" ], - testHooks: testHooks, + hooks: testHooks, enableBackgroundIndexing: true, pollIndex: false ) diff --git a/Tests/SourceKitLSPTests/SemanticTokensTests.swift b/Tests/SourceKitLSPTests/SemanticTokensTests.swift index 334a2560..48a1761d 100644 --- a/Tests/SourceKitLSPTests/SemanticTokensTests.swift +++ b/Tests/SourceKitLSPTests/SemanticTokensTests.swift @@ -947,7 +947,7 @@ final class SemanticTokensTests: XCTestCase { func testImplicitCancellationOnEdit() async throws { let testClient = try await TestSourceKitLSPClient( - testHooks: TestHooks(handleRequest: { request in + hooks: Hooks(preHandleRequest: { request in if request is DocumentSemanticTokensRequest { // Sleep long enough for the edit to be handled try? await Task.sleep(for: .seconds(10)) @@ -976,7 +976,7 @@ final class SemanticTokensTests: XCTestCase { let testClient = try await TestSourceKitLSPClient( options: SourceKitLSPOptions(cancelTextDocumentRequestsOnEditAndClose: false), - testHooks: TestHooks(handleRequest: { request in + hooks: Hooks(preHandleRequest: { request in if request is DocumentSemanticTokensRequest { // Sleep long enough for the edit to be handled try? await Task.sleep(for: .seconds(2)) diff --git a/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift b/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift index 1eb4cba5..c1c7f89c 100644 --- a/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift +++ b/Tests/SourceKitLSPTests/SwiftPMIntegrationTests.swift @@ -299,8 +299,8 @@ final class SwiftPMIntegrationTests: XCTestCase { files: [ "Test.swift": "" ], - testHooks: TestHooks( - buildSystemTestHooks: BuildSystemTestHooks( + hooks: Hooks( + buildSystemHooks: BuildSystemHooks( swiftPMTestHooks: SwiftPMTestHooks(reloadPackageDidStart: { receivedDocumentSymbolsReply.waitOrXCTFail() }) @@ -321,8 +321,8 @@ final class SwiftPMIntegrationTests: XCTestCase { let x: String = 1 """ ], - testHooks: TestHooks( - buildSystemTestHooks: BuildSystemTestHooks( + hooks: Hooks( + buildSystemHooks: BuildSystemHooks( swiftPMTestHooks: SwiftPMTestHooks(reloadPackageDidStart: { receivedInitialDiagnosticsReply.waitOrXCTFail() }) diff --git a/Tests/SwiftSourceKitPluginTests/PluginSwiftPMTestProject.swift b/Tests/SwiftSourceKitPluginTests/PluginSwiftPMTestProject.swift index 15e15ed9..25464aaf 100644 --- a/Tests/SwiftSourceKitPluginTests/PluginSwiftPMTestProject.swift +++ b/Tests/SwiftSourceKitPluginTests/PluginSwiftPMTestProject.swift @@ -37,7 +37,7 @@ final class PluginSwiftPMTestProject { toolchainRegistry: .forTesting, options: .testDefault(backgroundIndexing: false), connectionToClient: DummyBuildSystemManagerConnectionToClient(), - buildSystemTestHooks: BuildSystemTestHooks() + buildSystemHooks: BuildSystemHooks() ) _buildSystemManager = buildSystemManager return buildSystemManager