Skip to content

Commit bafd8ba

Browse files
authored
Merge pull request #2013 from ahoppen/clean-background-index-up-to-date-checks
When the build system sends an update for build targets, update the index for the files in those targets
2 parents 300c40b + fe750f6 commit bafd8ba

File tree

9 files changed

+317
-131
lines changed

9 files changed

+317
-131
lines changed

Sources/BuildServerProtocol/Messages/InitializeBuildRequest.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,11 @@ public struct SourceKitInitializeBuildResponseData: LSPAnyCodable, Codable, Send
283283
public var sourceKitOptionsProvider: Bool?
284284

285285
public init(
286-
indexDatabasePath: String?,
287-
indexStorePath: String?,
288-
watchers: [FileSystemWatcher]?,
289-
prepareProvider: Bool?,
290-
sourceKitOptionsProvider: Bool?
286+
indexDatabasePath: String? = nil,
287+
indexStorePath: String? = nil,
288+
watchers: [FileSystemWatcher]? = nil,
289+
prepareProvider: Bool? = nil,
290+
sourceKitOptionsProvider: Bool? = nil
291291
) {
292292
self.indexDatabasePath = indexDatabasePath
293293
self.indexStorePath = indexStorePath

Sources/BuildSystemIntegration/BuildSystemManager.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,20 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
392392
/// `pathComponents` is the result of `key.fileURL?.pathComponents`. We frequently need these path components to
393393
/// determine if a file is descendent of the directory and computing them from the `DocumentURI` is expensive.
394394
let directories: [DocumentURI: (pathComponents: [String]?, info: SourceFileInfo)]
395+
396+
/// Same as `Set(files.filter(\.value.isBuildable).keys)`. Pre-computed because we need this pretty frequently in
397+
/// `SemanticIndexManager.filesToIndex`.
398+
let buildableSourceFiles: Set<DocumentURI>
399+
400+
internal init(
401+
files: [DocumentURI: SourceFileInfo],
402+
directories: [DocumentURI: (pathComponents: [String]?, info: SourceFileInfo)]
403+
) {
404+
self.files = files
405+
self.directories = directories
406+
self.buildableSourceFiles = Set(files.filter(\.value.isBuildable).keys)
407+
}
408+
395409
}
396410

397411
private let cachedSourceFilesAndDirectories = Cache<SourceFilesAndDirectoriesKey, SourceFilesAndDirectories>()
@@ -1153,6 +1167,13 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
11531167
}
11541168
}
11551169

1170+
/// Returns all source files in the project that are considered buildable.
1171+
///
1172+
/// - SeeAlso: Comment in `sourceFilesAndDirectories` for a definition of what `buildable` means.
1173+
package func buildableSourceFiles() async throws -> Set<DocumentURI> {
1174+
return try await sourceFilesAndDirectories().buildableSourceFiles
1175+
}
1176+
11561177
/// Get all files and directories that are known to the build system, ie. that are returned by a `buildTarget/sources`
11571178
/// request for any target in the project.
11581179
///

Sources/BuildSystemIntegration/TestBuildSystem.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,15 @@ package actor TestBuildSystem: MessageHandler {
3737
connectionToSourceKitLSP.send(OnBuildTargetDidChangeNotification(changes: nil))
3838
}
3939

40-
package nonisolated var supportsPreparation: Bool { false }
40+
private let initializeData: SourceKitInitializeBuildResponseData
4141

42-
package init(connectionToSourceKitLSP: any Connection) {
42+
package init(
43+
initializeData: SourceKitInitializeBuildResponseData = SourceKitInitializeBuildResponseData(
44+
sourceKitOptionsProvider: true
45+
),
46+
connectionToSourceKitLSP: any Connection
47+
) {
48+
self.initializeData = initializeData
4349
self.connectionToSourceKitLSP = connectionToSourceKitLSP
4450
}
4551

@@ -90,6 +96,8 @@ package actor TestBuildSystem: MessageHandler {
9096
handle(request, using: self.workspaceBuildTargetsRequest)
9197
case let request as WorkspaceWaitForBuildSystemUpdatesRequest:
9298
handle(request, using: self.workspaceWaitForBuildSystemUpdatesRequest)
99+
case let request as BuildTargetPrepareRequest:
100+
handle(request, using: self.prepareTarget)
93101
default:
94102
reply(.failure(ResponseError.methodNotFound(type(of: request).method)))
95103
}
@@ -101,7 +109,8 @@ package actor TestBuildSystem: MessageHandler {
101109
version: "",
102110
bspVersion: "2.2.0",
103111
capabilities: BuildServerCapabilities(),
104-
data: nil
112+
dataKind: .sourceKit,
113+
data: initializeData.encodeToLSPAny()
105114
)
106115
}
107116

@@ -148,6 +157,10 @@ package actor TestBuildSystem: MessageHandler {
148157
return buildSettingsByFile[request.textDocument.uri]
149158
}
150159

160+
func prepareTarget(_ request: BuildTargetPrepareRequest) async throws -> VoidResponse {
161+
return VoidResponse()
162+
}
163+
151164
package func waitForBuildSystemUpdates(request: WorkspaceWaitForBuildSystemUpdatesRequest) async -> VoidResponse {
152165
return VoidResponse()
153166
}

Sources/SemanticIndex/CheckedIndex.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if compiler(>=6)
14-
import Foundation
14+
package import Foundation
1515
@preconcurrency package import IndexStoreDB
1616
package import LanguageServerProtocol
1717
import SKLogging
@@ -188,6 +188,20 @@ package final class CheckedIndex {
188188
return checker.fileHasInMemoryModifications(uri)
189189
}
190190

191+
/// Determine the modification date of the file at the given location or, if it is a symlink, the maximum modification
192+
/// time of any hop in the symlink change until the real file.
193+
///
194+
/// This uses the `CheckedIndex`'s mod date cache, so it doesn't require disk access if the modification date of the
195+
/// file has already been computed.
196+
///
197+
/// Returns `nil` if the modification date of the file could not be determined.
198+
package func modificationDate(of uri: DocumentURI) -> Date? {
199+
switch try? checker.modificationDate(of: uri) {
200+
case nil, .fileDoesNotExist: return nil
201+
case .date(let date): return date
202+
}
203+
}
204+
191205
/// If there are any definition occurrences of the given USR, return these.
192206
/// Otherwise return declaration occurrences.
193207
package func definitionOrDeclarationOccurrences(ofUSR usr: String) -> [SymbolOccurrence] {
@@ -327,7 +341,7 @@ private struct IndexOutOfDateChecker {
327341
private let checkLevel: IndexCheckLevel
328342

329343
/// The last modification time of a file. Can also represent the fact that the file does not exist.
330-
private enum ModificationTime {
344+
enum ModificationTime {
331345
case fileDoesNotExist
332346
case date(Date)
333347
}
@@ -495,7 +509,7 @@ private struct IndexOutOfDateChecker {
495509
}
496510
}
497511

498-
private mutating func modificationDate(of uri: DocumentURI) throws -> ModificationTime {
512+
mutating func modificationDate(of uri: DocumentURI) throws -> ModificationTime {
499513
if let cached = modTimeCache[uri] {
500514
return cached
501515
}

0 commit comments

Comments
 (0)