2.6.5 Diagnostics Pipeline
The language server does not compute diagnostics itself. Diagnostics are served by an LSP pull pipeline (textDocument/diagnostic) that asks diagnostics providers. The pipeline gives each result a result identity and gates its results on the document version.
Providers
A diagnostics provider is a platform extension whose manifest advertises the DiagnoseDocument capability. The extension declares it with the assembly attribute [assembly: ProvidesCorePlatformClientCapability<DiagnoseDocument>] (ProvidesCorePlatformClientCapabilityAttribute<T>). rdc.exe describe-ext records the declaration in the extension's extension.manifest.json; see RD-VBAL §1.1.5 Extension Manifest.
The set of registered capabilities, not a hard-coded list, determines which extensions the language server asks for diagnostics.
| Provider | Registration |
|---|---|
| RDCore.Diagnostics | The core-bundled diagnostics provider. It is always brought up during platform assembly. |
| Other extensions (dimensional analysis, and so on) | Register as diagnostics providers alongside RDCore.Diagnostics. |
With no diagnostics provider registered, a workspace has no diagnostics.
Pull Model
Diagnostics use the LSP 3.17 pull model (textDocument/diagnostic). When the editor asks for the diagnostics of a document, the language server acts as orchestrator:
- It resolves the workspace document and its current version.
- It parses the document. This parse is the authoritative parse.
- It fans the parsed ModuleParseResult (see RD-VBAL §3.0 Abstract Syntax Tree) out to every registered provider, over the internal
rdcore/diagnostics/documentrequest. - It aggregates the LSP
Diagnostics the providers return, collapsing exact duplicates (the same range, code, source and message). - It answers the pull.
The language server owns the document and parser state and pushes them down to the diagnostics providers. A diagnostics provider therefore needs no parser or file-system access of its own.
Each diagnostics provider projects its own findings to LSP Diagnostics through ICoreDiagnosticsFactory.
Note
Not implemented. Proactive push of diagnostics (textDocument/publishDiagnostics) and workspace-wide diagnostics (workspace/diagnostic) are not implemented. Diagnostics are served by the document pull only.
rdcore/diagnostics/document
| Hop | Protocol |
|---|---|
| Editor → language server | plain LSP (textDocument/diagnostic) |
| Language server → diagnostics provider | RDCore request rdcore/diagnostics/document (DiagnoseDocumentRequest, answered by a DiagnoseDocumentResponse) |
The editor edge of the diagnostics pipeline stays plain LSP throughout. Only the language-server-to-provider hop is an RDCore request.
The rdcore/diagnostics/document request carries the parse result (DiagnoseDocumentPayload) as a PlatformJson string, because the syntax tree is polymorphic.
Note
Not implemented. The rdcore/diagnostics/document request does not carry a SemanticContext (resolver output). It carries the parse result.
Result Identity and Staleness
The diagnostic report's resultId tracks the document's in-memory version. A previousResultId that still matches is answered with a RelatedUnchangedDocumentDiagnosticReport, and the language server computes nothing.
Diagnostic results are staleness-gated:
- The document version is captured before the diagnostics fan-out.
- The version is re-checked after the fan-out.
- A report that raced a later edit is dropped rather than returned, and the
resultIdadvances to the current version.
Note
Not implemented. textDocument/didChange is not handled, so document versioning is inert. The document version only moves on workspace reload or rename.
Start-up
On start-up the language server pulls diagnostics for every loaded document once. This exercises the fan-out without an editor attached.
⏮️ RD-VBAL §2.6.4 Rubberduck Core Diagnostics | ⏭️ RD-VBAL §3.0 Abstract Syntax Tree