Language Server (LSP)
The Skein Language Server is an Elixir application (skein_lsp) that implements the Language Server Protocol. It uses the Skein compiler as its analysis engine.
Capabilities
Section titled “Capabilities”The server advertises these LSP capabilities:
| Capability | Description |
|---|---|
textDocument/publishDiagnostics | Compile errors and warnings |
textDocument/documentSymbol | Document outline (modules, functions, handlers) |
textDocument/hover | Type information on hover |
textDocument/definition | Go-to-definition for functions and types |
textDocument/completion | Context-aware code completion |
textDocument/codeAction | Quickfixes applied generically from each error’s span/edit_kind/fix_code (with a per-code fallback for span-less diagnostics) |
textDocument/semanticTokens/full | Semantic highlighting |
textDocument/didOpen | Document tracking |
textDocument/didChange | Full document sync |
textDocument/didSave | Save-triggered recompilation |
textDocument/didClose | Document cleanup |
How It Works
Section titled “How It Works”Diagnostics Pipeline
Section titled “Diagnostics Pipeline”When a document is opened, changed, or saved, the server runs the Skein compiler pipeline:
Source text │ ├── Skein.Lexer.tokenize/1 │ └── {:error, errors} → Lexer diagnostics │ ├── Skein.Parser.parse/2 │ └── {:error, errors} → Parser diagnostics │ └── Skein.Analyzer.analyze/1 ├── {:error, errors} → Analyzer diagnostics (AST still retained) └── {:ok, ast} → No diagnosticsEach Skein.Error is converted to an LSP Diagnostic with:
- Position mapped from 1-indexed (Skein) to 0-indexed (LSP)
- Severity mapped from
:error/:warningto LSP severity levels - Error code and fix hint included in the message
Symbol Extraction
Section titled “Symbol Extraction”The server walks the AST to extract symbols for the document outline:
| AST Node | Symbol Kind |
|---|---|
Module | Module |
Agent | Class |
Fn | Function |
TypeDecl | Struct |
EnumDecl | Enum |
Handler | Event |
AgentHandler | Event |
ToolDecl | Interface |
Supervisor | Namespace |
Test / Scenario / Golden | Function |
Field | Field |
Variant | EnumMember |
| State fields | Property |
Hover Resolution
Section titled “Hover Resolution”The hover provider uses a name-based lookup strategy:
- Extract the word at the cursor position
- Search declarations in the current AST for a matching name
- If no match, check built-in types (
Int,String,Option, etc.) - Format the result as a Markdown code block with type signature
Completion Engine
Section titled “Completion Engine”Completions are context-sensitive based on the text before the cursor:
| Context | Strategy |
|---|---|
After . | Look up the namespace and return its methods |
After : or -> | Return type completions |
After @ | Return annotation names |
| General | Keywords + types + user symbols + effect namespaces + snippets |
Implementation
Section titled “Implementation”The LSP server is built with GenLSP, which provides:
- OTP behaviour for LSP process management
- Typed structs for all LSP protocol messages
- Stdio communication transport
- Built-in error handling (exceptions don’t crash the server)
Dependencies
Section titled “Dependencies”| Package | Version | Purpose |
|---|---|---|
gen_lsp | v0.11.3 | LSP behaviour and protocol types |
typed_struct | v0.3.0 | Struct definitions (GenLSP dep) |
nimble_options | v1.1.1 | Option validation (GenLSP dep) |
schematic | v0.2.1 | Schema validation (GenLSP dep) |
skein_compiler | in_umbrella | Skein lexer, parser, analyzer |
Running the Server
Section titled “Running the Server”# Via the standalone binary (used by the VS Code extension by default)skein lsp
# Via mix task (inside a Skein compiler checkout)mix skein.lsp
# ProgrammaticallySkeinLsp.start()The server communicates over stdio using JSON-RPC as specified by the LSP protocol.
Testing
Section titled “Testing”The language server has a test suite covering all features (see CI for current counts):
mix test apps/skein_lsp/test/Tests exercise each module directly without needing a running LSP process:
- Diagnostics tests — Valid source produces no diagnostics; invalid source produces correct error codes, locations, and severities
- Symbols tests — Modules produce correct symbol hierarchies; agents include state fields, phases, and handlers
- Completion tests — Keywords, types, effect namespaces, and method completions after
. - Code action tests — Generic span/edit_kind quickfixes (replace, insert, line insert/delete) pinned against real compiler output, plus the per-code fallback for missing tokens (
E0001), missing capabilities (E0012), unused capabilities (W0002), and unused bindings (W0001) - Hover tests — Function signatures, built-in type descriptions
- Semantic token tests — Valid source encodes to groups-of-5 integers; invalid source returns empty