diff --git a/Sources/SKCore/BuildServerBuildSystem.swift b/Sources/SKCore/BuildServerBuildSystem.swift index e297b36f..cce21ef4 100644 --- a/Sources/SKCore/BuildServerBuildSystem.swift +++ b/Sources/SKCore/BuildServerBuildSystem.swift @@ -173,12 +173,13 @@ extension BuildServerBuildSystem: BuildSystem { return nil } - public func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { - _ = self.buildServer?.send(BuildTargets(), queue: requestQueue) { result in - if let targets = result.success?.targets { reply(targets) } - else { - log("error fetching build targets: \(result)") - reply(nil) + public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { + _ = self.buildServer?.send(BuildTargets(), queue: requestQueue) { response in + switch response { + case .success(let result): + reply(.success(result.targets)) + case .failure(let error): + reply(.failure(error)) } } } diff --git a/Sources/SKCore/BuildSystem.swift b/Sources/SKCore/BuildSystem.swift index 13308908..074821fb 100644 --- a/Sources/SKCore/BuildSystem.swift +++ b/Sources/SKCore/BuildSystem.swift @@ -16,12 +16,13 @@ import TSCBasic /// Provider of FileBuildSettings and other build-related information. /// -/// The primary role of the build system is to answer queries for FileBuildSettings and to notify -/// its delegate when they change. The BuildSystem is also the source of related information, such -/// as where the index datastore is located. +/// The primary role of the build system is to answer queries for +/// FileBuildSettings and to notify its delegate when they change. The +/// BuildSystem is also the source of related information, such as where the +/// index datastore is located. /// -/// For example, a SwiftPMWorkspace provides compiler arguments for the files contained in a -/// SwiftPM package root directory. +/// For example, a SwiftPMWorkspace provides compiler arguments for the files +/// contained in a SwiftPM package root directory. public protocol BuildSystem: AnyObject { /// The path to the raw index store data, if any. @@ -36,18 +37,23 @@ public protocol BuildSystem: AnyObject { /// Returns the toolchain to use to compile this file func toolchain(for: URL, _ language: Language) -> Toolchain? - /// Delegate to handle any build system events such as file build settings changing. + /// Delegate to handle any build system events such as file build settings + /// changing. var delegate: BuildSystemDelegate? { get set } - /// Register the given file for build-system level change notifications, such as command - /// line flag changes, dependency changes, etc. + /// Register the given file for build-system level change notifications, such + /// as command line flag changes, dependency changes, etc. func registerForChangeNotifications(for: URL) - /// Unregister the given file for build-system level change notifications, such as command - /// line flag changes, dependency changes, etc. + /// Unregister the given file for build-system level change notifications, + /// such as command line flag changes, dependency changes, etc. func unregisterForChangeNotifications(for: URL) - /// Returns the build targets in the workspace - func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) - + /// Returns the build targets in the workspace. If the build system does not + /// support build targets the `buildTargetsNotSupported` error should be + /// returned. + func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) } + +public let buildTargetsNotSupported = + ResponseError.methodNotFound(BuildTargets.method) diff --git a/Sources/SKCore/BuildSystemList.swift b/Sources/SKCore/BuildSystemList.swift index d6ace9d4..fec6b1f3 100644 --- a/Sources/SKCore/BuildSystemList.swift +++ b/Sources/SKCore/BuildSystemList.swift @@ -63,7 +63,8 @@ extension BuildSystemList: BuildSystem { return providers.first?.toolchain(for: url, language) } - public func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { + public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { providers.first?.buildTargets(reply: reply) } + } diff --git a/Sources/SKCore/CompilationDatabaseBuildSystem.swift b/Sources/SKCore/CompilationDatabaseBuildSystem.swift index e5c6eaf6..2cf32145 100644 --- a/Sources/SKCore/CompilationDatabaseBuildSystem.swift +++ b/Sources/SKCore/CompilationDatabaseBuildSystem.swift @@ -60,7 +60,9 @@ extension CompilationDatabaseBuildSystem: BuildSystem { /// We don't support change watching. public func unregisterForChangeNotifications(for: URL) {} - public func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { reply(nil) } + public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { + reply(.failure(buildTargetsNotSupported)) + } func database(for url: URL) -> CompilationDatabase? { if let path = try? AbsolutePath(validating: url.path) { diff --git a/Sources/SKCore/FallbackBuildSystem.swift b/Sources/SKCore/FallbackBuildSystem.swift index 9fd99dcf..40b9ded9 100644 --- a/Sources/SKCore/FallbackBuildSystem.swift +++ b/Sources/SKCore/FallbackBuildSystem.swift @@ -62,7 +62,9 @@ public final class FallbackBuildSystem: BuildSystem { public func toolchain(for: URL, _ language: Language) -> Toolchain? { return nil } - public func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { reply(nil) } + public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { + reply(.failure(buildTargetsNotSupported)) + } func settingsSwift(_ path: AbsolutePath) -> FileBuildSettings { var args: [String] = [] diff --git a/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift b/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift index 1243a402..483c0074 100644 --- a/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift +++ b/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift @@ -234,9 +234,9 @@ extension SwiftPMWorkspace: BuildSystem { // TODO: Support for change detection (via file watching) } - public func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { - // TODO: add target support for SwiftPM - reply(nil) + public func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { + // TODO: Support for build targets + reply(.failure(buildTargetsNotSupported)) } /// Returns the resolved target description for the given file, if one is known. diff --git a/Tests/SKCoreTests/BuildServerBuildSystemTests.swift b/Tests/SKCoreTests/BuildServerBuildSystemTests.swift index 900bc003..6beb5179 100644 --- a/Tests/SKCoreTests/BuildServerBuildSystemTests.swift +++ b/Tests/SKCoreTests/BuildServerBuildSystemTests.swift @@ -74,25 +74,30 @@ final class BuildServerBuildSystemTests: XCTestCase { XCTAssertNotNil(buildSystem) let expectation = XCTestExpectation(description: "build target expectation") - buildSystem?.buildTargets(reply: { targets in - XCTAssertNotNil(targets) - XCTAssertEqual(targets, [ - BuildTarget(id: BuildTargetIdentifier(uri: URL(string: "first_target")!), - displayName: "First Target", - baseDirectory: URL(fileURLWithPath: "/some/dir"), - tags: [BuildTargetTag.library, BuildTargetTag.test], - capabilities: BuildTargetCapabilities(canCompile: true, canTest: true, canRun: false), - languageIds: [Language.objective_c, Language.swift], - dependencies: []), - BuildTarget(id: BuildTargetIdentifier(uri: URL(string: "second_target")!), - displayName: "Second Target", - baseDirectory: URL(fileURLWithPath: "/some/dir"), - tags: [BuildTargetTag.library, BuildTargetTag.test], - capabilities: BuildTargetCapabilities(canCompile: true, canTest: false, canRun: false), - languageIds: [Language.objective_c, Language.swift], - dependencies: [BuildTargetIdentifier(uri: URL(string: "first_target")!)]), - ]) - expectation.fulfill() + + buildSystem?.buildTargets(reply: { response in + switch(response) { + case .success(let targets): + XCTAssertEqual(targets, [ + BuildTarget(id: BuildTargetIdentifier(uri: URL(string: "first_target")!), + displayName: "First Target", + baseDirectory: URL(fileURLWithPath: "/some/dir"), + tags: [BuildTargetTag.library, BuildTargetTag.test], + capabilities: BuildTargetCapabilities(canCompile: true, canTest: true, canRun: false), + languageIds: [Language.objective_c, Language.swift], + dependencies: []), + BuildTarget(id: BuildTargetIdentifier(uri: URL(string: "second_target")!), + displayName: "Second Target", + baseDirectory: URL(fileURLWithPath: "/some/dir"), + tags: [BuildTargetTag.library, BuildTargetTag.test], + capabilities: BuildTargetCapabilities(canCompile: true, canTest: false, canRun: false), + languageIds: [Language.objective_c, Language.swift], + dependencies: [BuildTargetIdentifier(uri: URL(string: "first_target")!)]), + ]) + expectation.fulfill() + case .failure(let error): + XCTFail(error.message) + } }) XCTAssertEqual(XCTWaiter.wait(for: [expectation], timeout: 1), .completed) } diff --git a/Tests/SourceKitTests/BuildSystemTests.swift b/Tests/SourceKitTests/BuildSystemTests.swift index 247992bf..2c8d4c20 100644 --- a/Tests/SourceKitTests/BuildSystemTests.swift +++ b/Tests/SourceKitTests/BuildSystemTests.swift @@ -55,8 +55,8 @@ final class TestBuildSystem: BuildSystem { watchedFiles.remove(url) } - func buildTargets(reply: @escaping ([BuildTarget]?) -> Void) { - + func buildTargets(reply: @escaping (LSPResult<[BuildTarget]>) -> Void) { + reply(.failure(buildTargetsNotSupported)) } }