From 24bd7125c3e319ae726ea183b57c2e41fcbda7a8 Mon Sep 17 00:00:00 2001 From: Ambrus Toth Date: Fri, 3 Jul 2026 12:33:04 +0200 Subject: [PATCH 1/2] Add CompletionItem.labelDetails (LSP 3.17) Adds the CompletionItemLabelDetails structure and the corresponding labelDetails field on CompletionItem, so servers can return the signature/description next to the label when the client declares completionItem.labelDetailsSupport (which is already modeled). --- .../LanguageFeatures/Completion.swift | 13 +++++++++++++ .../CompletionItemTests.swift | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Tests/LanguageServerProtocolTests/CompletionItemTests.swift diff --git a/Sources/LanguageServerProtocol/LanguageFeatures/Completion.swift b/Sources/LanguageServerProtocol/LanguageFeatures/Completion.swift index ec659cd..a87ebaa 100644 --- a/Sources/LanguageServerProtocol/LanguageFeatures/Completion.swift +++ b/Sources/LanguageServerProtocol/LanguageFeatures/Completion.swift @@ -155,8 +155,19 @@ public enum InsertTextFormat: Int, Codable, Hashable, Sendable { case snippet = 2 } +public struct CompletionItemLabelDetails: Codable, Hashable, Sendable { + public let detail: String? + public let description: String? + + public init(detail: String? = nil, description: String? = nil) { + self.detail = detail + self.description = description + } +} + public struct CompletionItem: Codable, Hashable, Sendable { public let label: String + public let labelDetails: CompletionItemLabelDetails? public let kind: CompletionItemKind? public let detail: String? public let documentation: TwoTypeOption? @@ -174,6 +185,7 @@ public struct CompletionItem: Codable, Hashable, Sendable { public init( label: String, + labelDetails: CompletionItemLabelDetails? = nil, kind: CompletionItemKind? = nil, detail: String? = nil, documentation: TwoTypeOption? = nil, @@ -190,6 +202,7 @@ public struct CompletionItem: Codable, Hashable, Sendable { data: LSPAny? = nil ) { self.label = label + self.labelDetails = labelDetails self.kind = kind self.detail = detail self.documentation = documentation diff --git a/Tests/LanguageServerProtocolTests/CompletionItemTests.swift b/Tests/LanguageServerProtocolTests/CompletionItemTests.swift new file mode 100644 index 0000000..9c68184 --- /dev/null +++ b/Tests/LanguageServerProtocolTests/CompletionItemTests.swift @@ -0,0 +1,15 @@ +import XCTest +import LanguageServerProtocol + +final class CompletionItemTests: XCTestCase { + func testDecodingLabelDetails() throws { + // a textDocument/completion response item shaped per the LSP 3.17 spec + let json = """ +{"label":"map","labelDetails":{"detail":"(transform: (Element) -> T)","description":"[T]"},"kind":3,"insertText":"map"} +""" + let data = try XCTUnwrap(json.data(using: .utf8)) + let item = try JSONDecoder().decode(CompletionItem.self, from: data) + + XCTAssertEqual(item.labelDetails, CompletionItemLabelDetails(detail: "(transform: (Element) -> T)", description: "[T]")) + } +} From 3253983243b23d352b1bad468e71fa2528226741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ambrus=20T=C3=B3th?= <32463042+tothambrus11@users.noreply.github.com> Date: Sat, 4 Jul 2026 18:23:10 +0200 Subject: [PATCH 2/2] Apply suggestion from @tothambrus11 --- Tests/LanguageServerProtocolTests/CompletionItemTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/LanguageServerProtocolTests/CompletionItemTests.swift b/Tests/LanguageServerProtocolTests/CompletionItemTests.swift index 9c68184..baf9a71 100644 --- a/Tests/LanguageServerProtocolTests/CompletionItemTests.swift +++ b/Tests/LanguageServerProtocolTests/CompletionItemTests.swift @@ -5,8 +5,8 @@ final class CompletionItemTests: XCTestCase { func testDecodingLabelDetails() throws { // a textDocument/completion response item shaped per the LSP 3.17 spec let json = """ -{"label":"map","labelDetails":{"detail":"(transform: (Element) -> T)","description":"[T]"},"kind":3,"insertText":"map"} -""" + {"label":"map","labelDetails":{"detail":"(transform: (Element) -> T)","description":"[T]"},"kind":3,"insertText":"map"} + """ let data = try XCTUnwrap(json.data(using: .utf8)) let item = try JSONDecoder().decode(CompletionItem.self, from: data)