The language server#
alpha lsp speaks JSON-RPC on stdio. It contains no language knowledge: every
answer comes from the engine, the linter, the symbol index or the formatter.
What it answers#
| request | source of the answer |
|---|---|
publishDiagnostics | the incremental checker plus the linter |
hover | the symbol index and the module's own text |
definition, references, rename | the symbol index, by symbol IDENTITY |
documentSymbol, workspace/symbol | the symbol index |
completion | the module grammar's visibility rules |
formatting | the canonical formatter |
codeAction | the linter's fix-its, plus "import the module this name comes from" |
inlayHint | the module an unqualified name is imported from |
Rename is semantic, never textual: every edit lands on a span that really holds the name, and the harness checks that (38 edits over 9 files, all verified).
Costs, measured#
From debug/lsp-check.py, recorded in docs/generated/ALPHA-LSP-CHECK.json
(committed 2026-09-19, on this repository's own workspace):
- first answer after opening a workspace: 13.7 s (the closure check plus the index)
- an edit: 404 ms to republish that file's diagnostics — an edit re-indexes ONE file and does not run a workspace check
- a workspace symbol query with the index warm: 43 ms
What it does not do#
The closure check runs when the workspace opens (initialized) and on every
save (didSave), not on every keystroke. Opening or editing a document
re-indexes only that document. Engine diagnostics therefore reflect saved
bytes while lint findings reflect the buffer. That is a deliberate split, and
the editor is told which is which by severity.
Editor package#
editors/vscode starts this server and holds no language logic. Its TextMate
grammar is generated from the edition's feature registry, so the keyword set
cannot drift from the language.
To use it, build alpha, put it on PATH (or set alpha.serverPath), then
install the extension from source: cd editors/vscode && npm install, and
either press F5 in that folder or package it with vsce package. It activates
on .alpha files and in any workspace containing alpha.project, runs
alpha lsp --quiet in the first workspace folder, and forwards changes to
alpha.project and alpha.lock to the server. Settings: alpha.serverPath
(default alpha) and alpha.trace.server (off, messages, verbose).
The command Alpha: Restart Language Server restarts it by hand. The same
extension registers the alpha debug type, which runs alpha debug (see
the debugger adapter).
Any editor with a Language Server Protocol client can run alpha lsp the same
way: it speaks JSON-RPC on stdio from the workspace directory.
Evidence#
debug/lsp-check.py drives the server as an editor does and compares every
answer with the command line: 16 checks in the committed run, including
references equal to alpha inspect references --json exactly.