diff --git a/Sources/SKCore/BuildServerBuildSystem.swift b/Sources/SKCore/BuildServerBuildSystem.swift index 19d7270f..7bd9a500 100644 --- a/Sources/SKCore/BuildServerBuildSystem.swift +++ b/Sources/SKCore/BuildServerBuildSystem.swift @@ -317,14 +317,14 @@ extension BuildServerBuildSystem: BuildSystem { return .unhandled } - public func testFiles() async -> [DocumentURI] { - // BuildServerBuildSystem does not support syntactic test discovery + public func sourceFiles() async -> [SourceFileInfo] { + // BuildServerBuildSystem does not support syntactic test discovery or background indexing. // (https://github.com/apple/sourcekit-lsp/issues/1173). return [] } - public func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) { - // BuildServerBuildSystem does not support syntactic test discovery + public func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) { + // BuildServerBuildSystem does not support syntactic test discovery or background indexing. // (https://github.com/apple/sourcekit-lsp/issues/1173). } } diff --git a/Sources/SKCore/BuildSystem.swift b/Sources/SKCore/BuildSystem.swift index e9756023..a0954fd1 100644 --- a/Sources/SKCore/BuildSystem.swift +++ b/Sources/SKCore/BuildSystem.swift @@ -27,6 +27,22 @@ public enum FileHandlingCapability: Comparable, Sendable { case handled } +public struct SourceFileInfo: Sendable { + /// The URI of the source file. + public let uri: DocumentURI + + /// Whether the file might contain test cases. This property is an over-approximation. It might be true for files + /// from non-test targets or files that don't actually contain any tests. Keeping this list of files with + /// `mayContainTets` minimal as possible helps reduce the amount of work that the syntactic test indexer needs to + /// perform. + public let mayContainTests: Bool + + public init(uri: DocumentURI, mayContainTests: Bool) { + self.uri = uri + self.mayContainTests = mayContainTests + } +} + /// Provider of FileBuildSettings and other build-related information. /// /// The primary role of the build system is to answer queries for @@ -88,17 +104,13 @@ public protocol BuildSystem: AnyObject, Sendable { func fileHandlingCapability(for uri: DocumentURI) async -> FileHandlingCapability - /// Returns the list of files that might contain test cases. - /// - /// The returned file list is an over-approximation. It might contain tests from non-test targets or files that don't - /// actually contain any tests. Keeping this list as minimal as possible helps reduce the amount of work that the - /// syntactic test indexer needs to perform. - func testFiles() async -> [DocumentURI] + /// Returns the list of source files in the project. + func sourceFiles() async -> [SourceFileInfo] - /// Adds a callback that should be called when the value returned by `testFiles()` changes. + /// Adds a callback that should be called when the value returned by `sourceFiles()` changes. /// - /// The callback might also be called without an actual change to `testFiles`. - func addTestFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async + /// The callback might also be called without an actual change to `sourceFiles`. + func addSourceFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async } public let buildTargetsNotSupported = diff --git a/Sources/SKCore/BuildSystemManager.swift b/Sources/SKCore/BuildSystemManager.swift index 0e03e6b2..926037f0 100644 --- a/Sources/SKCore/BuildSystemManager.swift +++ b/Sources/SKCore/BuildSystemManager.swift @@ -191,8 +191,17 @@ extension BuildSystemManager { ) } + public func sourceFiles() async -> [SourceFileInfo] { + return await buildSystem?.sourceFiles() ?? [] + } + public func testFiles() async -> [DocumentURI] { - return await buildSystem?.testFiles() ?? [] + return await sourceFiles().compactMap { (info: SourceFileInfo) -> DocumentURI? in + guard info.mayContainTests else { + return nil + } + return info.uri + } } } diff --git a/Sources/SKCore/CompilationDatabaseBuildSystem.swift b/Sources/SKCore/CompilationDatabaseBuildSystem.swift index 929110f2..5e0e2fe7 100644 --- a/Sources/SKCore/CompilationDatabaseBuildSystem.swift +++ b/Sources/SKCore/CompilationDatabaseBuildSystem.swift @@ -192,11 +192,16 @@ extension CompilationDatabaseBuildSystem: BuildSystem { } } - public func testFiles() async -> [DocumentURI] { - return compdb?.allCommands.map { DocumentURI($0.url) } ?? [] + public func sourceFiles() async -> [SourceFileInfo] { + guard let compdb else { + return [] + } + return compdb.allCommands.map { + SourceFileInfo(uri: DocumentURI($0.url), mayContainTests: true) + } } - public func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) async { + public func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) async { testFilesDidChangeCallbacks.append(callback) } } diff --git a/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift b/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift index 4bb6ee64..c4599607 100644 --- a/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift +++ b/Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift @@ -437,17 +437,22 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem { } } - public func testFiles() -> [DocumentURI] { - return fileToTarget.compactMap { (path, target) -> DocumentURI? in + public func sourceFiles() -> [SourceFileInfo] { + return fileToTarget.compactMap { (path, target) -> SourceFileInfo? in guard target.isPartOfRootPackage else { // Don't consider files from package dependencies as possible test files. return nil } - return DocumentURI(path.asURL) + // We should only set mayContainTests to `true` for files from test targets + // (https://github.com/apple/sourcekit-lsp/issues/1174). + return SourceFileInfo( + uri: DocumentURI(path.asURL), + mayContainTests: true + ) } } - public func addTestFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async { + public func addSourceFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async { testFilesDidChangeCallbacks.append(callback) } } diff --git a/Sources/SourceKitLSP/Workspace.swift b/Sources/SourceKitLSP/Workspace.swift index bba836a3..50ec6a49 100644 --- a/Sources/SourceKitLSP/Workspace.swift +++ b/Sources/SourceKitLSP/Workspace.swift @@ -97,7 +97,7 @@ public final class Workspace { await indexDelegate?.addMainFileChangedCallback { [weak self] in await self?.buildSystemManager.mainFilesChanged() } - await underlyingBuildSystem?.addTestFilesDidChangeCallback { [weak self] in + await underlyingBuildSystem?.addSourceFilesDidChangeCallback { [weak self] in guard let self else { return } diff --git a/Tests/SKCoreTests/BuildSystemManagerTests.swift b/Tests/SKCoreTests/BuildSystemManagerTests.swift index 156a2f1c..96ec6890 100644 --- a/Tests/SKCoreTests/BuildSystemManagerTests.swift +++ b/Tests/SKCoreTests/BuildSystemManagerTests.swift @@ -469,11 +469,11 @@ class ManualBuildSystem: BuildSystem { } } - func testFiles() async -> [DocumentURI] { + func sourceFiles() async -> [SourceFileInfo] { return [] } - func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) {} + func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) {} } /// A `BuildSystemDelegate` setup for testing. diff --git a/Tests/SourceKitLSPTests/BuildSystemTests.swift b/Tests/SourceKitLSPTests/BuildSystemTests.swift index c0ac9f0d..092520dd 100644 --- a/Tests/SourceKitLSPTests/BuildSystemTests.swift +++ b/Tests/SourceKitLSPTests/BuildSystemTests.swift @@ -61,11 +61,11 @@ final class TestBuildSystem: BuildSystem { } } - func testFiles() async -> [DocumentURI] { + func sourceFiles() async -> [SourceFileInfo] { return [] } - func addTestFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {} + func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {} } final class BuildSystemTests: XCTestCase {