Skip to content

Migrate defaultLanguage(for:) and filesDependenciesUpdated to BSP and use InitializeRequest from BSP to communicate static options #1663

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
Sep 12, 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
27 changes: 26 additions & 1 deletion Sources/BuildServerProtocol/BuildTargetSourcesRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,30 @@ public struct SourceItemDataKind: RawRepresentable, Codable, Hashable, Sendable
}

/// `data` field must contain a JvmSourceItemData object.
public static let jvm = "jvm"
public static let jvm = SourceItemDataKind(rawValue: "jvm")

/// `data` field must contain a `SourceKitSourceItemData` object.
public static let sourceKit = SourceItemDataKind(rawValue: "sourceKit")
}

public struct SourceKitSourceItemData: LSPAnyCodable, Codable {
public var language: Language?

public init(language: Language? = nil) {
self.language = language
}

public init?(fromLSPDictionary dictionary: [String: LanguageServerProtocol.LSPAny]) {
if case .string(let language) = dictionary[CodingKeys.language.stringValue] {
self.language = Language(rawValue: language)
}
}

public func encodeToLSPAny() -> LanguageServerProtocol.LSPAny {
var result: [String: LSPAny] = [:]
if let language {
result[CodingKeys.language.stringValue] = .string(language.rawValue)
}
return .dictionary(result)
}
}
173 changes: 160 additions & 13 deletions Sources/BuildServerProtocol/InitializeBuild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import LanguageServerProtocol

public struct InitializeBuildRequestDataKind: RawRepresentable, Hashable, Codable, Sendable {
public let rawValue: String

public init(rawValue: String) {
self.rawValue = rawValue
}
}

/// Like the language server protocol, the initialize request is sent
/// as the first request from the client to the server. If the server
/// receives a request or notification before the initialize request
Expand All @@ -25,9 +34,9 @@ import LanguageServerProtocol
/// Until the server has responded to the initialize request with an
/// InitializeBuildResult, the client must not send any additional
/// requests or notifications to the server.
public struct InitializeBuild: RequestType, Hashable {
public struct InitializeBuildRequest: RequestType, Hashable {
public static let method: String = "build/initialize"
public typealias Response = InitializeBuildResult
public typealias Response = InitializeBuildResponse

/// Name of the client
public var displayName: String
Expand All @@ -44,18 +53,28 @@ public struct InitializeBuild: RequestType, Hashable {
/// The capabilities of the client
public var capabilities: BuildClientCapabilities

/// Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified. */
public var dataKind: InitializeBuildRequestDataKind?

/// Additional metadata about the client
public var data: LSPAny?

public init(
displayName: String,
version: String,
bspVersion: String,
rootUri: URI,
capabilities: BuildClientCapabilities
capabilities: BuildClientCapabilities,
dataKind: InitializeBuildRequestDataKind? = nil,
data: LSPAny? = nil
) {
self.displayName = displayName
self.version = version
self.bspVersion = bspVersion
self.rootUri = rootUri
self.capabilities = capabilities
self.dataKind = dataKind
self.data = data
}
}

Expand All @@ -66,12 +85,67 @@ public struct BuildClientCapabilities: Codable, Hashable, Sendable {
/// languages than those that appear in this list.
public var languageIds: [Language]

public init(languageIds: [Language]) {
/// Mirror capability to BuildServerCapabilities.jvmCompileClasspathProvider
/// The client will request classpath via `buildTarget/jvmCompileClasspath` so
/// it's safe to return classpath in ScalacOptionsItem empty. */
public var jvmCompileClasspathReceiver: Bool?

public init(languageIds: [Language], jvmCompileClasspathReceiver: Bool? = nil) {
self.languageIds = languageIds
self.jvmCompileClasspathReceiver = jvmCompileClasspathReceiver
}
}

public struct InitializeBuildResult: ResponseType, Hashable {
public struct InitializeBuildResponseDataKind: RawRepresentable, Hashable, Codable, Sendable {
public let rawValue: String

public init(rawValue: String) {
self.rawValue = rawValue
}

/// `data` field must contain a `SourceKitInitializeBuildResponseData` object.
public static let sourceKit = InitializeBuildResponseDataKind(rawValue: "sourcekit")
}

public struct SourceKitInitializeBuildResponseData: LSPAnyCodable, Codable, Sendable {
public var indexDatabasePath: String?
public var indexStorePath: String?
public var supportsPreparation: Bool?

public init(indexDatabasePath: String?, indexStorePath: String?, supportsPreparation: Bool?) {
self.indexDatabasePath = indexDatabasePath
self.indexStorePath = indexStorePath
self.supportsPreparation = supportsPreparation
}

public init?(fromLSPDictionary dictionary: [String: LanguageServerProtocol.LSPAny]) {
if case .string(let indexDatabasePath) = dictionary[CodingKeys.indexDatabasePath.stringValue] {
self.indexDatabasePath = indexDatabasePath
}
if case .string(let indexStorePath) = dictionary[CodingKeys.indexStorePath.stringValue] {
self.indexStorePath = indexStorePath
}
if case .bool(let supportsPreparation) = dictionary[CodingKeys.supportsPreparation.stringValue] {
self.supportsPreparation = supportsPreparation
}
}

public func encodeToLSPAny() -> LanguageServerProtocol.LSPAny {
var result: [String: LSPAny] = [:]
if let indexDatabasePath {
result[CodingKeys.indexDatabasePath.stringValue] = .string(indexDatabasePath)
}
if let indexStorePath {
result[CodingKeys.indexStorePath.stringValue] = .string(indexStorePath)
}
if let supportsPreparation {
result[CodingKeys.supportsPreparation.stringValue] = .bool(supportsPreparation)
}
return .dictionary(result)
}
}

public struct InitializeBuildResponse: ResponseType, Hashable {
/// Name of the server
public var displayName: String

Expand All @@ -84,6 +158,9 @@ public struct InitializeBuildResult: ResponseType, Hashable {
/// The capabilities of the build server
public var capabilities: BuildServerCapabilities

/// Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified.
public var dataKind: InitializeBuildResponseDataKind?

/// Optional metadata about the server
public var data: LSPAny?

Expand All @@ -92,41 +169,103 @@ public struct InitializeBuildResult: ResponseType, Hashable {
version: String,
bspVersion: String,
capabilities: BuildServerCapabilities,
dataKind: InitializeBuildResponseDataKind? = nil,
data: LSPAny? = nil
) {
self.displayName = displayName
self.version = version
self.bspVersion = bspVersion
self.capabilities = capabilities
self.dataKind = dataKind
self.data = data
}
}

public struct BuildServerCapabilities: Codable, Hashable, Sendable {
/// The languages the server supports compilation via method buildTarget/compile.
public var compileProvider: CompileProvider? = nil
public var compileProvider: CompileProvider?

/// The languages the server supports test execution via method buildTarget/test
public var testProvider: TestProvider? = nil
public var testProvider: TestProvider?

/// The languages the server supports run via method buildTarget/run
public var runProvider: RunProvider? = nil
public var runProvider: RunProvider?

/// The languages the server supports debugging via method debugSession/start.
public var debugProvider: DebugProvider?

/// The server can provide a list of targets that contain a
/// single text document via the method buildTarget/inverseSources
public var inverseSourcesProvider: Bool? = nil
public var inverseSourcesProvider: Bool?

/// The server provides sources for library dependencies
/// via method buildTarget/dependencySources
public var dependencySourcesProvider: Bool? = nil
public var dependencySourcesProvider: Bool?

/// The server provides all the resource dependencies
/// via method buildTarget/resources
public var resourcesProvider: Bool? = nil
public var resourcesProvider: Bool?

/// The server provides all output paths
/// via method buildTarget/outputPaths
public var outputPathsProvider: Bool?

/// The server sends notifications to the client on build
/// target change events via buildTarget/didChange
public var buildTargetChangedProvider: Bool? = nil
/// target change events via `buildTarget/didChange`
public var buildTargetChangedProvider: Bool?

/// The server can respond to `buildTarget/jvmRunEnvironment` requests with the
/// necessary information required to launch a Java process to run a main class.
public var jvmRunEnvironmentProvider: Bool?

/// The server can respond to `buildTarget/jvmTestEnvironment` requests with the
/// necessary information required to launch a Java process for testing or
/// debugging.
public var jvmTestEnvironmentProvider: Bool?

/// The server can respond to `workspace/cargoFeaturesState` and
/// `setCargoFeatures` requests. In other words, supports Cargo Features extension.
public var cargoFeaturesProvider: Bool?

/// Reloading the build state through workspace/reload is supported
public var canReload: Bool?

/// The server can respond to `buildTarget/jvmCompileClasspath` requests with the
/// necessary information about the target's classpath.
public var jvmCompileClasspathProvider: Bool?

public init(
compileProvider: CompileProvider? = nil,
testProvider: TestProvider? = nil,
runProvider: RunProvider? = nil,
debugProvider: DebugProvider? = nil,
inverseSourcesProvider: Bool? = nil,
dependencySourcesProvider: Bool? = nil,
resourcesProvider: Bool? = nil,
outputPathsProvider: Bool? = nil,
buildTargetChangedProvider: Bool? = nil,
jvmRunEnvironmentProvider: Bool? = nil,
jvmTestEnvironmentProvider: Bool? = nil,
cargoFeaturesProvider: Bool? = nil,
canReload: Bool? = nil,
jvmCompileClasspathProvider: Bool? = nil
) {
self.compileProvider = compileProvider
self.testProvider = testProvider
self.runProvider = runProvider
self.debugProvider = debugProvider
self.inverseSourcesProvider = inverseSourcesProvider
self.dependencySourcesProvider = dependencySourcesProvider
self.resourcesProvider = resourcesProvider
self.outputPathsProvider = outputPathsProvider
self.buildTargetChangedProvider = buildTargetChangedProvider
self.jvmRunEnvironmentProvider = jvmRunEnvironmentProvider
self.jvmTestEnvironmentProvider = jvmTestEnvironmentProvider
self.cargoFeaturesProvider = cargoFeaturesProvider
self.canReload = canReload
self.jvmCompileClasspathProvider = jvmCompileClasspathProvider
}

}

public struct CompileProvider: Codable, Hashable, Sendable {
Expand All @@ -153,6 +292,14 @@ public struct TestProvider: Codable, Hashable, Sendable {
}
}

public struct DebugProvider: Codable, Hashable, Sendable {
public var languageIds: [Language]

public init(languageIds: [Language]) {
self.languageIds = languageIds
}
}

public struct InitializedBuildNotification: NotificationType {
public static let method: String = "build/initialized"

Expand Down
2 changes: 1 addition & 1 deletion Sources/BuildServerProtocol/Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fileprivate let requestTypes: [_RequestType.Type] = [
BuildTargetOutputPaths.self,
BuildTargetsRequest.self,
BuildTargetSourcesRequest.self,
InitializeBuild.self,
InitializeBuildRequest.self,
InverseSourcesRequest.self,
RegisterForChanges.self,
ShutdownBuild.self,
Expand Down
14 changes: 1 addition & 13 deletions Sources/BuildSystemIntegration/BuildServerBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ package actor BuildServerBuildSystem: MessageHandler {
package private(set) var indexDatabasePath: AbsolutePath?
package private(set) var indexStorePath: AbsolutePath?

/// Delegate to handle any build system events.
package weak var delegate: BuildSystemDelegate?

/// - Note: Needed to set the delegate from a different actor isolation context
package func setDelegate(_ delegate: BuildSystemDelegate?) async {
self.delegate = delegate
}

package weak var messageHandler: BuiltInBuildSystemMessageHandler?

/// The build settings that have been received from the build server.
Expand Down Expand Up @@ -166,7 +158,7 @@ package actor BuildServerBuildSystem: MessageHandler {
Language.swift,
]

let initializeRequest = InitializeBuild(
let initializeRequest = InitializeBuildRequest(
displayName: "SourceKit-LSP",
version: "1.0",
bspVersion: "2.0",
Expand Down Expand Up @@ -338,10 +330,6 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
)
}

package func defaultLanguage(for document: DocumentURI) async -> Language? {
return nil
}

package func toolchain(for uri: DocumentURI, _ language: Language) async -> Toolchain? {
return nil
}
Expand Down
13 changes: 1 addition & 12 deletions Sources/BuildSystemIntegration/BuildSystemDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,10 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import BuildServerProtocol
import LanguageServerProtocol

/// Handles build system events, such as file build settings changes.
// FIXME: (BSP migration) The build system should exclusively communicate back to SourceKit-LSP using BSP and this protocol should be deleted.
package protocol BuildSystemDelegate: AnyObject, Sendable {
/// Notify the delegate that the dependencies of the given files have changed
/// and that ASTs may need to be refreshed. If the given set is empty, assume
/// that all watched files are affected.
///
/// The callee should refresh ASTs unless it is able to determine that a
/// refresh is not necessary.
func filesDependenciesUpdated(_ changedFiles: Set<DocumentURI>) async
}

/// Handles build system events, such as file build settings changes.
package protocol BuildSystemManagerDelegate: AnyObject, Sendable {
/// Notify the delegate that the given files' build settings have changed.
Expand Down
Loading