7.7. LSP Server — Editor & AI Diagnostics
The daslang LSP server implements the
Language Server Protocol
for .das files. What it buys over the MCP tools:
push diagnostics — the compiler and lint report after every edit
with no explicit tool call — plus native go-to-definition, references,
hover, document / workspace symbols, call hierarchy, and
go-to-implementation.
Zero setup beyond a daslang binary and Python 3: no sgconfig, no tree-sitter, no MCP server.
7.7.1. Quick start
Claude Code sessions started at the daslang repository root (or at an
installed SDK root) load the server automatically — the checked-in
.claude/skills/daslang-lsp/.claude-plugin/plugin.json manifest
registers it on workspace trust. From any other directory, wire it in
explicitly with:
claude --plugin-dir /abs/path/to/daScript/utils/lsp/plugin
(The explicit form also takes precedence over the checked-in manifest when both are present, which is what you want while developing the server itself.)
Diagnostics then attach automatically to the next tool result after any
edit of a .das file, and the LSP tool exposes definition,
references, hover, documentSymbol, workspaceSymbol, implementation, and
call-hierarchy operations.
Any other stdio LSP client works too — point it at:
python3 utils/lsp/lsp_supervisor.py
Note
The plugin manifest spawns python3. On Windows, python.org
installs typically ship only python.exe — either create a
python3 alias or edit the manifest’s command locally.
7.7.2. Diagnostics
One lint-profile compile serves both error classes:
Compile errors publish with severity Error, the numeric daslang error code (e.g.
30341), and the exact source range.On a clean compile, the repo’s paranoid / performance / style lint passes run on the same program: LINT and PERF rules publish as Warning, STYLE rules as Information. Repo lint policy is honored (
.lint_config, default-off rules,// nolintcomments).
dastest expect-files (negative tests that declare intentional compile
errors via expect directives) get a single informational note
instead of their intentional errors.
Unsaved buffers are compiled as-is: the server shadows every open document and overlays the buffer text over the on-disk content for both diagnostics and navigation, so clients that validate while typing get correct positions without saving.
7.7.4. Configuration
initializationOptions (all optional):
Key |
Description |
|---|---|
|
Path to the daslang binary. |
|
|
|
Passed as |
|
List; each entry passed as |
Compiler lookup order: initializationOptions.compiler →
$DASLANG_LSP_COMPILER → repo and installed-SDK layouts
(bin/Release/daslang[.exe], bin/daslang[.exe],
build/daslang, build/bin/daslang) under the workspace and the
supervisor’s own tree → daslang on PATH. All option paths
(compiler, project, project_root, load_module) are
absolutized against the workspace root at initialize — subtools spawn
with a per-request cwd, so relative paths would otherwise re-resolve
per file.
Set DASLANG_LSP_LOG=<path> for a message-by-message debug log
(default: daslang_lsp.log in the system temp directory).
7.7.5. Architecture
Two processes, hard split:
utils/lsp/lsp_supervisor.py— the endpoint the client spawns. Owns all session state: Content-Length framing, theinitializehandshake, the document shadow, debounce, and request dispatch. Zero language knowledge.utils/lsp/subtools/*.das— stateless batch tools (validate.das,nav.das). One fresh daslang process per request: argv in, LSP-shaped JSON out, exit.
No resident daslang process ever runs, by design: no macro-state leaks
across compiles, no binary or DLL locks while builds run, and a
compiler crash on a broken buffer costs one request instead of the
session. Full rationale and wave history: utils/lsp/ROADMAP.md.
7.7.6. Tests
tests/lsp/test_lsp_protocol.das drives the supervisor over a stdio
pipe: initialize → didOpen with broken buffer text against a clean disk
file (proving the unsaved-buffer overlay) → didChange back to clean →
definition → the call-hierarchy loop (prepare → incoming → outgoing) →
implementation → shutdown/exit:
bin/daslang dastest/dastest.das -- --test tests/lsp
The test probes python3 then python and skips with a log notice
when neither is on PATH.
See also
utils/lsp/README.md — setup and configuration details
MCP Server — AI Tool Integration — the MCP server (pull-style tools: introspection, navigation, execution, live-reload control)