Skip to content

Commit

Permalink
Merge pull request #2013 from ahoppen/clean-background-index-up-to-da…
Browse files Browse the repository at this point in the history
…te-checks

When the build system sends an update for build targets, update the index for the files in those targets
  • Loading branch information
ahoppen authored Mar 4, 2025
2 parents 300c40b + fe750f6 commit bafd8ba
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,11 @@ public struct SourceKitInitializeBuildResponseData: LSPAnyCodable, Codable, Send
public var sourceKitOptionsProvider: Bool?

public init(
indexDatabasePath: String?,
indexStorePath: String?,
watchers: [FileSystemWatcher]?,
prepareProvider: Bool?,
sourceKitOptionsProvider: Bool?
indexDatabasePath: String? = nil,
indexStorePath: String? = nil,
watchers: [FileSystemWatcher]? = nil,
prepareProvider: Bool? = nil,
sourceKitOptionsProvider: Bool? = nil
) {
self.indexDatabasePath = indexDatabasePath
self.indexStorePath = indexStorePath
Expand Down
21 changes: 21 additions & 0 deletions Sources/BuildSystemIntegration/BuildSystemManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,20 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
/// `pathComponents` is the result of `key.fileURL?.pathComponents`. We frequently need these path components to
/// determine if a file is descendent of the directory and computing them from the `DocumentURI` is expensive.
let directories: [DocumentURI: (pathComponents: [String]?, info: SourceFileInfo)]

/// Same as `Set(files.filter(\.value.isBuildable).keys)`. Pre-computed because we need this pretty frequently in
/// `SemanticIndexManager.filesToIndex`.
let buildableSourceFiles: Set<DocumentURI>

internal init(
files: [DocumentURI: SourceFileInfo],
directories: [DocumentURI: (pathComponents: [String]?, info: SourceFileInfo)]
) {
self.files = files
self.directories = directories
self.buildableSourceFiles = Set(files.filter(\.value.isBuildable).keys)
}

}

private let cachedSourceFilesAndDirectories = Cache<SourceFilesAndDirectoriesKey, SourceFilesAndDirectories>()
Expand Down Expand Up @@ -1153,6 +1167,13 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
}
}

/// Returns all source files in the project that are considered buildable.
///
/// - SeeAlso: Comment in `sourceFilesAndDirectories` for a definition of what `buildable` means.
package func buildableSourceFiles() async throws -> Set<DocumentURI> {
return try await sourceFilesAndDirectories().buildableSourceFiles
}

/// Get all files and directories that are known to the build system, ie. that are returned by a `buildTarget/sources`
/// request for any target in the project.
///
Expand Down
19 changes: 16 additions & 3 deletions Sources/BuildSystemIntegration/TestBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ package actor TestBuildSystem: MessageHandler {
connectionToSourceKitLSP.send(OnBuildTargetDidChangeNotification(changes: nil))
}

package nonisolated var supportsPreparation: Bool { false }
private let initializeData: SourceKitInitializeBuildResponseData

package init(connectionToSourceKitLSP: any Connection) {
package init(
initializeData: SourceKitInitializeBuildResponseData = SourceKitInitializeBuildResponseData(
sourceKitOptionsProvider: true
),
connectionToSourceKitLSP: any Connection
) {
self.initializeData = initializeData
self.connectionToSourceKitLSP = connectionToSourceKitLSP
}

Expand Down Expand Up @@ -90,6 +96,8 @@ package actor TestBuildSystem: MessageHandler {
handle(request, using: self.workspaceBuildTargetsRequest)
case let request as WorkspaceWaitForBuildSystemUpdatesRequest:
handle(request, using: self.workspaceWaitForBuildSystemUpdatesRequest)
case let request as BuildTargetPrepareRequest:
handle(request, using: self.prepareTarget)
default:
reply(.failure(ResponseError.methodNotFound(type(of: request).method)))
}
Expand All @@ -101,7 +109,8 @@ package actor TestBuildSystem: MessageHandler {
version: "",
bspVersion: "2.2.0",
capabilities: BuildServerCapabilities(),
data: nil
dataKind: .sourceKit,
data: initializeData.encodeToLSPAny()
)
}

Expand Down Expand Up @@ -148,6 +157,10 @@ package actor TestBuildSystem: MessageHandler {
return buildSettingsByFile[request.textDocument.uri]
}

func prepareTarget(_ request: BuildTargetPrepareRequest) async throws -> VoidResponse {
return VoidResponse()
}

package func waitForBuildSystemUpdates(request: WorkspaceWaitForBuildSystemUpdatesRequest) async -> VoidResponse {
return VoidResponse()
}
Expand Down
20 changes: 17 additions & 3 deletions Sources/SemanticIndex/CheckedIndex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//

#if compiler(>=6)
import Foundation
package import Foundation
@preconcurrency package import IndexStoreDB
package import LanguageServerProtocol
import SKLogging
Expand Down Expand Up @@ -188,6 +188,20 @@ package final class CheckedIndex {
return checker.fileHasInMemoryModifications(uri)
}

/// Determine the modification date of the file at the given location or, if it is a symlink, the maximum modification
/// time of any hop in the symlink change until the real file.
///
/// This uses the `CheckedIndex`'s mod date cache, so it doesn't require disk access if the modification date of the
/// file has already been computed.
///
/// Returns `nil` if the modification date of the file could not be determined.
package func modificationDate(of uri: DocumentURI) -> Date? {
switch try? checker.modificationDate(of: uri) {
case nil, .fileDoesNotExist: return nil
case .date(let date): return date
}
}

/// If there are any definition occurrences of the given USR, return these.
/// Otherwise return declaration occurrences.
package func definitionOrDeclarationOccurrences(ofUSR usr: String) -> [SymbolOccurrence] {
Expand Down Expand Up @@ -327,7 +341,7 @@ private struct IndexOutOfDateChecker {
private let checkLevel: IndexCheckLevel

/// The last modification time of a file. Can also represent the fact that the file does not exist.
private enum ModificationTime {
enum ModificationTime {
case fileDoesNotExist
case date(Date)
}
Expand Down Expand Up @@ -495,7 +509,7 @@ private struct IndexOutOfDateChecker {
}
}

private mutating func modificationDate(of uri: DocumentURI) throws -> ModificationTime {
mutating func modificationDate(of uri: DocumentURI) throws -> ModificationTime {
if let cached = modTimeCache[uri] {
return cached
}
Expand Down
Loading

0 comments on commit bafd8ba

Please sign in to comment.