Skip to content

v1.0.5 — LSP protocol conventions

Choose a tag to compare

@kurushimee kurushimee released this 12 Jun 11:42
cafc1d9

The LSP protocol-conventions release. A post-v1.0.4 audit compared every exposed capability against the LSP 3.17 spec and the rust-analyzer/gopls/clangd conventions and filed twelve issues (#43#54); this release closes all of them. Godot message strings, spans, and severities are untouched throughout: both conformance ratchets hold at parser 186/186 and analyzer 300/300.

Ranges anchor the symbol name token (#44, #46, #48)

  • Cross-file definition returns the member's name token, not the whole declaration node — MemberDecl records name_span at interface-extraction time (index cache format v4; old caches rebuild cold once on upgrade). Native-stub jumps land on the member's name token too.
  • workspace/symbol results carry real name-token ranges instead of zero-width points at column 0.
  • callHierarchy fromRanges cover the callee name token instead of the whole call expression — multi-line calls no longer highlight entire blocks.

Client capabilities honored (#43, #45, #47, #52)

  • documentSymbol downgrades to flat SymbolInformation[] for clients without hierarchicalDocumentSymbolSupport (Helix explicitly declines the nested shape).
  • references honors includeDeclaration: false as a filter at final assembly.
  • The empty workspace/symbol query returns all symbols (classes first, capped at 256) so symbol pickers open populated.
  • UNUSED_/UNREACHABLE_ diagnostics carry DiagnosticTag.Unnecessary (editors fade dead code), gated on client tagSupport; every warning-coded diagnostic links Godot's warning docs via codeDescription.

Call hierarchy correctness (#49, #50, #51)

  • Outgoing to items are expandable (they carry the same data blob prepare/incoming items do; data-less items re-resolve from uri + selectionRange).
  • Native callees anchor into their API stubs at the member's name token — the fabricated (0,0)-in-the-caller's-file item is gone, and unresolvable callees are omitted.
  • detail is populated everywhere: documentSymbol outlines render member signatures, call-hierarchy items carry their res:// script path (native items the declaring class).

Navigable diagnostics (#53)

  • SHADOWED_VARIABLE / SHADOWED_VARIABLE_BASE_CLASS publish relatedInformation pointing at the shadowed declaration's name token, even cross-file. Message strings stay byte-identical.

References precision (#54, pulled forward from Phase 2)

  • Binding::Call classifies its callee as a CalleeTarget (Script with owning class path / Native / Unresolved) derived from the resolution the dispatch actually used.
  • In-file attribute reads (self.hp) record Binding::Use, closing the last attribute-read recording gap.
  • References on resolved member targets are binding-backed: unrelated same-named members in different classes no longer report each other's sites; the "over-approximate, never under-report" raw scan survives only where resolution genuinely can't decide.

Validation

  • Diagnostics sweeps held exactly on both acceptance projects: Pixelorama (0 error-files / 119 warnings, strict profile identical) and a 2,338-script production project (error and warning baselines identical to v1.0.4).
  • Three-layer fuzz gate (parse + analyze + index_invariants) clean; differential oracle vs Godot 4.6.3-stable green.

Install

Download the binary for your platform, unpack, and point your editor's LSP client at gdls (stdio). Verify with sha256sum -c SHA256SUMS.

Known issues — fixed in v1.0.6

  • Bare utility-function references (print.call_deferred(msg), arr.map(floor), var f := absi, const PRINTER = print) false-positive Identifier "X" not declared in the current scope. (#88) — fixed in v1.0.6.