Skip to content

Allow configuring of SourceKit-LSP’s options using configuration files #1524

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 2 commits into from
Jun 28, 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
38 changes: 38 additions & 0 deletions Documentation/Configuration File.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Configuration File

`.sourcekit-lsp/config.json` configuration files can be used to modify the behavior of SourceKit-LSP in various ways. The following locations are checked. Settings in later configuration files override settings in earlier configuration files
- `~/.sourcekit-lsp/config.json`
- On macOS: `~/Library/Application Support/org.swift.sourcekit-lsp/config.json` from the various `Library` folders on the system
- If the `XDG_CONFIG_HOME` environment variable is set: `$XDG_CONFIG_HOME/org.swift.sourcekit-lsp/config.json`
- A `.sourcekit-lsp/config.json` file in a workspace’s root

The structure of the file is currently not guaranteed to be stable. Options may be removed or renamed.

## Structure

`config.json` is a JSON file with the following structure. All keys are optional and unknown keys are ignored.

- `swiftPM`: Dictionary with the following keys, defining options for SwiftPM workspaces
- `configuration: "debug"|"release"`: The configuration to build the project for during background indexing and the configuration whose build folder should be used for Swift modules if background indexing is disabled
- `scratchPath: string`: Build artifacts directory path. If nil, the build system may choose a default value
- `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
- `linkerFlags: string[]`: Extra arguments passed to the linker
- `compilationDatabase`: Dictionary with the following keys, defining options for workspaces with a compilation database
- `searchPaths: string[]`: Additional paths to search for a compilation database, relative to a workspace root.
- `fallbackBuildSystem`: Dictionary with the following keys, defining options for files that aren't managed by any build system
- `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
- `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.
- `indexDatabasePath: string`: Directory in which the indexstore-db should be stored. By default, inferred from the build system.
- `indexPrefixMap: [string: string]`: Path remappings for remapping index data for local use.
- `maxCoresPercentageToUseForBackgroundIndexing: double`: A hint indicating how many cores background indexing should use at most (value between 0 and 1). Background indexing is not required to honor this setting
- `updateIndexStoreTimeout: int`: Number of seconds to wait for an update index store task to finish before killing it.
- `defaultWorkspaceType: "buildserver"|"compdb"|"swiftpm"`: Overrides workspace type selection logic.
- `generatedFilesPath: string`: Directory in which generated interfaces and macro expansions should be stored.
- `experimentalFeatures: string[]`: Experimental features to enable
- `swiftPublishDiagnosticsDebounce`: The time that `SwiftLanguageService` should wait after an edit before starting to compute diagnostics and sending a `PublishDiagnosticsNotification`.
96 changes: 0 additions & 96 deletions Documentation/LSP Extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,102 +73,6 @@ Added case
identifier = 'identifier'
```

## `WorkspaceFolder`

Added field:

```ts
/**
* Build settings that should be used for this workspace.
*
* For arguments that have a single value (like the build configuration), this takes precedence over the global
* options set when launching sourcekit-lsp. For all other options, the values specified in the workspace-specific
* build setup are appended to the global options.
*/
var buildSetup?: WorkspaceBuildSetup
```

with

```ts
/**
* The configuration to build a workspace in.
*/
export enum BuildConfiguration {
case debug = 'debug'
case release = 'release'
}

/**
* The type of workspace; default workspace type selection logic can be overridden.
*/
export enum WorkspaceType {
buildServer = 'buildServer'
compilationDatabase = 'compilationDatabase'
swiftPM = 'swiftPM'
}

/// Build settings that should be used for a workspace.
interface WorkspaceBuildSetup {
/**
* The configuration that the workspace should be built in.
*/
buildConfiguration?: BuildConfiguration

/**
* The default workspace type to use for this workspace.
*/
defaultWorkspaceType?: WorkspaceType

/**
* The build directory for the workspace.
*/
scratchPath?: DocumentURI

/**
* Arguments to be passed to any C compiler invocations.
*/
cFlags?: string[]

/**
* Arguments to be passed to any C++ compiler invocations.
*/
cxxFlags?: string[]

/**
* Arguments to be passed to any linker invocations.
*/
linkerFlags?: string[]

/**
* Arguments to be passed to any Swift compiler invocations.
*/
swiftFlags?: string[]
}
```

## `textDocument/completion`

Added field:

```ts
/**
* Options to control code completion behavior in Swift
*/
sourcekitlspOptions?: SKCompletionOptions
```

with

```ts
interface SKCompletionOptions {
/**
* The maximum number of completion results to return, or `null` for unlimited.
*/
maxResults?: int
}
```

## `textDocument/interface`

New request that request a textual interface of a module to display in the IDE. Used internally within SourceKit-LSP
Expand Down
6 changes: 2 additions & 4 deletions Sources/Diagnose/IndexCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ public struct IndexCommand: AsyncParsableCommand {
public init() {}

public func run() async throws {
var serverOptions = SourceKitLSPServer.Options()
serverOptions.experimentalFeatures = Set(experimentalFeatures)
serverOptions.experimentalFeatures.insert(.backgroundIndexing)
let options = SourceKitLSPOptions(experimentalFeatures: Set(experimentalFeatures).union([.backgroundIndexing]))

let installPath =
if let toolchainOverride, let toolchain = Toolchain(try AbsolutePath(validating: toolchainOverride)) {
Expand All @@ -96,7 +94,7 @@ public struct IndexCommand: AsyncParsableCommand {
let messageHandler = IndexLogMessageHandler()
let inProcessClient = try await InProcessSourceKitLSPClient(
toolchainRegistry: ToolchainRegistry(installPath: installPath),
serverOptions: serverOptions,
options: options,
workspaceFolders: [WorkspaceFolder(uri: DocumentURI(URL(fileURLWithPath: project)))],
messageHandler: messageHandler
)
Expand Down
6 changes: 4 additions & 2 deletions Sources/InProcessClient/InProcessSourceKitLSPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public final class InProcessSourceKitLSPClient: Sendable {
/// `messageHandler` handles notifications and requests sent from the SourceKit-LSP server to the client.
public init(
toolchainRegistry: ToolchainRegistry,
serverOptions: SourceKitLSPServer.Options = SourceKitLSPServer.Options(),
options: SourceKitLSPOptions = SourceKitLSPOptions(),
testHooks: TestHooks = TestHooks(),
capabilities: ClientCapabilities = ClientCapabilities(),
workspaceFolders: [WorkspaceFolder],
messageHandler: any MessageHandler
Expand All @@ -35,7 +36,8 @@ public final class InProcessSourceKitLSPClient: Sendable {
self.server = SourceKitLSPServer(
client: serverToClientConnection,
toolchainRegistry: toolchainRegistry,
options: serverOptions,
options: options,
testHooks: testHooks,
onExit: {
serverToClientConnection.close()
}
Expand Down
1 change: 0 additions & 1 deletion Sources/LanguageServerProtocol/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ add_library(LanguageServerProtocol STATIC
SupportTypes/SemanticTokens.swift
SupportTypes/SemanticTokenTypes.swift
SupportTypes/ServerCapabilities.swift
SupportTypes/SKCompletionOptions.swift
SupportTypes/StringOrMarkupContent.swift
SupportTypes/SymbolKind.swift
SupportTypes/TestItem.swift
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
/// - textDocument: The document to perform completion in.
/// - position: The location to perform completion at.
/// - context: Optional code-completion context.
/// - sourcekitlspOptions: **(LSP Extension)** code-completion options for sourcekit-lsp.
///
/// - Returns: A list of completion items to complete the code at the given position.
public struct CompletionRequest: TextDocumentRequest, Hashable {
Expand All @@ -36,18 +35,14 @@ public struct CompletionRequest: TextDocumentRequest, Hashable {

public var context: CompletionContext?

public var sourcekitlspOptions: SKCompletionOptions?

public init(
textDocument: TextDocumentIdentifier,
position: Position,
context: CompletionContext? = nil,
sourcekitlspOptions: SKCompletionOptions? = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a doc comment for this parameter above, I guess it should be removed?

context: CompletionContext? = nil
) {
self.textDocument = textDocument
self.position = position
self.context = context
self.sourcekitlspOptions = sourcekitlspOptions
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@

/// Poll the index for unit changes and wait for them to be registered.
/// **LSP Extension, For Testing**.
///
/// Users of PollIndex should set `"initializationOptions": { "listenToUnitEvents": false }` during
/// the `initialize` request.
public struct PollIndexRequest: RequestType {
public static let method: String = "workspace/_pollIndex"
public typealias Response = VoidResponse
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,65 +10,6 @@
//
//===----------------------------------------------------------------------===//

/// The configuration to build a workspace in.
///
/// **(LSP Extension)**
public enum BuildConfiguration: Hashable, Codable, Sendable {
case debug
case release
}

/// The type of workspace; default workspace type selection logic can be overridden.
///
/// **(LSP Extension)**
public enum WorkspaceType: Hashable, Codable, Sendable {
case buildServer, compilationDatabase, swiftPM
}

/// Build settings that should be used for a workspace.
///
/// **(LSP Extension)**
public struct WorkspaceBuildSetup: Hashable, Codable, Sendable {
/// The configuration that the workspace should be built in.
public let buildConfiguration: BuildConfiguration?

/// The default workspace type to use for this workspace.
public let defaultWorkspaceType: WorkspaceType?

/// The build directory for the workspace.
public let scratchPath: DocumentURI?

/// Arguments to be passed to any C compiler invocations.
public let cFlags: [String]?

/// Arguments to be passed to any C++ compiler invocations.
public let cxxFlags: [String]?

/// Arguments to be passed to any linker invocations.
public let linkerFlags: [String]?

/// Arguments to be passed to any Swift compiler invocations.
public let swiftFlags: [String]?

public init(
buildConfiguration: BuildConfiguration? = nil,
defaultWorkspaceType: WorkspaceType? = nil,
scratchPath: DocumentURI? = nil,
cFlags: [String]? = nil,
cxxFlags: [String]? = nil,
linkerFlags: [String]? = nil,
swiftFlags: [String]? = nil
) {
self.buildConfiguration = buildConfiguration
self.defaultWorkspaceType = defaultWorkspaceType
self.scratchPath = scratchPath
self.cFlags = cFlags
self.cxxFlags = cxxFlags
self.linkerFlags = linkerFlags
self.swiftFlags = swiftFlags
}
}

/// Unique identifier for a document.
public struct WorkspaceFolder: ResponseType, Hashable, Codable, Sendable {

Expand All @@ -78,27 +19,13 @@ public struct WorkspaceFolder: ResponseType, Hashable, Codable, Sendable {
/// The name of the workspace (default: basename of url).
public var name: String

/// Build settings that should be used for this workspace.
///
/// For arguments that have a single value (like the build configuration), this takes precedence over the global
/// options set when launching sourcekit-lsp. For all other options, the values specified in the workspace-specific
/// build setup are appended to the global options.
///
/// **(LSP Extension)**
public var buildSetup: WorkspaceBuildSetup?

public init(
uri: DocumentURI,
name: String? = nil,
buildSetup: WorkspaceBuildSetup? = nil
) {
public init(uri: DocumentURI, name: String? = nil) {
self.uri = uri

self.name = name ?? uri.fileURL?.lastPathComponent ?? "unknown_workspace"

if self.name.isEmpty {
self.name = "unknown_workspace"
}
self.buildSetup = buildSetup
}
}
2 changes: 1 addition & 1 deletion Sources/SKCore/BuildConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//

public enum BuildConfiguration: String, Sendable {
public enum BuildConfiguration: String, Codable, Sendable {
case debug
case release
}
Loading