Add host-configurable LSP server

This commit is contained in:
2026-08-12 05:42:45 +09:00
parent bdaccd9803
commit 610358110f
11 changed files with 996 additions and 6 deletions
+8 -1
View File
@@ -43,14 +43,20 @@ The WebAssembly package is for execution, not syntax highlighting.
Semantic editor integration lives in the host-configurable language service crate.
It depends only on the runtime and accepts the same `HostEnvironment` implementation used by a production application.
A host-specific LSP binary can link this crate with its loader and global schema configuration without reimplementing evaluation rules.
The LSP crate adapts that service to the Language Server Protocol over stdin/stdout.
It provides full document synchronization, semantic diagnostics, and whole-document formatting.
A host-specific LSP binary injects its loader and global schema configuration without reimplementing evaluation rules.
Important paths:
```text
crates/decodal-language-service/
crates/decodal-lsp/
```
The default `decodal-lsp` binary reads Decodal imports from the filesystem.
Embedded hosts can call its library entry point with a custom `LspEnvironment` to reuse structured imports and to make unsaved external documents, such as Markdown, visible to the loader.
Source formatting lives in a separate Rust language tools crate.
Keeping it separate prevents host-specific semantic services from inheriting the formatter's Tree-sitter and WebAssembly dependencies.
@@ -124,6 +130,7 @@ Consumers that need syntax information should use the component that matches the
- Browser execution: `decodal-wasm`
- Web formatting and editor syntax: Lezer / CodeMirror
- Semantic editor analysis: `decodal-language-service`
- Language Server Protocol integration: `decodal-lsp`
- Rust formatting: `decodal-language-tools`
- General editor syntax: Tree-sitter
+18
View File
@@ -182,6 +182,24 @@ let analysis = service.analyze("site.dcdl", "site.dcdl", source);
Each analysis uses a fresh engine and runs the normal parse, evaluate, and materialize pipeline.
An environment may create loaders backed by shared filesystem, database, or editor-overlay state when repeated analysis needs a current workspace snapshot.
The LSP adapter constructs that environment after receiving the client's initialization parameters:
```rust
use decodal_lsp::{LspEnvironment, run_stdio};
impl LspEnvironment for AppEnvironment {}
run_stdio(|initialize| {
let _ = initialize;
Ok(AppEnvironment)
})?;
```
`LspEnvironment` adds document lifecycle hooks on top of `HostEnvironment`.
A `run_stdio` environment factory always receives the client's `InitializeParams`; the host decides whether to use its workspace folders, initialization options, and capabilities or ignore them.
A host that keeps unsaved buffers in shared state can update them from `open_document`, `change_document`, and `close_document`; every subsequent diagnostic pass creates the normal import loader from that updated environment.
Synchronized non-Decodal documents are passed through these hooks but are not evaluated as Decodal roots, so a loader can parse an unsaved Markdown file into `HostValue` and immediately revalidate the open Decodal documents that import it.
## Structured imports
`ImportLoader::load` returns either `LoadedImport::Source` or `LoadedImport::Value`.
+13 -1
View File
@@ -13,6 +13,18 @@ cargo check -p decodal --no-default-features
nix flake check
```
Run the default stdio language server with:
```sh
cargo run -q -p decodal-lsp
```
The protocol integration tests use an in-memory LSP connection and can be run independently:
```sh
cargo test -p decodal-lsp
```
Regex support is optional and should be tested explicitly when touched.
```sh
@@ -24,7 +36,7 @@ cargo run -q -p decodal-cli --features regex -- examples/regex/main.dcdl
The primary crates.io package is `decodal`, which contains the embeddable library.
`decodal-derive` provides optional derive macros for Rust struct integration and is published only when the derive crate changes.
Workspace support crates such as `decodal-cli`, the Rust source crate `decodal-wasm`, and `decodal-language-tools` are not published to crates.io.
Workspace support crates such as `decodal-cli`, the Rust source crate `decodal-wasm`, `decodal-language-tools`, and `decodal-lsp` are not published to crates.io.
The generated WebAssembly package under `packages/decodal-wasm/` is published to npm and JSR.
The CodeMirror package bundles the generated formatter WebAssembly from `decodal-language-tools`.
The project is dual licensed as `MIT OR Apache-2.0`.