Skip to content

Migrate getting the list of all source files to BSP #1660

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 1 commit 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
101 changes: 101 additions & 0 deletions Sources/BuildServerProtocol/BuildTargetSourcesRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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

/// 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
/// build target. The sources response must not include sources that are
/// external to the workspace.
public struct BuildTargetSourcesRequest: RequestType, Hashable {
public static let method: String = "buildTarget/sources"
public typealias Response = BuildTargetSourcesResponse

public var targets: [BuildTargetIdentifier]

public init(targets: [BuildTargetIdentifier]) {
self.targets = targets
}
}

public struct BuildTargetSourcesResponse: ResponseType, Hashable {
public var items: [SourcesItem]

public init(items: [SourcesItem]) {
self.items = items
}
}

public struct SourcesItem: Codable, Hashable, Sendable {
public var target: BuildTargetIdentifier

/// The text documents and directories that belong to this build target.
public var sources: [SourceItem]

public init(target: BuildTargetIdentifier, sources: [SourceItem]) {
self.target = target
self.sources = sources
}
}

public struct SourceItem: Codable, Hashable, Sendable {
/// Either a text document or a directory. A directory entry must end with a
/// forward slash "/" and a directory entry implies that every nested text
/// document within the directory belongs to this source item.
public var uri: URI

/// Type of file of the source item, such as whether it is file or directory.
public var kind: SourceItemKind

/// Indicates if this source is automatically generated by the build and is
/// not intended to be manually edited by the user.
public var generated: Bool

/// 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: SourceItemDataKind?

/// Language-specific metadata about this source item.
public var data: LSPAny?

public init(
uri: URI,
kind: SourceItemKind,
generated: Bool,
dataKind: SourceItemDataKind? = nil,
data: LSPAny? = nil
) {
self.uri = uri
self.kind = kind
self.generated = generated
self.dataKind = dataKind
self.data = data
}
}

public enum SourceItemKind: Int, Codable, Hashable, Sendable {
/// The source item references a normal file.
case file = 1

/// The source item references a directory.
case directory = 2
}

public struct SourceItemDataKind: RawRepresentable, Codable, Hashable, Sendable {
public var rawValue: String

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

/// `data` field must contain a JvmSourceItemData object.
public static let jvm = "jvm"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,26 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import LanguageServerProtocol

public typealias URI = DocumentURI

/// The workspace build targets request is sent from the client to the server to
/// ask for the list of all available build targets in the workspace.
public struct BuildTargets: RequestType, Hashable {
public struct BuildTargetsRequest: RequestType, Hashable {
public static let method: String = "workspace/buildTargets"
public typealias Response = BuildTargetsResult
public typealias Response = BuildTargetsResponse

public init() {}
}

public struct BuildTargetsResult: ResponseType, Hashable {
public struct BuildTargetsResponse: ResponseType, Hashable {
public var targets: [BuildTarget]

public init(targets: [BuildTarget]) {
self.targets = targets
}
}

public struct BuildTarget: Codable, Hashable, Sendable {
Expand Down Expand Up @@ -52,16 +57,23 @@ public struct BuildTarget: Codable, Hashable, Sendable {
/// are free to define new tags for custom purposes.
public var tags: [BuildTargetTag]

/// The capabilities of this build target.
public var capabilities: BuildTargetCapabilities

/// The set of languages that this target contains.
/// The ID string for each language is defined in the LSP.
public var languageIds: [Language]

/// The direct upstream build target dependencies of this build target
public var dependencies: [BuildTargetIdentifier]

/// The capabilities of this build target.
public var capabilities: BuildTargetCapabilities

/// 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: BuildTargetDataKind?

/// Language-specific metadata about this target.
/// See ScalaBuildTarget as an example.
public var data: LSPAny?

public init(
id: BuildTargetIdentifier,
displayName: String?,
Expand Down Expand Up @@ -96,17 +108,13 @@ public struct BuildTargetTag: Codable, Hashable, RawRepresentable, Sendable {
self.rawValue = rawValue
}

/// Target contains re-usable functionality for downstream targets. May have
/// any combination of capabilities.
public static let library: Self = Self(rawValue: "library")

/// Target contains source code for producing any kind of application, may
/// have but does not require the `canRun` capability.
public static let application: Self = Self(rawValue: "application")

/// Target contains source code for testing purposes, may have but does not
/// require the `canTest` capability.
public static let test: Self = Self(rawValue: "test")
/// Target contains source code to measure performance of a program, may have
/// but does not require the `canRun` build target capability.
public static let benchmark: Self = Self(rawValue: "benchmark")

/// Target contains source code for integration testing purposes, may have
/// but does not require the `canTest` capability. The difference between
Expand All @@ -115,77 +123,76 @@ public struct BuildTargetTag: Codable, Hashable, RawRepresentable, Sendable {
/// execute.
public static let integrationTest: Self = Self(rawValue: "integration-test")

/// Target contains source code to measure performance of a program, may have
/// but does not require the `canRun` build target capability.
public static let benchmark: Self = Self(rawValue: "benchmark")
/// Target contains re-usable functionality for downstream targets. May have
/// any combination of capabilities.
public static let library: Self = Self(rawValue: "library")

/// Actions on the target such as build and test should only be invoked manually
/// and explicitly. For example, triggering a build on all targets in the workspace
/// should by default not include this target.
/// The original motivation to add the "manual" tag comes from a similar functionality
/// that exists in Bazel, where targets with this tag have to be specified explicitly
/// on the command line.
public static let manual: Self = Self(rawValue: "manual")

/// Target should be ignored by IDEs.
public static let noIDE: Self = Self(rawValue: "no-ide")

/// Target contains source code for testing purposes, may have but does not
/// require the `canTest` capability.
public static let test: Self = Self(rawValue: "test")

/// This is a target of a dependency from the project the user opened, eg. a target that builds a SwiftPM dependency.
///
/// **(BSP Extension)**
public static let dependency: Self = Self(rawValue: "dependency")
}

public struct BuildTargetCapabilities: Codable, Hashable, Sendable {
/// This target can be compiled by the BSP server.
public var canCompile: Bool
public var canCompile: Bool?

/// This target can be tested by the BSP server.
public var canTest: Bool
public var canTest: Bool?

/// This target can be run by the BSP server.
public var canRun: Bool
public var canRun: Bool?

/// This target can be debugged by the BSP server.
public var canDebug: Bool?

public init(canCompile: Bool, canTest: Bool, canRun: Bool) {
public init(canCompile: Bool? = nil, canTest: Bool? = nil, canRun: Bool? = nil, canDebug: Bool? = nil) {
self.canCompile = canCompile
self.canTest = canTest
self.canRun = canRun
self.canDebug = canDebug
}
}

/// 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
/// build target. The sources response must not include sources that are
/// external to the workspace.
public struct BuildTargetSources: RequestType, Hashable {
public static let method: String = "buildTarget/sources"
public typealias Response = BuildTargetSourcesResult

public var targets: [BuildTargetIdentifier]
public struct BuildTargetDataKind: RawRepresentable, Codable, Hashable, Sendable {
public var rawValue: String

public init(targets: [BuildTargetIdentifier]) {
self.targets = targets
public init(rawValue: String) {
self.rawValue = rawValue
}
}

public struct BuildTargetSourcesResult: ResponseType, Hashable {
public var items: [SourcesItem]
}

public struct SourcesItem: Codable, Hashable, Sendable {
public var target: BuildTargetIdentifier

/// The text documents and directories that belong to this build target.
public var sources: [SourceItem]
}
/// `data` field must contain a CargoBuildTarget object.
public static let cargo = "cargo"

public struct SourceItem: Codable, Hashable, Sendable {
/// Either a text document or a directory. A directory entry must end with a
/// forward slash "/" and a directory entry implies that every nested text
/// document within the directory belongs to this source item.
public var uri: URI
/// `data` field must contain a CppBuildTarget object.
public static let cpp = "cpp"

/// Type of file of the source item, such as whether it is file or directory.
public var kind: SourceItemKind
/// `data` field must contain a JvmBuildTarget object.
public static let jvm = "jvm"

/// Indicates if this source is automatically generated by the build and is
/// not intended to be manually edited by the user.
public var generated: Bool
}
/// `data` field must contain a PythonBuildTarget object.
public static let python = "python"

public enum SourceItemKind: Int, Codable, Hashable, Sendable {
/// The source item references a normal file.
case file = 1
/// `data` field must contain a SbtBuildTarget object.
public static let sbt = "sbt"

/// The source item references a directory.
case directory = 2
/// `data` field must contain a ScalaBuildTarget object.
public static let scala = "scala"
}

/// The build target output paths request is sent from the client to the server
Expand Down
3 changes: 2 additions & 1 deletion Sources/BuildServerProtocol/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_library(BuildServerProtocol STATIC
BuildTargets.swift
BuildTargetSourcesRequest.swift
BuildTargetsRequest.swift
DidChangeBuildTargetNotification.swift
DidChangeWatchedFilesNotification.swift
InitializeBuild.swift
Expand Down
4 changes: 2 additions & 2 deletions Sources/BuildServerProtocol/Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import LanguageServerProtocol

fileprivate let requestTypes: [_RequestType.Type] = [
BuildTargetOutputPaths.self,
BuildTargets.self,
BuildTargetSources.self,
BuildTargetsRequest.self,
BuildTargetSourcesRequest.self,
InitializeBuild.self,
InverseSourcesRequest.self,
RegisterForChanges.self,
Expand Down
49 changes: 33 additions & 16 deletions Sources/BuildSystemIntegration/BuildServerBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,39 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {

package nonisolated var supportsPreparation: Bool { false }

package func buildTargets(request: BuildTargetsRequest) async throws -> BuildTargetsResponse {
// TODO: (BSP migration) Forward this request to the BSP server
return BuildTargetsResponse(targets: [
BuildTarget(
id: .dummy,
displayName: "Compilation database",
baseDirectory: nil,
tags: [.test],
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: []
)
])
}

package func buildTargetSources(request: BuildTargetSourcesRequest) async throws -> BuildTargetSourcesResponse {
// BuildServerBuildSystem does not support syntactic test discovery or background indexing.
// (https://github.com/swiftlang/sourcekit-lsp/issues/1173).
// TODO: (BSP migration) Forward this request to the BSP server
return BuildTargetSourcesResponse(items: [])
}

package func inverseSources(request: InverseSourcesRequest) -> InverseSourcesResponse {
return InverseSourcesResponse(targets: [BuildTargetIdentifier.dummy])
}

package func didChangeWatchedFiles(notification: BuildServerProtocol.DidChangeWatchedFilesNotification) {}

package func prepare(request: PrepareTargetsRequest) async throws -> VoidResponse {
throw PrepareNotSupportedError()
}

package func sourceKitOptions(request: SourceKitOptionsRequest) async throws -> SourceKitOptionsResponse? {
// FIXME: (BSP Migration) If the BSP server supports it, send the `SourceKitOptions` request to it. Only do the
// `RegisterForChanges` dance if we are in the legacy mode.
Expand Down Expand Up @@ -313,10 +346,6 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
return nil
}

package func inverseSources(request: InverseSourcesRequest) -> InverseSourcesResponse {
return InverseSourcesResponse(targets: [BuildTargetIdentifier.dummy])
}

package func scheduleBuildGraphGeneration() {}

package func waitForUpToDateBuildGraph() async {}
Expand All @@ -329,18 +358,6 @@ extension BuildServerBuildSystem: BuiltInBuildSystem {
return nil
}

package func prepare(request: PrepareTargetsRequest) async throws -> VoidResponse {
throw PrepareNotSupportedError()
}

package func didChangeWatchedFiles(notification: BuildServerProtocol.DidChangeWatchedFilesNotification) {}

package func sourceFiles() async -> [SourceFileInfo] {
// BuildServerBuildSystem does not support syntactic test discovery or background indexing.
// (https://github.com/swiftlang/sourcekit-lsp/issues/1173).
return []
}

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).
Expand Down
Loading