mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Merge pull request #1665 from ahoppen/another-asp
Migrate the remaining methods in `BuiltInBuildSystem` to be BSP-based
This commit is contained in:
@@ -81,7 +81,9 @@ public struct BuildTarget: Codable, Hashable, Sendable {
|
||||
tags: [BuildTargetTag],
|
||||
capabilities: BuildTargetCapabilities,
|
||||
languageIds: [Language],
|
||||
dependencies: [BuildTargetIdentifier]
|
||||
dependencies: [BuildTargetIdentifier],
|
||||
dataKind: BuildTargetDataKind? = nil,
|
||||
data: LSPAny? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.displayName = displayName
|
||||
@@ -90,6 +92,8 @@ public struct BuildTarget: Codable, Hashable, Sendable {
|
||||
self.capabilities = capabilities
|
||||
self.languageIds = languageIds
|
||||
self.dependencies = dependencies
|
||||
self.dataKind = dataKind
|
||||
self.data = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,22 +181,52 @@ public struct BuildTargetDataKind: RawRepresentable, Codable, Hashable, Sendable
|
||||
}
|
||||
|
||||
/// `data` field must contain a CargoBuildTarget object.
|
||||
public static let cargo = "cargo"
|
||||
public static let cargo = BuildTargetDataKind(rawValue: "cargo")
|
||||
|
||||
/// `data` field must contain a CppBuildTarget object.
|
||||
public static let cpp = "cpp"
|
||||
public static let cpp = BuildTargetDataKind(rawValue: "cpp")
|
||||
|
||||
/// `data` field must contain a JvmBuildTarget object.
|
||||
public static let jvm = "jvm"
|
||||
public static let jvm = BuildTargetDataKind(rawValue: "jvm")
|
||||
|
||||
/// `data` field must contain a PythonBuildTarget object.
|
||||
public static let python = "python"
|
||||
public static let python = BuildTargetDataKind(rawValue: "python")
|
||||
|
||||
/// `data` field must contain a SbtBuildTarget object.
|
||||
public static let sbt = "sbt"
|
||||
public static let sbt = BuildTargetDataKind(rawValue: "sbt")
|
||||
|
||||
/// `data` field must contain a ScalaBuildTarget object.
|
||||
public static let scala = "scala"
|
||||
public static let scala = BuildTargetDataKind(rawValue: "scala")
|
||||
|
||||
/// `data` field must contain a SourceKitBuildTarget object.
|
||||
public static let sourceKit = BuildTargetDataKind(rawValue: "sourceKit")
|
||||
}
|
||||
|
||||
public struct SourceKitBuildTarget: LSPAnyCodable, Codable {
|
||||
/// The toolchain that should be used to build this target. The URI should point to the directory that contains the
|
||||
/// `usr` directory. On macOS, this is typically a bundle ending in `.xctoolchain`. If the toolchain is installed to
|
||||
/// `/` on Linux, the toolchain URI would point to `/`.
|
||||
///
|
||||
/// If no toolchain is given, SourceKit-LSP will pick a toolchain to use for this target.
|
||||
public var toolchain: URI?
|
||||
|
||||
public init(toolchain: URI? = nil) {
|
||||
self.toolchain = toolchain
|
||||
}
|
||||
|
||||
public init(fromLSPDictionary dictionary: [String: LanguageServerProtocol.LSPAny]) {
|
||||
if case .string(let toolchain) = dictionary[CodingKeys.toolchain.stringValue] {
|
||||
self.toolchain = try? URI(string: toolchain)
|
||||
}
|
||||
}
|
||||
|
||||
public func encodeToLSPAny() -> LanguageServerProtocol.LSPAny {
|
||||
var result: [String: LSPAny] = [:]
|
||||
if let toolchain {
|
||||
result[CodingKeys.toolchain.stringValue] = .string(toolchain.stringValue)
|
||||
}
|
||||
return .dictionary(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// The build target output paths request is sent from the client to the server
|
||||
|
||||
@@ -10,7 +10,8 @@ add_library(BuildServerProtocol STATIC
|
||||
PrepareTargetsRequest.swift
|
||||
RegisterForChangeNotifications.swift
|
||||
ShutdownBuild.swift
|
||||
SourceKitOptionsRequest.swift)
|
||||
SourceKitOptionsRequest.swift
|
||||
WaitForBuildSystemUpdates.swift)
|
||||
set_target_properties(BuildServerProtocol PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
|
||||
target_link_libraries(BuildServerProtocol PRIVATE
|
||||
|
||||
@@ -104,7 +104,7 @@ public struct InitializeBuildResponseDataKind: RawRepresentable, Hashable, Codab
|
||||
}
|
||||
|
||||
/// `data` field must contain a `SourceKitInitializeBuildResponseData` object.
|
||||
public static let sourceKit = InitializeBuildResponseDataKind(rawValue: "sourcekit")
|
||||
public static let sourceKit = InitializeBuildResponseDataKind(rawValue: "sourceKit")
|
||||
}
|
||||
|
||||
public struct SourceKitInitializeBuildResponseData: LSPAnyCodable, Codable, Sendable {
|
||||
|
||||
25
Sources/BuildServerProtocol/WaitForBuildSystemUpdates.swift
Normal file
25
Sources/BuildServerProtocol/WaitForBuildSystemUpdates.swift
Normal file
@@ -0,0 +1,25 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import LanguageServerProtocol
|
||||
|
||||
/// This request is a no-op and doesn't have any effects.
|
||||
///
|
||||
/// If the build system is currently updating the build graph, this request should return after those updates have
|
||||
/// finished processing.
|
||||
public struct WaitForBuildSystemUpdatesRequest: RequestType, Hashable {
|
||||
public typealias Response = VoidResponse
|
||||
|
||||
public static let method: String = "workspace/waitForBuildSystemUpdates"
|
||||
|
||||
public init() {}
|
||||
}
|
||||
@@ -330,15 +330,8 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
|
||||
)
|
||||
}
|
||||
|
||||
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
|
||||
return nil
|
||||
}
|
||||
|
||||
package func waitForUpToDateBuildGraph() async {}
|
||||
|
||||
package func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) {
|
||||
// BuildServerBuildSystem does not support syntactic test discovery or background indexing.
|
||||
// (https://github.com/swiftlang/sourcekit-lsp/issues/1173).
|
||||
package func waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest) async -> VoidResponse {
|
||||
return VoidResponse()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,4 +32,7 @@ package protocol BuildSystemManagerDelegate: AnyObject, Sendable {
|
||||
|
||||
/// Log the given message to the client's index log.
|
||||
func logMessageToIndexLog(taskID: IndexTaskID, message: String)
|
||||
|
||||
/// Notify the delegate that the list of source files in the build system might have changed.
|
||||
func sourceFilesDidChange() async
|
||||
}
|
||||
|
||||
@@ -25,15 +25,15 @@ import struct TSCBasic.AbsolutePath
|
||||
import os
|
||||
#endif
|
||||
|
||||
fileprivate class RequestCache<Request: RequestType & Hashable> {
|
||||
private var storage: [Request: Task<Request.Response, Error>] = [:]
|
||||
fileprivate class RequestCache<Request: RequestType & Hashable, Result: Sendable> {
|
||||
private var storage: [Request: Task<Result, Error>] = [:]
|
||||
|
||||
func get(
|
||||
_ key: Request,
|
||||
isolation: isolated any Actor = #isolation,
|
||||
compute: @Sendable @escaping (Request) async throws(Error) -> Request.Response
|
||||
) async throws(Error) -> Request.Response {
|
||||
let task: Task<Request.Response, Error>
|
||||
compute: @Sendable @escaping (Request) async throws(Error) -> Result
|
||||
) async throws(Error) -> Result {
|
||||
let task: Task<Result, Error>
|
||||
if let cached = storage[key] {
|
||||
task = cached
|
||||
} else {
|
||||
@@ -110,15 +110,15 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
/// Force-unwrapped optional because initializing it requires access to `self`.
|
||||
private var filesDependenciesUpdatedDebouncer: Debouncer<Set<DocumentURI>>! = nil
|
||||
|
||||
private var cachedTargetsForDocument = RequestCache<InverseSourcesRequest>()
|
||||
private var cachedTargetsForDocument = RequestCache<InverseSourcesRequest, InverseSourcesResponse>()
|
||||
|
||||
private var cachedSourceKitOptions = RequestCache<SourceKitOptionsRequest>()
|
||||
private var cachedSourceKitOptions = RequestCache<SourceKitOptionsRequest, SourceKitOptionsResponse?>()
|
||||
|
||||
private var cachedBuildTargets = RequestCache<BuildTargetsRequest>()
|
||||
private var cachedBuildTargets = RequestCache<
|
||||
BuildTargetsRequest, [BuildTargetIdentifier: (target: BuildTarget, depth: Int)]
|
||||
>()
|
||||
|
||||
private var cachedTargetSources = RequestCache<BuildTargetSourcesRequest>()
|
||||
|
||||
private var cachedTargetDepths: (buildTargets: [BuildTarget], depths: [BuildTargetIdentifier: Int])? = nil
|
||||
private var cachedTargetSources = RequestCache<BuildTargetSourcesRequest, BuildTargetSourcesResponse>()
|
||||
|
||||
/// The root of the project that this build system manages. For example, for SwiftPM packages, this is the folder
|
||||
/// containing Package.swift. For compilation databases it is the root folder based on which the compilation database
|
||||
@@ -176,6 +176,8 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
}
|
||||
await delegate.filesDependenciesUpdated(changedWatchedFiles)
|
||||
}
|
||||
|
||||
// FIXME: (BSP migration) Forward file watch patterns from this initialize request to the client
|
||||
initializeResult = Task { () -> InitializeBuildResponse? in
|
||||
guard let buildSystem else {
|
||||
return nil
|
||||
@@ -222,10 +224,9 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
if !options.backgroundIndexingOrDefault,
|
||||
events.contains(where: { $0.uri.fileURL?.pathExtension == "swiftmodule" })
|
||||
{
|
||||
let targets = await orLog("Getting build targets") {
|
||||
try await self.buildTargets()
|
||||
await orLog("Getting build targets") {
|
||||
targetsWithUpdatedDependencies.formUnion(try await self.buildTargets().keys)
|
||||
}
|
||||
targetsWithUpdatedDependencies.formUnion(targets?.map(\.id) ?? [])
|
||||
}
|
||||
|
||||
var filesWithUpdatedDependencies: Set<DocumentURI> = []
|
||||
@@ -271,9 +272,37 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
}
|
||||
|
||||
/// Returns the toolchain that should be used to process the given document.
|
||||
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
|
||||
if let toolchain = await buildSystem?.underlyingBuildSystem.toolchain(for: uri, language) {
|
||||
return toolchain
|
||||
package func toolchain(
|
||||
for uri: DocumentURI,
|
||||
in target: BuildTargetIdentifier?,
|
||||
language: Language
|
||||
) async -> Toolchain? {
|
||||
let toolchainPath = await orLog("Getting toolchain from build targets") { () -> AbsolutePath? in
|
||||
guard let target else {
|
||||
return nil
|
||||
}
|
||||
let targets = try await self.buildTargets()
|
||||
guard let target = targets[target]?.target else {
|
||||
logger.error("Failed to find target \(target.forLogging) to determine toolchain")
|
||||
return nil
|
||||
}
|
||||
guard target.dataKind == .sourceKit, case .dictionary(let data) = target.data else {
|
||||
return nil
|
||||
}
|
||||
guard let toolchain = SourceKitBuildTarget(fromLSPDictionary: data).toolchain else {
|
||||
return nil
|
||||
}
|
||||
guard let toolchainUrl = toolchain.fileURL else {
|
||||
logger.error("Toolchain is not a file URL")
|
||||
return nil
|
||||
}
|
||||
return try AbsolutePath(validating: toolchainUrl.path)
|
||||
}
|
||||
if let toolchainPath {
|
||||
if let toolchain = await self.toolchainRegistry.toolchain(withPath: toolchainPath) {
|
||||
return toolchain
|
||||
}
|
||||
logger.error("Toolchain at \(toolchainPath) not registered in toolchain registry.")
|
||||
}
|
||||
|
||||
switch language {
|
||||
@@ -484,15 +513,14 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
}
|
||||
|
||||
package func waitForUpToDateBuildGraph() async {
|
||||
await self.buildSystem?.underlyingBuildSystem.waitForUpToDateBuildGraph()
|
||||
await orLog("Waiting for build system updates") {
|
||||
let _: VoidResponse? = try await self.buildSystem?.send(WaitForBuildSystemUpdatesRequest())
|
||||
}
|
||||
}
|
||||
|
||||
/// The root targets of the project have depth of 0 and all target dependencies have a greater depth than the target
|
||||
// itself.
|
||||
private func targetDepths(for buildTargets: [BuildTarget]) -> [BuildTargetIdentifier: Int] {
|
||||
if let cachedTargetDepths, cachedTargetDepths.buildTargets == buildTargets {
|
||||
return cachedTargetDepths.depths
|
||||
}
|
||||
var nonRoots: Set<BuildTargetIdentifier> = []
|
||||
for buildTarget in buildTargets {
|
||||
nonRoots.formUnion(buildTarget.dependencies)
|
||||
@@ -511,7 +539,6 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
cachedTargetDepths = (buildTargets, depths)
|
||||
return depths
|
||||
}
|
||||
|
||||
@@ -522,25 +549,25 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
///
|
||||
/// `nil` if the build system doesn't support topological sorting of targets.
|
||||
package func topologicalSort(of targets: [BuildTargetIdentifier]) async throws -> [BuildTargetIdentifier]? {
|
||||
guard let workspaceTargets = await orLog("Getting build targets for topological sort", { try await buildTargets() })
|
||||
guard let buildTargets = await orLog("Getting build targets for topological sort", { try await buildTargets() })
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let depths = targetDepths(for: workspaceTargets)
|
||||
return targets.sorted { (lhs: BuildTargetIdentifier, rhs: BuildTargetIdentifier) -> Bool in
|
||||
return depths[lhs, default: 0] > depths[rhs, default: 0]
|
||||
return (buildTargets[lhs]?.depth ?? 0) > (buildTargets[rhs]?.depth ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of targets that might depend on the given target and that need to be re-prepared when a file in
|
||||
/// `target` is modified.
|
||||
package func targets(dependingOn targetIds: Set<BuildTargetIdentifier>) async -> [BuildTargetIdentifier] {
|
||||
guard let buildTargets = await orLog("Getting build targets for dependencies", { try await self.buildTargets() })
|
||||
guard
|
||||
let buildTargets = await orLog("Getting build targets for dependencies", { try await self.buildTargets().values })
|
||||
else {
|
||||
return []
|
||||
}
|
||||
return buildTargets.filter { $0.dependencies.contains(anyIn: targetIds) }.map { $0.id }
|
||||
return buildTargets.filter { $0.target.dependencies.contains(anyIn: targetIds) }.map { $0.target.id }
|
||||
}
|
||||
|
||||
package func prepare(
|
||||
@@ -564,26 +591,46 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
self.watchedFiles[uri] = nil
|
||||
}
|
||||
|
||||
package func buildTargets() async throws -> [BuildTarget] {
|
||||
package func buildTargets() async throws -> [BuildTargetIdentifier: (target: BuildTarget, depth: Int)] {
|
||||
guard let buildSystem else {
|
||||
return []
|
||||
return [:]
|
||||
}
|
||||
|
||||
let request = BuildTargetsRequest()
|
||||
let response = try await cachedBuildTargets.get(request) { request in
|
||||
try await buildSystem.send(request)
|
||||
let result = try await cachedBuildTargets.get(request) { request in
|
||||
let buildTargets = try await buildSystem.send(request).targets
|
||||
let depths = await self.targetDepths(for: buildTargets)
|
||||
var result: [BuildTargetIdentifier: (target: BuildTarget, depth: Int)] = [:]
|
||||
result.reserveCapacity(buildTargets.count)
|
||||
for buildTarget in buildTargets {
|
||||
guard result[buildTarget.id] == nil else {
|
||||
logger.error("Found two targets with the same ID \(buildTarget.id)")
|
||||
continue
|
||||
}
|
||||
let depth: Int
|
||||
if let d = depths[buildTarget.id] {
|
||||
depth = d
|
||||
} else {
|
||||
logger.fault("Did not compute depth for target \(buildTarget.id)")
|
||||
depth = 0
|
||||
}
|
||||
result[buildTarget.id] = (buildTarget, depth)
|
||||
}
|
||||
return result
|
||||
}
|
||||
return response.targets
|
||||
return result
|
||||
}
|
||||
|
||||
package func sourceFiles(in targets: [BuildTargetIdentifier]) async throws -> [SourcesItem] {
|
||||
package func sourceFiles(in targets: some Sequence<BuildTargetIdentifier>) async throws -> [SourcesItem] {
|
||||
guard let buildSystem else {
|
||||
return []
|
||||
}
|
||||
|
||||
// FIXME: (BSP migration) If we have a cached request for a superset of the targets, serve the result from that
|
||||
// cache entry.
|
||||
let request = BuildTargetSourcesRequest.init(targets: targets)
|
||||
// Sort targets to help cache hits if we have two calls to `sourceFiles` with targets in different orders.
|
||||
let sortedTargets = targets.sorted { $0.uri.stringValue < $1.uri.stringValue }
|
||||
let request = BuildTargetSourcesRequest(targets: sortedTargets)
|
||||
let response = try await cachedTargetSources.get(request) { request in
|
||||
try await buildSystem.send(request)
|
||||
}
|
||||
@@ -595,9 +642,8 @@ package actor BuildSystemManager: BuiltInBuildSystemAdapterDelegate {
|
||||
// retrieving the source files for those targets.
|
||||
// FIXME: (BSP Migration) Handle source files that are in multiple targets
|
||||
let targets = try await self.buildTargets()
|
||||
let targetsById = Dictionary(elements: targets, keyedBy: \.id)
|
||||
let sourceFiles = try await self.sourceFiles(in: targets.map(\.id)).flatMap { sourcesItem in
|
||||
let target = targetsById[sourcesItem.target]
|
||||
let sourceFiles = try await self.sourceFiles(in: targets.keys).flatMap { sourcesItem in
|
||||
let target = targets[sourcesItem.target]?.target
|
||||
return sourcesItem.sources.map { sourceItem in
|
||||
SourceFileInfo(
|
||||
uri: sourceItem.uri,
|
||||
@@ -663,6 +709,7 @@ extension BuildSystemManager {
|
||||
// FIXME: (BSP Migration) Communicate that the build target has changed to the `BuildSystemManagerDelegate` and make
|
||||
// it responsible for figuring out which files are affected.
|
||||
await delegate?.fileBuildSettingsChanged(Set(watchedFiles.keys))
|
||||
await self.delegate?.sourceFilesDidChange()
|
||||
}
|
||||
|
||||
private func logMessage(notification: BuildServerProtocol.LogMessageNotification) async {
|
||||
|
||||
@@ -103,15 +103,5 @@ package protocol BuiltInBuildSystem: AnyObject, Sendable {
|
||||
func sourceKitOptions(request: SourceKitOptionsRequest) async throws -> SourceKitOptionsResponse?
|
||||
|
||||
/// Wait until the build graph has been loaded.
|
||||
func waitForUpToDateBuildGraph() async
|
||||
|
||||
/// The toolchain that should be used to open the given document.
|
||||
///
|
||||
/// If `nil` is returned, then the default toolchain for the given language is used.
|
||||
func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain?
|
||||
|
||||
/// 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 `sourceFiles`.
|
||||
func addSourceFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async
|
||||
func waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest) async -> VoidResponse
|
||||
}
|
||||
|
||||
@@ -165,6 +165,8 @@ package actor BuiltInBuildSystemAdapter: BuiltInBuildSystemMessageHandler {
|
||||
return try await handle(request, underlyingBuildSystem.prepare)
|
||||
case let request as SourceKitOptionsRequest:
|
||||
return try await handle(request, underlyingBuildSystem.sourceKitOptions)
|
||||
case let request as WaitForBuildSystemUpdatesRequest:
|
||||
return try await handle(request, underlyingBuildSystem.waitForUpBuildSystemUpdates)
|
||||
default:
|
||||
throw ResponseError.methodNotFound(R.method)
|
||||
}
|
||||
|
||||
@@ -153,12 +153,10 @@ extension CompilationDatabaseBuildSystem: BuiltInBuildSystem {
|
||||
)
|
||||
}
|
||||
|
||||
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
|
||||
return nil
|
||||
package func waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest) async -> VoidResponse {
|
||||
return VoidResponse()
|
||||
}
|
||||
|
||||
package func waitForUpToDateBuildGraph() async {}
|
||||
|
||||
private func database(for uri: DocumentURI) -> CompilationDatabase? {
|
||||
if let url = uri.fileURL, let path = try? AbsolutePath(validating: url.path) {
|
||||
return database(for: path)
|
||||
@@ -208,8 +206,4 @@ extension CompilationDatabaseBuildSystem: BuiltInBuildSystem {
|
||||
await testFilesDidChangeCallback()
|
||||
}
|
||||
}
|
||||
|
||||
package func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {
|
||||
testFilesDidChangeCallbacks.append(callback)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,12 @@ extension BuildTargetIdentifier {
|
||||
return (target, runDestination)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension TSCBasic.AbsolutePath {
|
||||
var asURI: DocumentURI? {
|
||||
DocumentURI(self.asURL)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let preparationTaskID: AtomicUInt32 = AtomicUInt32(initialValue: 0)
|
||||
@@ -531,7 +536,9 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
|
||||
capabilities: BuildTargetCapabilities(),
|
||||
// Be conservative with the languages that might be used in the target. SourceKit-LSP doesn't use this property.
|
||||
languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift],
|
||||
dependencies: self.targetDependencies[targetId, default: []].sorted { $0.uri.stringValue < $1.uri.stringValue }
|
||||
dependencies: self.targetDependencies[targetId, default: []].sorted { $0.uri.stringValue < $1.uri.stringValue },
|
||||
dataKind: .sourceKit,
|
||||
data: SourceKitBuildTarget(toolchain: toolchain.path?.asURI).encodeToLSPAny()
|
||||
)
|
||||
}
|
||||
return BuildTargetsResponse(targets: targets)
|
||||
@@ -595,10 +602,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
|
||||
)
|
||||
}
|
||||
|
||||
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
|
||||
return toolchain
|
||||
}
|
||||
|
||||
package func targets(for uri: DocumentURI) -> [BuildTargetIdentifier] {
|
||||
guard let url = uri.fileURL, let path = try? AbsolutePath(validating: url.path) else {
|
||||
// We can't determine targets for non-file URIs.
|
||||
@@ -626,8 +629,9 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
|
||||
return InverseSourcesResponse(targets: targets(for: request.textDocument.uri))
|
||||
}
|
||||
|
||||
package func waitForUpToDateBuildGraph() async {
|
||||
package func waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest) async -> VoidResponse {
|
||||
await self.packageLoadingQueue.async {}.valuePropagatingCancellation
|
||||
return VoidResponse()
|
||||
}
|
||||
|
||||
package func prepare(request: PrepareTargetsRequest) async throws -> VoidResponse {
|
||||
@@ -791,10 +795,6 @@ extension SwiftPMBuildSystem: BuildSystemIntegration.BuiltInBuildSystem {
|
||||
}
|
||||
}
|
||||
|
||||
package func addSourceFilesDidChangeCallback(_ callback: @Sendable @escaping () async -> Void) async {
|
||||
testFilesDidChangeCallbacks.append(callback)
|
||||
}
|
||||
|
||||
/// Retrieve settings for a package manifest (Package.swift).
|
||||
private func settings(forPackageManifest path: AbsolutePath) throws -> SourceKitOptionsResponse? {
|
||||
let compilerArgs = workspace.interpreterFlags(for: path.parentDirectory) + [path.pathString]
|
||||
|
||||
@@ -70,15 +70,11 @@ package actor TestBuildSystem: BuiltInBuildSystem {
|
||||
return buildSettingsByFile[request.textDocument.uri]
|
||||
}
|
||||
|
||||
package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
|
||||
return nil
|
||||
package func waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest) async -> VoidResponse {
|
||||
return VoidResponse()
|
||||
}
|
||||
|
||||
package func waitForUpToDateBuildGraph() async {}
|
||||
|
||||
package func topologicalSort(of targets: [BuildTargetIdentifier]) -> [BuildTargetIdentifier]? {
|
||||
return nil
|
||||
}
|
||||
|
||||
package func addSourceFilesDidChangeCallback(_ callback: @escaping () async -> Void) async {}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ package struct UpdateIndexStoreTaskDescription: IndexTaskDescription {
|
||||
logger.error("Not indexing \(file.forLogging) because it has fallback compiler arguments")
|
||||
return
|
||||
}
|
||||
guard let toolchain = await buildSystemManager.toolchain(for: file.mainFile, language) else {
|
||||
guard let toolchain = await buildSystemManager.toolchain(for: file.mainFile, in: target, language: language) else {
|
||||
logger.error(
|
||||
"Not updating index store for \(file.forLogging) because no toolchain could be determined for the document"
|
||||
)
|
||||
|
||||
@@ -573,9 +573,16 @@ package actor SourceKitLSPServer {
|
||||
return service
|
||||
}
|
||||
|
||||
guard let toolchain = await workspace.buildSystemManager.toolchain(for: uri, language),
|
||||
let service = await languageService(for: toolchain, language, in: workspace)
|
||||
else {
|
||||
let toolchain = await workspace.buildSystemManager.toolchain(
|
||||
for: uri,
|
||||
in: workspace.buildSystemManager.canonicalTarget(for: uri),
|
||||
language: language
|
||||
)
|
||||
guard let toolchain else {
|
||||
logger.error("Failed to determine toolchain for \(uri)")
|
||||
return nil
|
||||
}
|
||||
guard let service = await languageService(for: toolchain, language, in: workspace) else {
|
||||
logger.error("Failed to create language service for \(uri)")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -130,15 +130,6 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate {
|
||||
await indexDelegate?.addMainFileChangedCallback { [weak self] in
|
||||
await self?.buildSystemManager.mainFilesChanged()
|
||||
}
|
||||
await buildSystemManager.buildSystem?.underlyingBuildSystem.addSourceFilesDidChangeCallback { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let testFiles = await orLog("Getting test files", { try await self.buildSystemManager.testFiles() }) else {
|
||||
return
|
||||
}
|
||||
await self.syntacticTestIndex.listOfTestFilesDidChange(testFiles)
|
||||
}
|
||||
// Trigger an initial population of `syntacticTestIndex`.
|
||||
if let testFiles = await orLog("Getting initial test files", { try await self.buildSystemManager.testFiles() }) {
|
||||
await syntacticTestIndex.listOfTestFilesDidChange(testFiles)
|
||||
@@ -328,6 +319,11 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate {
|
||||
package func logMessageToIndexLog(taskID: IndexTaskID, message: String) {
|
||||
self.logMessageToIndexLogCallback(taskID, message)
|
||||
}
|
||||
|
||||
package func sourceFilesDidChange() async {
|
||||
let testFiles = await orLog("Getting test files") { try await buildSystemManager.testFiles() } ?? []
|
||||
await syntacticTestIndex.listOfTestFilesDidChange(testFiles)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper around a workspace that isn't being retained.
|
||||
|
||||
@@ -406,4 +406,6 @@ private actor BSMDelegate: BuildSystemManagerDelegate {
|
||||
func buildTargetsChanged(_ changes: [BuildTargetEvent]?) async {}
|
||||
|
||||
nonisolated func logMessageToIndexLog(taskID: BuildSystemIntegration.IndexTaskID, message: String) {}
|
||||
|
||||
func sourceFilesDidChange() async {}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ fileprivate extension SwiftPMBuildSystem {
|
||||
request: SourceKitOptionsRequest(textDocument: TextDocumentIdentifier(uri: uri), target: target)
|
||||
)
|
||||
}
|
||||
|
||||
func waitForUpToDateBuildGraph() async {
|
||||
let _: VoidResponse = await self.waitForUpBuildSystemUpdates(request: WaitForBuildSystemUpdatesRequest())
|
||||
}
|
||||
}
|
||||
|
||||
final class SwiftPMBuildSystemTests: XCTestCase {
|
||||
|
||||
Reference in New Issue
Block a user