diff --git a/Sources/SKCore/BuildServerBuildSystem.swift b/Sources/SKCore/BuildServerBuildSystem.swift index fba894d7..328d3d64 100644 --- a/Sources/SKCore/BuildServerBuildSystem.swift +++ b/Sources/SKCore/BuildServerBuildSystem.swift @@ -35,6 +35,9 @@ public final class BuildServerBuildSystem { public private(set) var indexDatabasePath: AbsolutePath? public private(set) var indexStorePath: AbsolutePath? + // FIXME: Add support for prefix mappings to the Build Server protocol. + public var indexPrefixMappings: [PathPrefixMapping] { return [] } + /// Delegate to handle any build system events. public weak var delegate: BuildSystemDelegate? { get { return self.handler?.delegate } diff --git a/Sources/SKCore/BuildSystem.swift b/Sources/SKCore/BuildSystem.swift index 094d368c..5ecf15c6 100644 --- a/Sources/SKCore/BuildSystem.swift +++ b/Sources/SKCore/BuildSystem.swift @@ -43,6 +43,9 @@ public protocol BuildSystem: AnyObject { /// The path to put the index database, if any. var indexDatabasePath: AbsolutePath? { get } + /// Path remappings for remapping index data for local use. + var indexPrefixMappings: [PathPrefixMapping] { get } + /// Delegate to handle any build system events such as file build settings /// initial reports as well as changes. var delegate: BuildSystemDelegate? { get set } diff --git a/Sources/SKCore/BuildSystemManager.swift b/Sources/SKCore/BuildSystemManager.swift index d7727c01..c012e75c 100644 --- a/Sources/SKCore/BuildSystemManager.swift +++ b/Sources/SKCore/BuildSystemManager.swift @@ -140,6 +140,8 @@ extension BuildSystemManager: BuildSystem { public var indexDatabasePath: AbsolutePath? { queue.sync { buildSystem?.indexDatabasePath } } + public var indexPrefixMappings: [PathPrefixMapping] { queue.sync { buildSystem?.indexPrefixMappings ?? [] } } + public var delegate: BuildSystemDelegate? { get { queue.sync { _delegate } } set { queue.sync { _delegate = newValue } } diff --git a/Sources/SKCore/CMakeLists.txt b/Sources/SKCore/CMakeLists.txt index 7cd686d4..5281bf85 100644 --- a/Sources/SKCore/CMakeLists.txt +++ b/Sources/SKCore/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(SKCore STATIC FileBuildSettingsChange.swift LanguageServer.swift MainFilesProvider.swift + PathPrefixMapping.swift Toolchain.swift ToolchainRegistry.swift XCToolchainPlist.swift) diff --git a/Sources/SKCore/CompilationDatabaseBuildSystem.swift b/Sources/SKCore/CompilationDatabaseBuildSystem.swift index 1bb46fc6..7a3287cc 100644 --- a/Sources/SKCore/CompilationDatabaseBuildSystem.swift +++ b/Sources/SKCore/CompilationDatabaseBuildSystem.swift @@ -88,6 +88,8 @@ extension CompilationDatabaseBuildSystem: BuildSystem { indexStorePath?.parentDirectory.appending(component: "IndexDatabase") } + public var indexPrefixMappings: [PathPrefixMapping] { return [] } + public func registerForChangeNotifications(for uri: DocumentURI, language: Language) { queue.async { self.watchedFiles[uri] = language diff --git a/Sources/SKCore/FallbackBuildSystem.swift b/Sources/SKCore/FallbackBuildSystem.swift index ceb6cade..5f5d28ee 100644 --- a/Sources/SKCore/FallbackBuildSystem.swift +++ b/Sources/SKCore/FallbackBuildSystem.swift @@ -40,6 +40,8 @@ public final class FallbackBuildSystem: BuildSystem { public var indexDatabasePath: AbsolutePath? { return nil } + public var indexPrefixMappings: [PathPrefixMapping] { return [] } + public func settings(for uri: DocumentURI, _ language: Language) -> FileBuildSettings? { switch language { case .swift: diff --git a/Sources/SKCore/PathPrefixMapping.swift b/Sources/SKCore/PathPrefixMapping.swift new file mode 100644 index 00000000..ac71f4f2 --- /dev/null +++ b/Sources/SKCore/PathPrefixMapping.swift @@ -0,0 +1,14 @@ +import Foundation + +public struct PathPrefixMapping { + /// Path prefix to be replaced, typically the canonical or hermetic path. + public let original: String + + /// Replacement path prefix, typically the path on the local machine. + public let replacement: String + + public init(original: String, replacement: String) { + self.original = original + self.replacement = replacement + } +} diff --git a/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift b/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift index e542fd02..779a179c 100644 --- a/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift +++ b/Sources/SKSwiftPMWorkspace/SwiftPMWorkspace.swift @@ -240,6 +240,8 @@ extension SwiftPMWorkspace: SKCore.BuildSystem { return buildPath.appending(components: "index", "db") } + public var indexPrefixMappings: [PathPrefixMapping] { return [] } + /// **Public for testing only** public func _settings( for uri: DocumentURI, diff --git a/Sources/SourceKitLSP/Workspace.swift b/Sources/SourceKitLSP/Workspace.swift index edaec13d..957717e5 100644 --- a/Sources/SourceKitLSP/Workspace.swift +++ b/Sources/SourceKitLSP/Workspace.swift @@ -112,12 +112,14 @@ public final class Workspace { do { let lib = try IndexStoreLibrary(dylibPath: libPath.pathString) indexDelegate = SourceKitIndexDelegate() + let prefixMappings = indexOptions.indexPrefixMappings ?? buildSystem?.indexPrefixMappings ?? [] index = try IndexStoreDB( storePath: storePath.pathString, databasePath: dbPath.pathString, library: lib, delegate: indexDelegate, - listenToUnitEvents: indexOptions.listenToUnitEvents) + listenToUnitEvents: indexOptions.listenToUnitEvents, + prefixMappings: prefixMappings.map { PathMapping(original: $0.original, replacement: $0.replacement) }) log("opened IndexStoreDB at \(dbPath) with store path \(storePath)") } catch { log("failed to open IndexStoreDB: \(error.localizedDescription)", level: .error) @@ -144,11 +146,22 @@ public struct IndexOptions { /// Override the index-database-path provided by the build system. public var indexDatabasePath: AbsolutePath? + /// Override the index prefix mappings provided by the build system. + public var indexPrefixMappings: [PathPrefixMapping]? + /// *For Testing* Whether the index should listen to unit events, or wait for /// explicit calls to pollForUnitChangesAndWait(). public var listenToUnitEvents: Bool - public init(indexStorePath: AbsolutePath? = nil, indexDatabasePath: AbsolutePath? = nil, listenToUnitEvents: Bool = true) { + public init( + indexStorePath: AbsolutePath? = nil, + indexDatabasePath: AbsolutePath? = nil, + indexPrefixMappings: [PathPrefixMapping]? = nil, + listenToUnitEvents: Bool = true + ) { + self.indexStorePath = indexStorePath + self.indexDatabasePath = indexDatabasePath + self.indexPrefixMappings = indexPrefixMappings self.listenToUnitEvents = listenToUnitEvents } } diff --git a/Sources/sourcekit-lsp/main.swift b/Sources/sourcekit-lsp/main.swift index 8f0828d4..361cf52a 100644 --- a/Sources/sourcekit-lsp/main.swift +++ b/Sources/sourcekit-lsp/main.swift @@ -41,6 +41,14 @@ extension AbsolutePath: ExpressibleByArgument { } } +extension PathPrefixMapping: ExpressibleByArgument { + public init?(argument: String) { + guard let eqIndex = argument.firstIndex(of: "=") else { return nil } + self.init(original: String(argument[..) -> Void) { fatalError() diff --git a/Tests/SourceKitLSPTests/BuildSystemTests.swift b/Tests/SourceKitLSPTests/BuildSystemTests.swift index fbaadc83..45318375 100644 --- a/Tests/SourceKitLSPTests/BuildSystemTests.swift +++ b/Tests/SourceKitLSPTests/BuildSystemTests.swift @@ -27,6 +27,7 @@ typealias LSPNotification = LanguageServerProtocol.Notification final class TestBuildSystem: BuildSystem { var indexStorePath: AbsolutePath? = nil var indexDatabasePath: AbsolutePath? = nil + var indexPrefixMappings: [PathPrefixMapping] = [] weak var delegate: BuildSystemDelegate?