diff --git a/Sources/BuildSystemIntegration/BuildSystemManager.swift b/Sources/BuildSystemIntegration/BuildSystemManager.swift index 47832ef4..6a5855e2 100644 --- a/Sources/BuildSystemIntegration/BuildSystemManager.swift +++ b/Sources/BuildSystemIntegration/BuildSystemManager.swift @@ -59,6 +59,18 @@ fileprivate class RequestCache [SourceFileInfo] { - // FIXME: (BSP Migration): Consider removing this method and letting callers get all targets first and then - // retrieving the source files for those targets. - // FIXME: (BSP Migration) Handle source files that are in multiple targets + package func sourceFiles() async throws -> [DocumentURI: SourceFileInfo] { let targets = try await self.buildTargets() - let sourceFiles = try await self.sourceFiles(in: targets.keys).flatMap { sourcesItem in + var sourceFiles: [DocumentURI: SourceFileInfo] = [:] + for sourcesItem in try await self.sourceFiles(in: targets.keys) { let target = targets[sourcesItem.target]?.target - return sourcesItem.sources.map { sourceItem in - SourceFileInfo( - uri: sourceItem.uri, - isPartOfRootProject: !(target?.tags.contains(.dependency) ?? false), - mayContainTests: target?.tags.contains(.test) ?? true - ) + let isPartOfRootProject = !(target?.tags.contains(.dependency) ?? false) + let mayContainTests = target?.tags.contains(.test) ?? true + + for sourceItem in sourcesItem.sources { + if let existingEntry = sourceFiles[sourceItem.uri] { + sourceFiles[sourceItem.uri] = SourceFileInfo( + isPartOfRootProject: existingEntry.isPartOfRootProject || isPartOfRootProject, + mayContainTests: existingEntry.mayContainTests || mayContainTests + ) + } else { + sourceFiles[sourceItem.uri] = SourceFileInfo( + isPartOfRootProject: isPartOfRootProject, + mayContainTests: mayContainTests + ) + } } } return sourceFiles } package func testFiles() async throws -> [DocumentURI] { - return try await sourceFiles().compactMap { (info: SourceFileInfo) -> DocumentURI? in + return try await sourceFiles().compactMap { (uri, info) -> DocumentURI? in guard info.isPartOfRootProject, info.mayContainTests else { return nil } - return info.uri + return uri } } } diff --git a/Sources/BuildSystemIntegration/BuiltInBuildSystem.swift b/Sources/BuildSystemIntegration/BuiltInBuildSystem.swift index 0d9fd420..317ecf84 100644 --- a/Sources/BuildSystemIntegration/BuiltInBuildSystem.swift +++ b/Sources/BuildSystemIntegration/BuiltInBuildSystem.swift @@ -19,27 +19,6 @@ import ToolchainRegistry import struct TSCBasic.AbsolutePath import struct TSCBasic.RelativePath -package struct SourceFileInfo: Sendable { - /// The URI of the source file. - package let uri: DocumentURI - - /// `true` if this file belongs to the root project that the user is working on. It is false, if the file belongs - /// to a dependency of the project. - package let isPartOfRootProject: Bool - - /// 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. - package let mayContainTests: Bool - - package init(uri: DocumentURI, isPartOfRootProject: Bool, mayContainTests: Bool) { - self.uri = uri - self.isPartOfRootProject = isPartOfRootProject - self.mayContainTests = mayContainTests - } -} - /// An error build systems can throw from `prepare` if they don't support preparation of targets. package struct PrepareNotSupportedError: Error, CustomStringConvertible { package init() {} diff --git a/Sources/SemanticIndex/SemanticIndexManager.swift b/Sources/SemanticIndex/SemanticIndexManager.swift index 5d9a2d1d..136f582b 100644 --- a/Sources/SemanticIndex/SemanticIndexManager.swift +++ b/Sources/SemanticIndex/SemanticIndexManager.swift @@ -270,7 +270,7 @@ package final actor SemanticIndexManager { filesToIndex } else { await orLog("Getting files to index") { - try await self.buildSystemManager.sourceFiles().lazy.map(\.uri) + try await self.buildSystemManager.sourceFiles().keys.sorted { $0.stringValue < $1.stringValue } } ?? [] } if !indexFilesWithUpToDateUnit { @@ -366,7 +366,7 @@ package final actor SemanticIndexManager { toCover files: some Collection & Sendable ) async -> [FileToIndex] { let sourceFiles = await orLog("Getting source files in project") { - Set(try await buildSystemManager.sourceFiles().map(\.uri)) + Set(try await buildSystemManager.sourceFiles().keys) } guard let sourceFiles else { return []