Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Language Server

mimas ships a language server to use in the editor of your choice. It is still very young but offers diagnostics, hover, navigation, rename, outlines, and inlay hints for scripting use. Scripts that use a Rust host’s functions and types are checked against that host’s API once it has run – see Host APIs.

What it supports

Diagnostics

Syntax and type errors are all reported inline in your editor. The lexer and parser are resilient to errors and will offer a full report of any syntax errors your code contains. The same is not true of today’s solver, which halts the first time it encounters an error. This means that you can get multiple syntax errors at once, but can only get one type error at a time (the same is true of the compiler however you use it). This will be improved in future releases.

Hover

Hovering a name shows what it is and what type it has. If its declaration has a /// doc comment, that shows underneath. For a function or type a Rust host registers, that’s the /// on the Rust item.

You hoverYou get
a local, parameter, or fieldx: int
a function or methodthe owner on one line, the declaration on the next
a struct or enumits qualified name, like one::two::Foo
a constantconst SCALE: int
a modulemodule `fs`
anything elsethe expression’s type

Functions carry where they came from, which matters once a project has modules:

// hovering `bar` anywhere it is used or declared
one::two::Foo
fn bar(self, fizz: int) -> Self

Go to definition

Any name that resolves to a declaration in your project jumps to it, across files. That covers locals, parameters, struct fields, functions, methods, structs, enums, and constants.

Find references

The same names work in reverse: ask for a declaration’s references and you’ll get every use of it in the project, wherever it lives. Resting your cursor on a name also highlights its other uses in the file you’re reading.

Rename

Renaming rewrites a name everywhere it appears in the project. Renaming a member of a pact carries every implementation with it, so the two can’t drift apart.

Outline

Your editor’s outline, breadcrumbs, and symbol search list what a file declares – types with their fields and variants, impl blocks with their methods, and a script’s top-level bindings. This is the one feature that only needs the syntax tree, so it keeps working while the rest of the file doesn’t.

Inlay hints

A let written without an annotation shows the type that was inferred for it.

let count = items.len(); // your editor can render this as `let count: int = ...`

What it does not support

  • The solver is not resilient. This means that any error will cut off type information and you’ll be left with only that error in the editor. Everything but diagnostics and the outline goes quiet until the project checks cleanly again, which you’ll notice most while mid-keystroke.
  • No completion, formatting, signature help, or code actions. These are the obvious next steps, but none of them exist today.
  • Navigation stops at the language boundary. Natives from the standard library or a host, builtin types like int, and module names have no mimas source to jump to, so nothing happens. We will support navigating to the Rust definition in the future.
  • One host per workspace. The server loads a single file, found from the first workspace folder. A workspace whose crates embed mimas with different APIs, or several workspace folders, all share it.

Setting it up

The server

The VS Code extension bundles the server, so skip this step if that’s your editor. Otherwise, install the lsp via cargo:

cargo install mimas-lsp

That puts a mimas-lsp binary on your PATH, which is where editors will look for it by default.

The extension

Install mimas from the Visual Studio Code marketplace. Each release also attaches the extension’s .vsix files to its GitHub release, which you can install by opening the command palette and selecting “Install from VSIX”. Its source lives in tools/vscode.

Other editors

Any LSP client works. The server speaks the protocol over stdio, takes no arguments, and wants to be started for the mimas language on .mim files. In Neovim, for example:

vim.lsp.config.mimas = {
    cmd = { "mimas-lsp" },
    filetypes = { "mimas" },
    root_markers = { "Cargo.toml", ".git" },
}
vim.lsp.enable("mimas")

Host APIs

When a Rust host embeds mimas, its scripts use the functions, types, and constants it registers. The server learns about those from a file the host writes. Running the host from its cargo target dir writes its API to target/mimas/api.json, which the server finds by asking cargo where your target dir is. You’ll be notified if it can’t find that file. After you change the host’s API, run it again, and diagnostics pick up the change on your next edit.

  • The host and the server have to be the same version of mimas. On a mismatch, the server shows a warning and falls back to the standard library alone.
  • To turn the automatic write off, depend on mimas with default-features = false.
  • Only a binary running from inside a cargo target dir writes the file automatically, so a shipped build never does, and neither do test or bench builds. If you want to export it yourself (e.g. for modding support), call mimas::write_api.
let library = mimas::Vm::new().install_library(mimas::library::std);
mimas::write_api(&library, "scripts/api.json".as_ref())?;

In VS Code, the mimas.apiPath setting points the server at a different file (relative to the workspace folder), or turns it off with off, which leaves the standard library alone. The mimas: Select Host API Manifest command sets it with a file dialog, and mimas: Restart Language Server restarts the server, which also happens on its own when the setting changes. Other editors pass the same value as apiPath in the server’s initialization options. In Neovim, add it to the config above:

init_options = { apiPath = "path/to/api.json" },