Editor support
LSP, syntax highlighting, and editor setup.
OpenSchema ships two independent pieces of editor tooling:
| Piece | Gives you | Lives in |
|---|---|---|
| Tree-sitter grammar | Syntax highlighting, folding, structural selection | tree-sitter-openschema/ |
| Language server (LSP) | Live diagnostics, hover, go-to-definition, completion, outline | src/lsp/ |
They work together but neither depends on the other. The instructions below are for Neovim 0.11+, but the LSP is a standard stdio server that works in any LSP-capable editor.
1. Tree-sitter grammar
The grammar mirrors the real lexer/parser: decorators and directives, leading
ordinals, model/enum/type/op/interface/overlay, the full type
algebra (scalars, decimal(p,s), arrays, maps, nullable, unions, oneof,
generics), and backtick-escaped identifiers.
Install (Neovim)
Requires the tree-sitter CLI.
editor/nvim/install.sh
This runs tree-sitter generate + tree-sitter build, then copies the compiled
parser to ~/.config/nvim/parser/openschema.so and the queries to
~/.config/nvim/queries/openschema/.
Work on the grammar
cd tree-sitter-openschema
tree-sitter generate # regenerate src/parser.c from grammar.js
tree-sitter test # run the corpus tests in test/corpus/
tree-sitter parse ../examples/ecommerce/orders.schema # inspect a parse tree
Highlight captures use the standard Neovim groups (@keyword, @type,
@type.builtin, @variable.member, @attribute, @comment.documentation, …),
so they pick up your colorscheme automatically.
2. Language server
The server (src/lsp/server.ts) runs the actual OpenSchema compiler over your
buffer, so the editor reports exactly what the CLI would — the same OS####
diagnostic codes, including ordinal, name-resolution, and overlay errors. It
follows import statements from disk, so a file that imports siblings does not
show false "undefined type" errors.
Features: diagnostics, hover, go-to-definition, find references, completion, and the document outline.
Find-references reports every place a type is used (field types, parameters,
return types, type arguments, unions, oneof variants, alias targets), plus its
declaration. It is currently scoped to the open document.
Hover explains declared types, scalar types, decorator names, and — the useful
part for enum-like arguments — known decorator argument values: hovering
backward in @compatibility(backward) describes the compatibility mode, and
the same applies to @visibility(...) phases and @format(...) values.
Completion is context-aware: after @ it offers decorators; inside a decorator
whose arguments are an enum (e.g. @compatibility() it offers the valid values;
elsewhere it offers scalars, keywords, and declared type names.
Run it
The server runs straight from source with Bun — no build step:
bun run src/lsp/server.ts # or: bun run lsp
Neovim setup
After installing the parser, add the bundled config:
-- in your init.lua, after copying or pointing at the repo file
vim.cmd("luafile /home/moritz/Documents/neoworks/openschema/editor/nvim/openschema.lua")
editor/nvim/openschema.lua registers the *.schema / *.openschema
filetype, turns on tree-sitter highlighting + folding, and wires the LSP via
vim.lsp.config / vim.lsp.enable. Edit the REPO_ROOT constant at the top if
you move the repo.
Using lazy.nvim? Do not put
editor/nvim/openschema.luain yourlua/plugins/directory — lazy imports every file there and expects each to return a plugin spec table, so a plain config module fails withinvalid spec module: plugins.openschema expected a table. Useeditor/nvim/lazy.luainstead, which returns a proper spec (a local, no-download plugin), e.g. copy it tolua/plugins/openschema.lua. The plainopenschema.luais only forrequire(...)or:luafile.
Neovim 0.10 or earlier lacks
vim.lsp.config/vim.lsp.enable. Start the server from aFileTypeautocmd instead:vim.api.nvim_create_autocmd("FileType", { pattern = "openschema", callback = function(args) vim.lsp.start({ name = "openschema", cmd = { "bun", "run", "/home/moritz/Documents/neoworks/openschema/src/lsp/server.ts" }, root_dir = vim.fs.root(args.buf, { "package.json", ".git" }), }) end, })
Other editors
The server speaks LSP over stdio with the launch command
bun run <repo>/src/lsp/server.ts. Point any LSP client at that command and
associate it with the schema/openschema extensions.
Sanity check
Open examples/ecommerce/orders.schema. You should see highlighting, an outline
(:lua vim.lsp.buf.document_symbol()), and — if you introduce a duplicate
ordinal or reference an undefined type — a diagnostic with an OS#### code.