Skip to content

Commit bc374c7

Browse files
committed
Enumerate supported code lens commands
1 parent f48dec7 commit bc374c7

File tree

6 files changed

+47
-20
lines changed

6 files changed

+47
-20
lines changed

Sources/LanguageServerProtocol/SupportTypes/ClientCapabilities.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,15 @@ public struct TextDocumentClientCapabilities: Hashable, Codable, Sendable {
470470
/// Whether the client supports dynamic registration of this request.
471471
public var dynamicRegistration: Bool?
472472

473-
public var supportedCommands: [String: String]
473+
/// Dictionary of supported commands announced by the client.
474+
/// The key is the CodeLens name recognized by SourceKit-LSP and the
475+
/// value is the command as recognized by the client.
476+
public var supportedCommands: [SupportedCodeLensCommand: String]
474477

475-
public init(dynamicRegistration: Bool? = nil, supportedCommands: [String: String] = [:]) {
478+
public init(
479+
dynamicRegistration: Bool? = nil,
480+
supportedCommands: [SupportedCodeLensCommand: String] = [:]
481+
) {
476482
self.dynamicRegistration = dynamicRegistration
477483
self.supportedCommands = supportedCommands
478484
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// Code lenses that LSP can annotate code with.
14+
///
15+
/// Clients provide these as keys to the `supportedCommands` dictionary supplied
16+
/// in the client's `InitializeRequest`.
17+
public enum SupportedCodeLensCommand: String, Sendable {
18+
case run = "swift.run"
19+
case debug = "swift.debug"
20+
}

Sources/SourceKitLSP/CapabilityRegistry.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ public final actor CapabilityRegistry {
3838
/// Dynamically registered pull diagnostics options.
3939
private var pullDiagnostics: [CapabilityRegistration: DiagnosticRegistrationOptions] = [:]
4040

41-
/// Dynamically registered code lens options.
42-
private var codeLens: [CapabilityRegistration: CodeLensRegistrationOptions] = [:]
43-
4441
/// Dynamically registered file watchers.
4542
private var didChangeWatchedFiles: DidChangeWatchedFilesRegistrationOptions?
4643

@@ -83,7 +80,7 @@ public final actor CapabilityRegistry {
8380
clientCapabilities.textDocument?.publishDiagnostics?.codeDescriptionSupport == true
8481
}
8582

86-
public var supportedCodeLensCommands: [String: String] {
83+
public var supportedCodeLensCommands: [SupportedCodeLensCommand: String] {
8784
clientCapabilities.textDocument?.codeLens?.supportedCommands ?? [:]
8885
}
8986

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -980,14 +980,18 @@ extension SourceKitLSPServer {
980980
case let .dictionary(codeLensConfig) = codeLens,
981981
case let .dictionary(supportedCommands) = codeLensConfig["supportedCommands"]
982982
{
983-
let commandMap = supportedCommands.compactMapValues({
984-
if case let .string(val) = $0 {
985-
return val
983+
let commandMap = supportedCommands.compactMap { (key, value) in
984+
if case let .string(clientCommand) = value,
985+
let lspCommand = SupportedCodeLensCommand(rawValue: key)
986+
{
987+
return (lspCommand, clientCommand)
986988
}
989+
990+
logger.error("Encountered an unsupported code lens \"\(key)\" in client's initialization request.")
987991
return nil
988-
})
992+
}
989993

990-
clientCapabilities.textDocument?.codeLens?.supportedCommands = commandMap
994+
clientCapabilities.textDocument?.codeLens?.supportedCommands = Dictionary(uniqueKeysWithValues: commandMap)
991995
}
992996
}
993997

Sources/SourceKitLSP/Swift/SwiftCodeLensScanner.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ final class SwiftCodeLensScanner: SyntaxVisitor {
2222
private var result: [CodeLens] = []
2323

2424
/// The map of supported commands and their client side command names
25-
private let supportedCommands: [String: String]
25+
private let supportedCommands: [SupportedCodeLensCommand: String]
2626

27-
private init(snapshot: DocumentSnapshot, supportedCommands: [String: String]) {
27+
private init(snapshot: DocumentSnapshot, supportedCommands: [SupportedCodeLensCommand: String]) {
2828
self.snapshot = snapshot
2929
self.supportedCommands = supportedCommands
3030
super.init(viewMode: .fixedUp)
@@ -35,7 +35,7 @@ final class SwiftCodeLensScanner: SyntaxVisitor {
3535
public static func findCodeLenses(
3636
in snapshot: DocumentSnapshot,
3737
syntaxTreeManager: SyntaxTreeManager,
38-
supportedCommands: [String: String]
38+
supportedCommands: [SupportedCodeLensCommand: String]
3939
) async -> [CodeLens] {
4040
guard snapshot.text.contains("@main") && !supportedCommands.isEmpty else {
4141
// This is intended to filter out files that obviously do not contain an entry point.
@@ -62,7 +62,7 @@ final class SwiftCodeLensScanner: SyntaxVisitor {
6262
if attribute.trimmedDescription == "@main" {
6363
let range = self.snapshot.absolutePositionRange(of: attribute.trimmedRange)
6464

65-
if let runCommand = supportedCommands["swift.run"] {
65+
if let runCommand = supportedCommands[SupportedCodeLensCommand.run] {
6666
// Return commands for running/debugging the executable.
6767
// These command names must be recognized by the client and so should not be chosen arbitrarily.
6868
self.result.append(
@@ -73,7 +73,7 @@ final class SwiftCodeLensScanner: SyntaxVisitor {
7373
)
7474
}
7575

76-
if let debugCommand = supportedCommands["swift.debug"] {
76+
if let debugCommand = supportedCommands[SupportedCodeLensCommand.run] {
7777
self.result.append(
7878
CodeLens(
7979
range: range,

Tests/SourceKitLSPTests/CodeLensTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ final class CodeLensTests: XCTestCase {
1919
func testNoLenses() async throws {
2020
var codeLensCapabilities = TextDocumentClientCapabilities.CodeLens()
2121
codeLensCapabilities.supportedCommands = [
22-
"swift.run": "swift.run",
23-
"swift.debug": "swift.debug"
22+
SupportedCodeLensCommand.run: "swift.run",
23+
SupportedCodeLensCommand.debug: "swift.debug"
2424
]
2525
let capabilities = ClientCapabilities(textDocument: TextDocumentClientCapabilities(codeLens: codeLensCapabilities))
2626

@@ -67,8 +67,8 @@ final class CodeLensTests: XCTestCase {
6767
func testSuccessfulCodeLensRequest() async throws {
6868
var codeLensCapabilities = TextDocumentClientCapabilities.CodeLens()
6969
codeLensCapabilities.supportedCommands = [
70-
"swift.run": "swift.run",
71-
"swift.debug": "swift.debug"
70+
SupportedCodeLensCommand.run: "swift.run",
71+
SupportedCodeLensCommand.debug: "swift.debug"
7272
]
7373
let capabilities = ClientCapabilities(textDocument: TextDocumentClientCapabilities(codeLens: codeLensCapabilities))
7474

0 commit comments

Comments
 (0)