Skip to content

Address review comments for BSP implementation #1817

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 3 commits into from
Nov 14, 2024
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 @@ -17,7 +17,7 @@ import LanguageServerProtocol
#endif

/// The build target sources request is sent from the client to the server to
/// query for the list of text documents and directories that are belong to a
/// query for the list of text documents and directories that belong to a
/// build target. The sources response must not include sources that are
/// external to the workspace.
public struct BuildTargetSourcesRequest: RequestType, Hashable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public struct BuildTarget: Codable, Hashable, Sendable {
/// A human readable name for this target.
/// May be presented in the user interface.
/// Should be unique if possible.
/// The id.uri is used if None.
/// The id.uri is used if `nil`.
public var displayName: String?

/// The directory where this target belongs to. Multiple build targets are
Expand Down
28 changes: 14 additions & 14 deletions Sources/BuildSystemIntegration/BuildSystemManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private enum BuildSystemAdapter {
}
}

private extension BuildSystemKind {
private extension BuildSystemSpec {
private static func createBuiltInBuildSystemAdapter(
projectRoot: AbsolutePath,
messagesToSourceKitLSPHandler: any MessageHandler,
Expand Down Expand Up @@ -172,8 +172,8 @@ private extension BuildSystemKind {
buildSystemTestHooks testHooks: BuildSystemTestHooks,
messagesToSourceKitLSPHandler: any MessageHandler
) async -> BuildSystemAdapter? {
switch self {
case .buildServer(projectRoot: let projectRoot):
switch self.kind {
case .buildServer:
let buildSystem = await orLog("Creating external build system") {
try await ExternalBuildSystemAdapter(
projectRoot: projectRoot,
Expand All @@ -186,7 +186,7 @@ private extension BuildSystemKind {
}
logger.log("Created external build server at \(projectRoot.pathString)")
return .external(buildSystem)
case .compilationDatabase(projectRoot: let projectRoot):
case .compilationDatabase:
return await Self.createBuiltInBuildSystemAdapter(
projectRoot: projectRoot,
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
Expand All @@ -200,7 +200,7 @@ private extension BuildSystemKind {
connectionToSourceKitLSP: connectionToSourceKitLSP
)
}
case .swiftPM(projectRoot: let projectRoot):
case .swiftPM:
return await Self.createBuiltInBuildSystemAdapter(
projectRoot: projectRoot,
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
Expand All @@ -214,7 +214,7 @@ private extension BuildSystemKind {
testHooks: testHooks.swiftPMTestHooks
)
}
case .testBuildSystem(projectRoot: let projectRoot):
case .testBuildSystem:
return await Self.createBuiltInBuildSystemAdapter(
projectRoot: projectRoot,
messagesToSourceKitLSPHandler: messagesToSourceKitLSPHandler,
Expand Down Expand Up @@ -349,7 +349,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
}

package init(
buildSystemKind: BuildSystemKind?,
buildSystemSpec: BuildSystemSpec?,
toolchainRegistry: ToolchainRegistry,
options: SourceKitLSPOptions,
connectionToClient: BuildSystemManagerConnectionToClient,
Expand All @@ -358,8 +358,8 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
self.toolchainRegistry = toolchainRegistry
self.options = options
self.connectionToClient = connectionToClient
self.projectRoot = buildSystemKind?.projectRoot
self.buildSystemAdapter = await buildSystemKind?.createBuildSystemAdapter(
self.projectRoot = buildSystemSpec?.projectRoot
self.buildSystemAdapter = await buildSystemSpec?.createBuildSystemAdapter(
toolchainRegistry: toolchainRegistry,
options: options,
buildSystemTestHooks: buildSystemTestHooks,
Expand Down Expand Up @@ -388,8 +388,8 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
guard let buildSystemAdapter else {
return nil
}
guard let buildSystemKind else {
logger.fault("If we have a connectionToBuildSystem, we must have had a buildSystemKind")
guard let buildSystemSpec else {
logger.fault("If we have a connectionToBuildSystem, we must have had a buildSystemSpec")
return nil
}
let initializeResponse = await orLog("Initializing build system") {
Expand All @@ -398,7 +398,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
displayName: "SourceKit-LSP",
version: "",
bspVersion: "2.2.0",
rootUri: URI(buildSystemKind.projectRoot.asURL),
rootUri: URI(buildSystemSpec.projectRoot.asURL),
capabilities: BuildClientCapabilities(languageIds: [.c, .cpp, .objective_c, .objective_cpp, .swift])
)
)
Expand All @@ -411,7 +411,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
// the build server.
logger.log("Launched a legacy BSP server. Using push-based build settings model.")
let legacyBuildServer = await LegacyBuildServerBuildSystem(
projectRoot: buildSystemKind.projectRoot,
projectRoot: buildSystemSpec.projectRoot,
initializationData: initializeResponse,
externalBuildSystemAdapter
)
Expand Down Expand Up @@ -647,7 +647,7 @@ package actor BuildSystemManager: QueueBasedMessageHandler {
let sourcesItems = try await self.sourceFiles(in: [target])
let sourceFiles = sourcesItems.flatMap(\.sources)
var result: Language? = nil
for sourceFile in sourceFiles {
for sourceFile in sourceFiles where sourceFile.uri == document {
guard let language = sourceFile.sourceKitData?.language else {
continue
}
Expand Down
29 changes: 16 additions & 13 deletions Sources/BuildSystemIntegration/BuiltInBuildSystemAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,22 @@ import struct TSCBasic.AbsolutePath
import struct TSCBasic.RelativePath
#endif

package enum BuildSystemKind {
case buildServer(projectRoot: AbsolutePath)
case compilationDatabase(projectRoot: AbsolutePath)
case swiftPM(projectRoot: AbsolutePath)
case testBuildSystem(projectRoot: AbsolutePath)

package var projectRoot: AbsolutePath {
switch self {
case .buildServer(let projectRoot): return projectRoot
case .compilationDatabase(let projectRoot): return projectRoot
case .swiftPM(let projectRoot): return projectRoot
case .testBuildSystem(let projectRoot): return projectRoot
}
/// The details necessary to create a `BuildSystemAdapter`.
package struct BuildSystemSpec {
package enum Kind {
case buildServer
case compilationDatabase
case swiftPM
case testBuildSystem
}

package var kind: Kind

package var projectRoot: AbsolutePath

package init(kind: BuildSystemSpec.Kind, projectRoot: AbsolutePath) {
self.kind = kind
self.projectRoot = projectRoot
}
}

Expand Down
8 changes: 4 additions & 4 deletions Sources/BuildSystemIntegration/DetermineBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import struct TSCBasic.AbsolutePath
package func determineBuildSystem(
forWorkspaceFolder workspaceFolder: DocumentURI,
options: SourceKitLSPOptions
) -> BuildSystemKind? {
) -> BuildSystemSpec? {
var buildSystemPreference: [WorkspaceType] = [
.buildServer, .swiftPM, .compilationDatabase,
]
Expand All @@ -52,17 +52,17 @@ package func determineBuildSystem(
switch buildSystemType {
case .buildServer:
if let projectRoot = ExternalBuildSystemAdapter.projectRoot(for: workspaceFolderPath, options: options) {
return .buildServer(projectRoot: projectRoot)
return BuildSystemSpec(kind: .buildServer, projectRoot: projectRoot)
}
case .compilationDatabase:
if let projectRoot = CompilationDatabaseBuildSystem.projectRoot(for: workspaceFolderPath, options: options) {
return .compilationDatabase(projectRoot: projectRoot)
return BuildSystemSpec(kind: .compilationDatabase, projectRoot: projectRoot)
}
case .swiftPM:
if let projectRootURL = SwiftPMBuildSystem.projectRoot(for: workspaceFolderUrl, options: options),
let projectRoot = try? AbsolutePath(validating: projectRootURL.filePath)
{
return .swiftPM(projectRoot: projectRoot)
return BuildSystemSpec(kind: .swiftPM, projectRoot: projectRoot)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/SourceKitLSP/SharedWorkDoneProgressManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ extension WorkDoneProgressManager {
actor SharedWorkDoneProgressManager {
private weak var sourceKitLSPServer: SourceKitLSPServer?

/// The number of in-progress operations. When greater than 0 `workDoneProgress` non-nil and a work done progress is
/// displayed to the user.
/// The number of in-progress operations. When greater than 0 `workDoneProgress` is non-nil and a work done progress
/// is displayed to the user.
private var inProgressOperations = 0
private var workDoneProgress: WorkDoneProgressManager?

Expand Down
53 changes: 25 additions & 28 deletions Sources/SourceKitLSP/SourceKitLSPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,16 @@ package actor SourceKitLSPServer {
// was added to it and thus currently doesn't know that it can handle that file. In that case, we shouldn't open
// a new workspace for the same root. Instead, the existing workspace's build system needs to be reloaded.
let uri = DocumentURI(url)
guard let buildSystemKind = determineBuildSystem(forWorkspaceFolder: uri, options: self.options) else {
guard let buildSystemSpec = determineBuildSystem(forWorkspaceFolder: uri, options: self.options) else {
continue
}
guard !projectRoots.contains(buildSystemKind.projectRoot) else {
guard !projectRoots.contains(buildSystemSpec.projectRoot) else {
continue
}
guard
let workspace = await orLog(
"Creating workspace",
{ try await createWorkspace(workspaceFolder: uri, buildSystemKind: buildSystemKind) }
{ try await createWorkspace(workspaceFolder: uri, buildSystemSpec: buildSystemSpec) }
)
else {
continue
Expand Down Expand Up @@ -809,7 +809,7 @@ extension SourceKitLSPServer {
/// If the build system that was determined for the workspace does not satisfy `condition`, `nil` is returned.
private func createWorkspace(
workspaceFolder: DocumentURI,
buildSystemKind: BuildSystemKind?
buildSystemSpec: BuildSystemSpec?
) async throws -> Workspace {
guard let capabilityRegistry = capabilityRegistry else {
struct NoCapabilityRegistryError: Error {}
Expand All @@ -833,7 +833,7 @@ extension SourceKitLSPServer {
documentManager: self.documentManager,
rootUri: workspaceFolder,
capabilityRegistry: capabilityRegistry,
buildSystemKind: buildSystemKind,
buildSystemSpec: buildSystemSpec,
toolchainRegistry: self.toolchainRegistry,
options: options,
testHooks: testHooks,
Expand All @@ -856,6 +856,15 @@ extension SourceKitLSPServer {
return workspace
}

/// Determines the build system for the given workspace folder and creates a `Workspace` that uses this inferred build
/// system.
private func createWorkspaceWithInferredBuildSystem(workspaceFolder: DocumentURI) async throws -> Workspace {
return try await self.createWorkspace(
workspaceFolder: workspaceFolder,
buildSystemSpec: determineBuildSystem(forWorkspaceFolder: workspaceFolder, options: self.options)
)
}

func initialize(_ req: InitializeRequest) async throws -> InitializeResult {
logger.logFullObjectInMultipleLogMessages(header: "Initialize request", AnyRequestType(request: req))
// If the client can handle `PeekDocumentsRequest`, they can enable the
Expand Down Expand Up @@ -916,34 +925,25 @@ extension SourceKitLSPServer {
if let workspaceFolders = req.workspaceFolders {
self.workspacesAndIsImplicit += await workspaceFolders.asyncCompactMap { workspaceFolder in
await orLog("Creating workspace from workspaceFolders") {
let workspace = try await self.createWorkspace(
workspaceFolder: workspaceFolder.uri,
buildSystemKind: determineBuildSystem(forWorkspaceFolder: workspaceFolder.uri, options: self.options)
return (
workspace: try await self.createWorkspaceWithInferredBuildSystem(workspaceFolder: workspaceFolder.uri),
isImplicit: false
)
return (workspace: workspace, isImplicit: false)
}
}
} else if let uri = req.rootURI {
let workspace = await orLog("Creating workspace from rootURI") {
try await self.createWorkspace(
workspaceFolder: uri,
buildSystemKind: determineBuildSystem(forWorkspaceFolder: uri, options: self.options)
await orLog("Creating workspace from rootURI") {
self.workspacesAndIsImplicit.append(
(workspace: try await self.createWorkspaceWithInferredBuildSystem(workspaceFolder: uri), isImplicit: false)
)
}
if let workspace {
self.workspacesAndIsImplicit.append((workspace: workspace, isImplicit: false))
}
} else if let path = req.rootPath {
let uri = DocumentURI(URL(fileURLWithPath: path))
let workspace = await orLog("Creating workspace from rootPath") {
try await self.createWorkspace(
workspaceFolder: uri,
buildSystemKind: determineBuildSystem(forWorkspaceFolder: uri, options: self.options)
await orLog("Creating workspace from rootPath") {
self.workspacesAndIsImplicit.append(
(workspace: try await self.createWorkspaceWithInferredBuildSystem(workspaceFolder: uri), isImplicit: false)
)
}
if let workspace {
self.workspacesAndIsImplicit.append((workspace: workspace, isImplicit: false))
}
}

if self.workspaces.isEmpty {
Expand All @@ -955,7 +955,7 @@ extension SourceKitLSPServer {
documentManager: self.documentManager,
rootUri: req.rootURI,
capabilityRegistry: self.capabilityRegistry!,
buildSystemKind: nil,
buildSystemSpec: nil,
toolchainRegistry: self.toolchainRegistry,
options: options,
testHooks: testHooks,
Expand Down Expand Up @@ -1340,10 +1340,7 @@ extension SourceKitLSPServer {
if let added = notification.event.added {
let newWorkspaces = await added.asyncCompactMap { workspaceFolder in
await orLog("Creating workspace after workspace folder change") {
try await self.createWorkspace(
workspaceFolder: workspaceFolder.uri,
buildSystemKind: determineBuildSystem(forWorkspaceFolder: workspaceFolder.uri, options: self.options)
)
try await self.createWorkspaceWithInferredBuildSystem(workspaceFolder: workspaceFolder.uri)
}
}
self.workspacesAndIsImplicit += newWorkspaces.map { (workspace: $0, isImplicit: false) }
Expand Down
6 changes: 3 additions & 3 deletions Sources/SourceKitLSP/Workspace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate {
documentManager: DocumentManager,
rootUri: DocumentURI?,
capabilityRegistry: CapabilityRegistry,
buildSystemKind: BuildSystemKind?,
buildSystemSpec: BuildSystemSpec?,
toolchainRegistry: ToolchainRegistry,
options: SourceKitLSPOptions,
testHooks: TestHooks,
Expand Down Expand Up @@ -222,15 +222,15 @@ package final class Workspace: Sendable, BuildSystemManagerDelegate {
}

let buildSystemManager = await BuildSystemManager(
buildSystemKind: buildSystemKind,
buildSystemSpec: buildSystemSpec,
toolchainRegistry: toolchainRegistry,
options: options,
connectionToClient: ConnectionToClient(sourceKitLSPServer: sourceKitLSPServer),
buildSystemTestHooks: testHooks.buildSystemTestHooks
)

logger.log(
"Created workspace at \(rootUri.forLogging) with project root \(buildSystemKind?.projectRoot.pathString ?? "<nil>")"
"Created workspace at \(rootUri.forLogging) with project root \(buildSystemSpec?.projectRoot.pathString ?? "<nil>")"
)

var index: IndexStoreDB? = nil
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftExtensions/Sequence+AsyncMap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extension Sequence {

/// Just like `Sequence.first` but allows an `async` predicate function.
package func asyncFirst(
@_inheritActorContext _ predicate: @Sendable (Element) async throws -> Bool
@_inheritActorContext where predicate: @Sendable (Element) async throws -> Bool
) async rethrows -> Element? {
for element in self {
if try await predicate(element) {
Expand All @@ -86,6 +86,6 @@ extension Sequence {
package func asyncContains(
@_inheritActorContext where predicate: @Sendable (Element) async throws -> Bool
) async rethrows -> Bool {
return try await asyncFirst(predicate) != nil
return try await asyncFirst(where: predicate) != nil
}
}
Loading