Skip to content

When the build system sends an update for build targets, update the index for the files in those targets #2013

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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