Skip to content

Clean-up of the build system integration #1674

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 29 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8ac405c
Make `BuildSystemManager.buildSystem` and `BuiltInBuildSystemAdapter.…
ahoppen Sep 13, 2024
d00722e
Use BSP to log messages from preparation in the build system
ahoppen Sep 13, 2024
f741b0d
Use more fine-grained dependency tracking to allow BSP requests to be…
ahoppen Sep 14, 2024
5ffc782
Add BSP messages to `bspRegistry`
ahoppen Sep 14, 2024
7028846
Log target name instead of the target's URI
ahoppen Sep 14, 2024
29cfda0
Refactor `sourceFiles` to return a dictionary from `DocumentURI` to `…
ahoppen Sep 14, 2024
8a10963
Remove double logging of BSP replies
ahoppen Sep 14, 2024
14e9631
Fix issue that created incorrect display name for BSP server
ahoppen Sep 14, 2024
5870ad9
Implement `InverseSourcesRequest` in `BuildSystemManager`
ahoppen Sep 14, 2024
79e1d2a
If we have a cached request for a superset of the targets, serve the …
ahoppen Sep 14, 2024
cb2924a
Remove `sourceFilesDidChange`
ahoppen Sep 14, 2024
765ea48
Remove `testSettingsChangedAfterUnregister`
ahoppen Sep 14, 2024
6762bb3
Remove resolved `FIXME`
ahoppen Sep 14, 2024
80afa15
Replace `FIXME` with `TODO`
ahoppen Sep 14, 2024
85b2f1f
Review `BuildServerProtocol` module for consistency
ahoppen Sep 15, 2024
2f388b9
Send shutdown request to build system from `BuildSystemManager`
ahoppen Sep 15, 2024
3a78b65
Share logic to infer language from file extension between `BuildSyste…
ahoppen Sep 15, 2024
9ee7c59
Minor cleanups
ahoppen Sep 15, 2024
a9578bb
Review `BuildSystemMessageDependencyTracker`
ahoppen Sep 15, 2024
0f56e5f
Simplify `FallbackBuildSystem` to a free function returning fallback …
ahoppen Sep 15, 2024
d155665
Review `BuildSystemManager`
ahoppen Sep 15, 2024
5996e56
Review `BuiltInBuildSystemAdapter`
ahoppen Sep 15, 2024
316790f
Review `BuiltInBuildSystem`
ahoppen Sep 15, 2024
bc9ee37
Review `QueueBasedMessageHandler`
ahoppen Sep 15, 2024
3753837
Review `CompilationDatabase.swift`
ahoppen Sep 15, 2024
0bdbb50
Review `CompilationDatabaseBuildSystem`
ahoppen Sep 15, 2024
db539b0
Review `TestBuildSystem.swift`
ahoppen Sep 15, 2024
2c2d9f9
Review `PrefixMessageWithTaskEmoji.swift`
ahoppen Sep 15, 2024
e15bdd7
Review `SwiftPMBuildSystem.swift`
ahoppen Sep 15, 2024
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
163 changes: 163 additions & 0 deletions Contributor Documentation/BSP Extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# BSP Extensions

SourceKit-LSP extends the BSP protocol in the following ways.

## `build/initialize`

`InitializeBuildResultDataKind` can be `sourceKit`, in which case `InitializeBuildResultData` contains the following data.

```ts
export interface SourceKitInitializeBuildResponseData {
/** The directory to which the index store is written during compilation, ie. the path passed to `-index-store-path`
* for `swiftc` or `clang` invocations **/
indexStorePath?: string;

/** The path at which SourceKit-LSP can store its index database, aggregating data from `indexStorePath` */
indexDatabasePath?: string;

/** Whether the build server supports the `buildTarget/prepare` request */
supportsPreparation?: bool;
}
```

## `buildTarget/didChange`

`changes` can be `null` to indicate that all targets have changed.

## `buildTarget/prepare`

The prepare build target request is sent from the client to the server to prepare the given list of build targets for editor functionality.

To do so, the build server should build Swift modules for all dependencies of this module so that all `import` statements in this module can be resolved.

The server communicates during the initialize handshake whether this method is supported or not by setting `supportsPreparation` in `SourceKitInitializeBuildResponseData`.

- method: `buildTarget/prepare`
- params: `PrepareParams`

```ts
export interface PrepareParams {
/** A list of build targets to prepare. */
targets: BuildTargetIdentifier[];

/** A unique identifier generated by the client to identify this request.
* The server may include this id in triggered notifications or responses. **/
originId?: OriginId;
}
```

## `builtTarget/sources`

`SourceItemDataKind` can be `sourceKit` in which case `SourceItem.data` contains the following data.

```ts
export interface SourceKitSourceItemData {
/** The language of the source file. If `nil`, the language is inferred from the file extension. */
language? LanguageId;

/** Whether the file is a header file that is clearly associated with one target.
*
* For example header files in SwiftPM projects are always associated to one target and SwiftPM can provide build
* settings for that header file.
*
* In general, build systems don't need to list all header files in the `buildTarget/sources` request: Semantic
* functionality for header files is usually provided by finding a main file that includes the header file and
* inferring build settings from it. Listing header files in `buildTarget/sources` allows SourceKit-LSP to provide
* semantic functionality for header files if they haven't been included by any main file. **/
isHeader?: bool;
}
```

## `textDocument/sourceKitOptions`

The `TextDocumentSourceKitOptionsRequest` request is sent from the client to the server to query for the list of compiler options necessary to compile this file in the given target.

The build settings are considered up-to-date and can be cached by SourceKit-LSP until a `buildTarget/didChange` is sent for the requested target.

The request may return `nil` if it doesn't have any build settings for this file in the given target.

- method: `textDocument/sourceKitOptions`
- params: `TextDocumentSourceKitOptionsParams`
- result: `TextDocumentSourceKitOptionsResult`

```ts
export interface TextDocumentSourceKitOptionsRequest {
/** The URI of the document to get options for */
textDocument: TextDocumentIdentifier;

/** The target for which the build setting should be returned.
*
* A source file might be part of multiple targets and might have different compiler arguments in those two targets,
* thus the target is necessary in this request. **/
target: BuildTargetIdentifier;

/** The language with which the document was opened in the editor. */
language: LanguageId;
}

export interface TextDocumentSourceKitOptionsResult {
/** The compiler options required for the requested file. */
compilerArguments: string[];

/** The working directory for the compile command. */
workingDirectory?: string;
}
```

## `window/workDoneProgress/create`

Request from the build server to SourceKit-LSP to create a work done progress.

Definition is the same as in LSP.

## `workspace/buildTargets`

`BuildTargetTag` can have the following additional values

```ts
export interface BuildTargetTag {
// ...

/** This is a target of a dependency from the project the user opened, eg. a target that builds a SwiftPM dependency. */
export const Dependency = "dependency";

/** This target only exists to provide compiler arguments for SourceKit-LSP can't be built standalone.
*
* For example, a SwiftPM package manifest is in a non-buildable target. **/
export const NotBuildable = "not-buildable";
}
```

`BuildTargetDataKind` can be `sourceKit` in which case `BuildTarget.data` contains the following data.


```ts
export interface SourceKitBuildTarget {
/** 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. **/
toolchain?: URI;
}
```

## `workspace/didChangeWatchedFiles`

Notification sent from SourceKit-LSP to the build system to indicate that files within the project have been modified.

Definition is the same as in LSP.

## `workspace/waitForBuildSystemUpdates`

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.

- method: `workspace/waitForBuildSystemUpdates`

## `$/progress`

Notification from the build server to SourceKit-LSP to update a work done progress created using `window/workDoneProgress/create`.

Definition is the same as in LSP.
1 change: 1 addition & 0 deletions Documentation/Configuration File.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The structure of the file is currently not guaranteed to be stable. Options may
- `cCompilerFlags: string[]`: Extra arguments passed to the compiler for C files
- `cxxCompilerFlags: string[]`: Extra arguments passed to the compiler for C++ files
- `swiftCompilerFlags: string[]`: Extra arguments passed to the compiler for Swift files
- `sdk: string`: The SDK to use for fallback arguments. Default is to infer the SDK using `xcrun`.
- `clangdOptions: string[]`: Extra command line arguments passed to `clangd` when launching it
- `index`: Dictionary with the following keys, defining options related to indexing
- `indexStorePath: string`: Directory in which a separate compilation stores the index store. By default, inferred from the build system.
Expand Down
33 changes: 20 additions & 13 deletions Sources/BuildServerProtocol/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
add_library(BuildServerProtocol STATIC
BuildTargetSourcesRequest.swift
BuildTargetsRequest.swift
DidChangeBuildTargetNotification.swift
DidChangeWatchedFilesNotification.swift
InitializeBuild.swift
InverseSourcesRequest.swift
LogMessageNotification.swift
Messages.swift
PrepareTargetsRequest.swift
RegisterForChangeNotifications.swift
ShutdownBuild.swift
SourceKitOptionsRequest.swift
WaitForBuildSystemUpdates.swift
WorkDoneProgress.swift)

Messages/TextDocumentSourceKitOptionsRequest.swift
Messages/OnBuildTargetDidChangeNotification.swift
Messages/InitializeBuildRequest.swift
Messages/BuildTargetSourcesRequest.swift
Messages/OnBuildExitNotification.swift
Messages/RegisterForChangeNotifications.swift
Messages/OnBuildLogMessageNotification.swift
Messages/WorkDoneProgress.swift
Messages/OnWatchedFilesDidChangeNotification.swift
Messages/OnBuildInitializedNotification.swift
Messages/WorkspaceWaitForBuildSystemUpdates.swift
Messages/BuildShutdownRequest.swift
Messages/WorkspaceBuildTargetsRequest.swift
Messages/BuildTargetPrepareRequest.swift

SupportTypes/TextDocumentIdentifier.swift
SupportTypes/TaskId.swift
SupportTypes/BuildTarget.swift
SupportTypes/MessageType.swift)
set_target_properties(BuildServerProtocol PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
target_link_libraries(BuildServerProtocol PRIVATE
Expand Down
45 changes: 0 additions & 45 deletions Sources/BuildServerProtocol/InverseSourcesRequest.swift

This file was deleted.

20 changes: 12 additions & 8 deletions Sources/BuildServerProtocol/Messages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,28 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import LanguageServerProtocol

fileprivate let requestTypes: [_RequestType.Type] = [
BuildTargetOutputPaths.self,
BuildTargetsRequest.self,
BuildShutdownRequest.self,
BuildTargetPrepareRequest.self,
BuildTargetSourcesRequest.self,
CreateWorkDoneProgressRequest.self,
InitializeBuildRequest.self,
InverseSourcesRequest.self,
RegisterForChanges.self,
ShutdownBuild.self,
SourceKitOptionsRequest.self,
TextDocumentSourceKitOptionsRequest.self,
WorkspaceWaitForBuildSystemUpdatesRequest.self,
WorkspaceBuildTargetsRequest.self,
]

fileprivate let notificationTypes: [NotificationType.Type] = [
DidChangeBuildTargetNotification.self,
ExitBuildNotification.self,
OnBuildExitNotification.self,
FileOptionsChangedNotification.self,
InitializedBuildNotification.self,
OnBuildInitializedNotification.self,
OnBuildLogMessageNotification.self,
OnBuildTargetDidChangeNotification.self,
OnWatchedFilesDidChangeNotification.self,
]

public let bspRegistry = MessageRegistry(requests: requestTypes, notifications: notificationTypes)
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,17 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import LanguageServerProtocol

/// Like the language server protocol, the shutdown build request is
/// sent from the client to the server. It asks the server to shut down,
/// but to not exit (otherwise the response might not be delivered
/// correctly to the client). There is a separate exit notification
/// that asks the server to exit.
public struct ShutdownBuild: RequestType {
public struct BuildShutdownRequest: RequestType {
public static let method: String = "build/shutdown"
public typealias Response = VoidResponse

public init() {}
}

/// Like the language server protocol, a notification to ask the
/// server to exit its process. The server should exit with success
/// code 0 if the shutdown request has been received before;
/// otherwise with error code 1.
public struct ExitBuildNotification: NotificationType {
public static let method: String = "build/exit"

public init() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,22 @@ import LanguageServerProtocol

public typealias OriginId = String

public struct PrepareTargetsRequest: RequestType, Hashable {
/// The prepare build target request is sent from the client to the server to prepare the given list of build targets
/// for editor functionality.
///
/// To do so, the build server should build Swift modules for all dependencies of this module so that all `import`
/// statements in this module can be resolved.
///
/// The server communicates during the initialize handshake whether this method is supported or not.
public struct BuildTargetPrepareRequest: RequestType, Hashable {
public static let method: String = "buildTarget/prepare"
public typealias Response = VoidResponse

/// A list of build targets to prepare.
public var targets: [BuildTargetIdentifier]

/// A unique identifier generated by the client to identify this request.
/// The server may include this id in triggered notifications or responses.
public var originId: OriginId?

public init(targets: [BuildTargetIdentifier], originId: OriginId? = nil) {
Expand Down
Loading