Skip to content

Commit 1077ea3

Browse files
Add boilerplate for pull-model diagnostics
1 parent 1fc50ae commit 1077ea3

File tree

8 files changed

+103
-1
lines changed

8 files changed

+103
-1
lines changed

Sources/LanguageServerProtocol/SupportTypes/ClientCapabilities.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,16 @@ public struct TextDocumentClientCapabilities: Hashable, Codable {
526526
}
527527
}
528528

529+
/// Capabilities specific to 'textDocument/diagnostic'. Since LSP 3.17.0.
530+
public struct Diagnostic: Equatable, Hashable, Codable {
531+
532+
/// Whether implementation supports dynamic registration.
533+
public var dynamicRegistration: Bool?
534+
535+
/// Whether the clients supports related documents for document diagnostic pulls.
536+
public var relatedDocumentSupport: Bool?
537+
}
538+
529539
// MARK: Properties
530540

531541
public var synchronization: Synchronization? = nil
@@ -575,6 +585,8 @@ public struct TextDocumentClientCapabilities: Hashable, Codable {
575585
public var semanticTokens: SemanticTokens? = nil
576586

577587
public var inlayHint: InlayHint? = nil
588+
589+
public var diagnostic: Diagnostic? = nil
578590

579591
public init(synchronization: Synchronization? = nil,
580592
completion: Completion? = nil,
@@ -599,7 +611,8 @@ public struct TextDocumentClientCapabilities: Hashable, Codable {
599611
foldingRange: FoldingRange? = nil,
600612
callHierarchy: DynamicRegistrationCapability? = nil,
601613
semanticTokens: SemanticTokens? = nil,
602-
inlayHint: InlayHint? = nil) {
614+
inlayHint: InlayHint? = nil,
615+
diagnostic: Diagnostic? = nil) {
603616
self.synchronization = synchronization
604617
self.completion = completion
605618
self.hover = hover
@@ -624,5 +637,6 @@ public struct TextDocumentClientCapabilities: Hashable, Codable {
624637
self.callHierarchy = callHierarchy
625638
self.semanticTokens = semanticTokens
626639
self.inlayHint = inlayHint
640+
self.diagnostic = diagnostic
627641
}
628642
}

Sources/LanguageServerProtocol/SupportTypes/RegistrationOptions.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,30 @@ public struct InlayHintRegistrationOptions: RegistrationOptions, TextDocumentReg
156156
}
157157
}
158158

159+
/// Describe options to be used when registering for pull diagnostics. Since LSP 3.17.0
160+
public struct DiagnosticRegistrationOptions: RegistrationOptions, TextDocumentRegistrationOptionsProtocol {
161+
public var textDocumentRegistrationOptions: TextDocumentRegistrationOptions
162+
public var diagnosticOptions: DiagnosticOptions
163+
164+
public init(
165+
documentSelector: DocumentSelector? = nil,
166+
diagnosticOptions: DiagnosticOptions
167+
) {
168+
textDocumentRegistrationOptions = TextDocumentRegistrationOptions(documentSelector: documentSelector)
169+
self.diagnosticOptions = diagnosticOptions
170+
}
171+
172+
public func encodeIntoLSPAny(dict: inout [String: LSPAny]) {
173+
textDocumentRegistrationOptions.encodeIntoLSPAny(dict: &dict)
174+
175+
dict["interFileDependencies"] = .bool(diagnosticOptions.interFileDependencies)
176+
dict["workspaceDiagnostics"] = .bool(diagnosticOptions.workspaceDiagnostics)
177+
if let workDoneProgress = diagnosticOptions.workDoneProgress {
178+
dict["workDoneProgress"] = .bool(workDoneProgress)
179+
}
180+
}
181+
}
182+
159183
/// Describe options to be used when registering for file system change events.
160184
public struct DidChangeWatchedFilesRegistrationOptions: RegistrationOptions {
161185
/// The watchers to register.

Sources/LanguageServerProtocol/SupportTypes/ServerCapabilities.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ public struct ServerCapabilities: Codable, Hashable {
108108
/// Whether the server supports the `textDocument/inlayHint` family of requests.
109109
public var inlayHintProvider: ValueOrBool<InlayHintOptions>?
110110

111+
/// Whether the server supports the `textDocument/diagnostic` request.
112+
public var diagnosticProvider: DiagnosticOptions?
113+
111114
/// Whether the server provides selection range support.
112115
public var selectionRangeProvider: ValueOrBool<TextDocumentAndStaticRegistrationOptions>?
113116

@@ -152,6 +155,7 @@ public struct ServerCapabilities: Codable, Hashable {
152155
typeHierarchyProvider: ValueOrBool<TextDocumentAndStaticRegistrationOptions>? = nil,
153156
semanticTokensProvider: SemanticTokensOptions? = nil,
154157
inlayHintProvider: ValueOrBool<InlayHintOptions>? = nil,
158+
diagnosticProvider: DiagnosticOptions? = nil,
155159
selectionRangeProvider: ValueOrBool<TextDocumentAndStaticRegistrationOptions>? = nil,
156160
linkedEditingRangeProvider: ValueOrBool<TextDocumentAndStaticRegistrationOptions>? = nil,
157161
monikerProvider: ValueOrBool<MonikerOptions>? = nil,
@@ -188,6 +192,7 @@ public struct ServerCapabilities: Codable, Hashable {
188192
self.typeHierarchyProvider = typeHierarchyProvider
189193
self.semanticTokensProvider = semanticTokensProvider
190194
self.inlayHintProvider = inlayHintProvider
195+
self.diagnosticProvider = diagnosticProvider
191196
self.selectionRangeProvider = selectionRangeProvider
192197
self.linkedEditingRangeProvider = linkedEditingRangeProvider
193198
self.experimental = experimental

Sources/SourceKitLSP/CapabilityRegistry.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public final class CapabilityRegistry {
3131

3232
/// Dynamically registered inlay hint options.
3333
private var inlayHint: [CapabilityRegistration: InlayHintRegistrationOptions] = [:]
34+
35+
/// Dynamically registered pull diagnostics options.
36+
private var pullDiagnostics: [CapabilityRegistration: DiagnosticRegistrationOptions] = [:]
3437

3538
/// Dynamically registered file watchers.
3639
private var didChangeWatchedFiles: DidChangeWatchedFilesRegistrationOptions?
@@ -60,6 +63,10 @@ public final class CapabilityRegistry {
6063
clientCapabilities.textDocument?.inlayHint?.dynamicRegistration == true
6164
}
6265

66+
public var clientHasDocumentDiagnosticsRegistration: Bool {
67+
clientCapabilities.textDocument?.diagnostic?.dynamicRegistration == true
68+
}
69+
6370
public var clientHasDynamicExecuteCommandRegistration: Bool {
6471
clientCapabilities.workspace?.executeCommand?.dynamicRegistration == true
6572
}
@@ -202,6 +209,33 @@ public final class CapabilityRegistry {
202209
registerOnClient(registration)
203210
}
204211

212+
/// Dynamically register (pull model) diagnostic capabilities,
213+
/// if the client supports it.
214+
public func registerDiagnosticIfNeeded(
215+
options: DiagnosticOptions,
216+
for languages: [Language],
217+
registerOnClient: ClientRegistrationHandler
218+
) {
219+
guard clientHasDocumentDiagnosticsRegistration else { return }
220+
if let registration = registration(for: languages, in: pullDiagnostics) {
221+
if options != registration.diagnosticOptions {
222+
log("Unable to register new pull diagnostics options \(options) for " +
223+
"\(languages) due to pre-existing options \(registration.diagnosticOptions)", level: .warning)
224+
}
225+
return
226+
}
227+
let registrationOptions = DiagnosticRegistrationOptions(
228+
documentSelector: self.documentSelector(for: languages),
229+
diagnosticOptions: options)
230+
let registration = CapabilityRegistration(
231+
method: DocumentDiagnosticsRequest.method,
232+
registerOptions: self.encode(registrationOptions))
233+
234+
self.pullDiagnostics[registration] = registrationOptions
235+
236+
registerOnClient(registration)
237+
}
238+
205239
/// Dynamically register executeCommand with the given IDs if the client supports
206240
/// it and we haven't yet registered the given command IDs yet.
207241
public func registerExecuteCommandIfNeeded(

Sources/SourceKitLSP/Clang/ClangLanguageServer.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ extension ClangLanguageServerShim {
515515
forwardRequestToClangdOnQueue(req)
516516
}
517517

518+
func documentDiagnostic(_ req: Request<DocumentDiagnosticsRequest>) {
519+
forwardRequestToClangdOnQueue(req)
520+
}
521+
518522
func foldingRange(_ req: Request<FoldingRangeRequest>) {
519523
queue.async {
520524
if self.capabilities?.foldingRangeProvider?.isSupported == true {

Sources/SourceKitLSP/SourceKitServer.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ public final class SourceKitServer: LanguageServer {
202202
registerToolchainTextDocumentRequest(SourceKitServer.colorPresentation, [])
203203
registerToolchainTextDocumentRequest(SourceKitServer.codeAction, nil)
204204
registerToolchainTextDocumentRequest(SourceKitServer.inlayHint, [])
205+
registerToolchainTextDocumentRequest(SourceKitServer.documentDiagnostic,
206+
.full(.init(items: [])))
205207
}
206208

207209
/// Register a `TextDocumentRequest` that requires a valid `Workspace`, `ToolchainLanguageServer`,
@@ -709,6 +711,11 @@ extension SourceKitServer {
709711
self.dynamicallyRegisterCapability($0, registry)
710712
}
711713
}
714+
if let diagnosticOptions = server.diagnosticProvider {
715+
registry.registerDiagnosticIfNeeded(options: diagnosticOptions, for: languages) {
716+
self.dynamicallyRegisterCapability($0, registry)
717+
}
718+
}
712719
if let commandOptions = server.executeCommandProvider {
713720
registry.registerExecuteCommandIfNeeded(commands: commandOptions.commands) {
714721
self.dynamicallyRegisterCapability($0, registry)
@@ -1209,6 +1216,14 @@ extension SourceKitServer {
12091216
languageService.inlayHint(req)
12101217
}
12111218

1219+
func documentDiagnostic(
1220+
_ req: Request<DocumentDiagnosticsRequest>,
1221+
workspace: Workspace,
1222+
languageService: ToolchainLanguageServer
1223+
) {
1224+
languageService.documentDiagnostic(req)
1225+
}
1226+
12121227
/// Converts a location from the symbol index to an LSP location.
12131228
///
12141229
/// - Parameter location: The symbol index location

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,11 @@ extension SwiftLanguageServer {
13261326
}
13271327
}
13281328
}
1329+
1330+
public func documentDiagnostic(_ req: Request<DocumentDiagnosticsRequest>) {
1331+
// TODO: Return provider object in initializeSync and implement pull-model document diagnostics here.
1332+
req.reply(.failure(.unknown("Pull-model diagnostics not implemented yet.")))
1333+
}
13291334

13301335
public func executeCommand(_ req: Request<ExecuteCommandRequest>) {
13311336
let params = req.params

Sources/SourceKitLSP/ToolchainLanguageServer.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public protocol ToolchainLanguageServer: AnyObject {
9797
func colorPresentation(_ req: Request<ColorPresentationRequest>)
9898
func codeAction(_ req: Request<CodeActionRequest>)
9999
func inlayHint(_ req: Request<InlayHintRequest>)
100+
func documentDiagnostic(_ req: Request<DocumentDiagnosticsRequest>)
100101

101102
// MARK: - Other
102103

0 commit comments

Comments
 (0)