feat(lsp): hover, documentSymbol, willSaveWaitUntil, token-wide diagnostic ranges
This commit is contained in:
+26
-45
@@ -16,10 +16,12 @@ Verified by hand against the built binary (`pgtidy lsp`, JSON-RPC 2.0 over stdio
|
||||
|
||||
| Capability | Value | Where |
|
||||
|---|---|---|
|
||||
| `textDocumentSync` | `1` (full sync) | `serverCaps` |
|
||||
| `textDocumentSync` | `{openClose: true, change: 1 (full), willSaveWaitUntil: true}` | `serverCaps` |
|
||||
| `documentFormattingProvider` | `true` | `handle("initialize")` |
|
||||
| `documentRangeFormattingProvider` | `true` | `handle("initialize")` |
|
||||
| `codeActionProvider` | `true` | `handle("initialize")` |
|
||||
| `hoverProvider` | `true` | `handle("initialize")` |
|
||||
| `documentSymbolProvider` | `true` | `handle("initialize")` |
|
||||
|
||||
### Supported methods
|
||||
|
||||
@@ -32,7 +34,10 @@ Verified by hand against the built binary (`pgtidy lsp`, JSON-RPC 2.0 over stdio
|
||||
| `textDocument/formatting` | req/resp | Full-doc format via `pkg/format`; returns one `fullReplace` `TextEdit`. |
|
||||
| `textDocument/rangeFormatting` | req/resp | Formats doc, returns minimal edit over the selected line range. |
|
||||
| `textDocument/codeAction` | req/resp | Returns quick-fix `WorkspaceEdit`s for fixable diagnostics overlapping the range. |
|
||||
| `textDocument/publishDiagnostics` | notif | Sent on every open/change; diagnostic code = `RuleID`, source = `pgtidy`. |
|
||||
| `textDocument/willSaveWaitUntil` | req/resp | Format-on-save: returns the same safety-gated edit as `formatting`. |
|
||||
| `textDocument/hover` | req/resp | Markdown with the rule ID + message of the diagnostic under the cursor; `null` elsewhere. |
|
||||
| `textDocument/documentSymbol` | req/resp | `CREATE FUNCTION`/`PROCEDURE` statements (name, kind Function, `function`/`procedure` detail, full range + name selection range). |
|
||||
| `textDocument/publishDiagnostics` | notif | Sent on every open/change; diagnostic code = `RuleID`, source = `pgtidy`; the range covers the offending token, not one character. |
|
||||
| `$/cancelRequest` | req | Ignored (per LSP, no response). |
|
||||
| unknown | req/resp | `-32601 method not found` (when the request has an `id`). |
|
||||
|
||||
@@ -47,33 +52,18 @@ Verified by hand against the built binary (`pgtidy lsp`, JSON-RPC 2.0 over stdio
|
||||
|
||||
## What the server does NOT provide (gaps)
|
||||
|
||||
These are the most useful, well-scoped gaps to fill next. None are blockers for the
|
||||
current shipping state.
|
||||
Done since the first inventory: real diagnostic highlight range, `hover`, `documentSymbol`,
|
||||
`willSaveWaitUntil`. Still open:
|
||||
|
||||
1. **No `hover`.** `textDocument/hover` is unimplemented and returns `-32601`.
|
||||
A natural first add: return the `RuleID` + a short explanation for diagnostics
|
||||
on the hovered range, or a keyword/type doc for `hover` on SQL identifiers.
|
||||
2. **No `documentSymbol` / `documentLink`.** No outline/symbol tree. For a formatter
|
||||
that already parses `CREATE FUNCTION`/`PROCEDURE` headers into a CST, a symbol
|
||||
provider listing functions/procedures would be low-cost and high-value in large
|
||||
schema files.
|
||||
3. **`hover`-style diagnostics shape.** Diagnostics currently use a `Range` whose
|
||||
`end.character` is `start.character + 1` (a 1-char caret), not the actual
|
||||
offending span. A real highlight range would improve editor UX.
|
||||
4. **`textDocument/willSave` / `willSaveWaitUntil` / `didSave`.** No save hooks —
|
||||
"format-on-save" must currently be driven by the client binding
|
||||
`textDocument/formatting` to the editor's save event. A `willSaveWaitUntil`
|
||||
handler would let the server own format-on-save.
|
||||
5. **No `completion`.** `textDocument/completion` is not implemented. Not urgent for
|
||||
a formatter/linter, but relevant if PL/pgSQL autocompletion (keywords, types) is
|
||||
ever in scope.
|
||||
6. **No diagnostics debounce/coalescing beyond full-sync.** Every `didChange`
|
||||
re-runs the full lint engine. Fine for now; a debounce + incremental re-check
|
||||
becomes relevant on large files.
|
||||
7. **`initializationOptions` / workspace config.** `initialize` params are parsed
|
||||
nowhere — no way to pass style overrides or a config path over the protocol.
|
||||
8. **No `textDocument/prepareRename`, `rename`, `references`, `foldingRange`.**
|
||||
Low priority; would be natural extensions once symbol info exists.
|
||||
1. **No `completion`.** `textDocument/completion` is not implemented. Not urgent for a
|
||||
formatter/linter.
|
||||
2. **No diagnostics debounce/coalescing beyond full-sync.** Every `didChange` re-runs the full
|
||||
lint engine. Fine for now; matters on large files.
|
||||
3. **`initializationOptions` / workspace config.** `initialize` params are parsed nowhere — no
|
||||
way to pass style overrides or a config path over the protocol.
|
||||
4. **No `prepareRename`, `rename`, `references`, `foldingRange`, `documentLink`.** Low priority;
|
||||
`documentSymbol` now provides the symbol info they would build on.
|
||||
5. **Hover is diagnostics-only.** No keyword/type glossary for hover on plain identifiers.
|
||||
|
||||
## Conventions to keep consistent
|
||||
|
||||
@@ -89,22 +79,13 @@ current shipping state.
|
||||
|
||||
## Concrete next steps (recommended, smallest-first)
|
||||
|
||||
Ranked by effort/value for the smallest useful delta:
|
||||
1. **`initializationOptions`**: accept a config path / style overrides in `initialize`.
|
||||
2. **Debounce `didChange` diagnostics.**
|
||||
3. **Hover glossary** for keywords/types.
|
||||
|
||||
1. **Add a real diagnostic highlight range** (swap the 1-char caret for the actual
|
||||
offending span) — ~1 file, no new method, immediate UX win. Reuses existing
|
||||
`RuleID`/severity data.
|
||||
2. **Add `textDocument/hover`** returning the rule explanation for the hovered
|
||||
diagnostic, or a keyword/type glossary. Reuses `pkg/lint` rule metadata.
|
||||
3. **Add `documentSymbol`** listing `CREATE FUNCTION`/`PROCEDURE` signatures.
|
||||
Reuses the existing CST header parse in `pkg/format`.
|
||||
4. **Add `willSaveWaitUntil`** to own format-on-save instead of relying on client
|
||||
binding.
|
||||
|
||||
> Do NOT: expand the LSP surface into a broad design (workspace features,
|
||||
incremental parsing, custom `textDocument/*` extensions) as part of this issue.
|
||||
Keep any change scoped to the above and evidence-backed by a `pkg/lsp` test
|
||||
(see `server_test.go` for the framed-request/response harness).
|
||||
> Do NOT: expand the LSP surface into a broad design (workspace features, incremental
|
||||
parsing, custom `textDocument/*` extensions). Keep any change scoped and evidence-backed by
|
||||
a `pkg/lsp` test (see `server_test.go` for the framed-request/response harness).
|
||||
|
||||
## Verification
|
||||
|
||||
@@ -112,5 +93,5 @@ Ranked by effort/value for the smallest useful delta:
|
||||
- `go test ./...` passes (LSP unit tests in `pkg/lsp/server_test.go` exercise
|
||||
`initialize`, formatting, range formatting, `didClose` diagnostics clearing).
|
||||
- Runtime e2e smoke test (framed JSON-RPC over stdio) confirmed `initialize`
|
||||
capabilities, `COR001` diagnostics, and a formatting edit; `hover` correctly
|
||||
returns `-32601`.
|
||||
capabilities, `COR001` diagnostics, and a formatting edit. `hover`, `documentSymbol` and
|
||||
`willSaveWaitUntil` are covered by tests in `pkg/lsp/server_test.go`.
|
||||
|
||||
Reference in New Issue
Block a user