Skip to content

Language Server

Rust

The VM Registry LSP (vm-registry-lsp) is a Language Server Protocol implementation that provides editor intelligence for VMFile and VMCompose YAML files. It delivers real-time diagnostics, context-aware completions, and hover documentation directly in your editor — catching errors as you type rather than at deploy time.

Overview

The LSP is a standalone Rust binary that communicates with editors over the standard LSP JSON-RPC protocol via stdin/stdout. It understands the full schema of both VMFile and VMCompose formats, providing the same validation logic that the daemon applies at import/deploy time but with immediate, inline feedback.

text
Editor (Zed, Neovim, VS Code, etc.)

    │  LSP JSON-RPC (stdin/stdout)


vm-registry-lsp
    ├── Document tracking
    ├── YAML parsing
    ├── Schema validation
    ├── Completion engine
    └── Hover documentation

Building

bash
cd vm-registry-lsp
cargo build --release

The binary is produced at target/release/vm-registry-lsp.

Editor Configuration

Zed

Add the following to your Zed settings.json:

json
{
  "lsp": {
    "vm-registry-lsp": {
      "binary": {
        "path": "/path/to/vm-registry-lsp"
      }
    }
  },
  "languages": {
    "YAML": {
      "language_servers": ["vm-registry-lsp"]
    }
  }
}

Neovim (nvim-lspconfig)

lua
local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')

configs.vmregistry = {
  default_config = {
    cmd = { '/path/to/vm-registry-lsp' },
    filetypes = { 'yaml' },
    root_dir = lspconfig.util.find_git_ancestor,
    settings = {},
  },
}

lspconfig.vmregistry.setup {}

VS Code

Create a .vscode/settings.json in your workspace:

json
{
  "yaml.customTags": [],
  "vmregistry.lsp.path": "/path/to/vm-registry-lsp"
}

TIP

The LSP activates for files matching VMFile and VMCompose patterns. It detects the file kind based on content — files containing a services key are treated as VMCompose, while files containing metadata and spec keys are treated as VMFile.

Capabilities

Diagnostics

The LSP validates documents in real-time as you edit, reporting errors and warnings inline. Diagnostics cover:

Structural validation:

  • Missing required fields (apiVersion, metadata.name, spec.diskImage, services, etc.)
  • Unknown or misspelled field names at every nesting level
  • Incorrect value types (e.g., a string where an integer is expected)

Value validation:

  • apiVersion matches a known version (vmregistry.io/v1alpha1 or v1)
  • diskFormat is one of qcow2, raw, iso
  • bootloader.type is UEFI or BIOS
  • Network mode is one of nat, isolated, routed, bridge, open, macvtap, or default
  • restartPolicy is one of always, on-failure, never, unless-stopped
  • Network driver is one of bridge, nat, isolated, macvtap

Format validation:

  • Memory values match the <number><unit> pattern with valid units (MiB, GiB, TiB)
  • IP addresses use valid IPv4 dotted-decimal notation
  • Subnets use valid CIDR notation (e.g., 192.168.100.0/24)
  • MAC addresses use colon-separated hex format (e.g., 52:54:00:12:34:56)
  • Service and network names follow the naming pattern (lowercase letters, digits, hyphens)

Cross-reference validation (VMCompose):

  • Service dependsOn entries reference services that exist in the file
  • Service network name entries reference networks defined in the top-level networks section
  • Detection of cyclic dependencies between services

Completions

The LSP provides context-aware completions with snippet support. When you trigger completion:

  • At the top level, it suggests root fields (apiVersion, metadata, spec, services, networks, etc.)
  • Inside a mapping, it suggests the valid child fields for that context
  • For enum fields, it suggests only the allowed values with descriptions
  • Completions include snippet templates that expand into multi-line structures with tab stops

For example, completing inside spec in a VMFile offers:

CompletionSnippet
diskImagediskImage: disk.qcow2
diskFormatdiskFormat: qcow2|raw|iso
resourcesMulti-line block with cpu, memory, and bootloader

Hover

Hovering over any field name displays documentation including:

  • A description of the field's purpose
  • Whether the field is required or optional
  • The expected value type
  • For enum fields, the list of valid values with explanations
  • Format requirements (e.g., memory pattern, CIDR notation)

File Kind Detection

The LSP automatically detects whether a YAML file is a VMFile or VMCompose based on its content:

IndicatorDetected Kind
Contains services keyVMCompose
Contains kind: VMComposeVMCompose
Contains metadata and spec keysVMFile
File extension .VMComposeVMCompose
File named VMFile or *.VMFileVMFile

Each file kind activates a different schema, ensuring that completions, diagnostics, and hover documentation are appropriate for the document type.

Schema Architecture

All validation, completion, and hover intelligence is driven by a centralized schema definition (src/schema.rs). The schema encodes:

  • Field descriptors — name, documentation, required status, value type, enum values, child fields, and completion snippets for every field in both VMFile and VMCompose formats
  • Value typesStr, Int, Bool, Mapping, SeqScalar, SeqMapping, DynamicMapping, MemoryStr, IpAddr, Cidr, MacAddr, DiskSize
  • Path resolution — resolving dotted YAML paths to field descriptors, with support for dynamic mappings (where user-defined keys like service names act as intermediate path segments)
  • Enum documentation — short descriptions for each valid value of enum fields, displayed in completion detail text

This schema mirrors the validation logic in the daemon's VMFile and VMCompose parsers, ensuring consistency between editor-time and deploy-time validation.

Internal Structure

ModuleResponsibility
main.rsLSP server initialization, capability registration, and main event loop
dispatch.rsMessage dispatcher — routes incoming LSP notifications and requests to the appropriate handler
document.rsDocument tracking — maintains the current state of open files, detects file kind
schema.rsSchema definitions — field descriptors, value types, path resolution, and enum documentation for VMFile and VMCompose
diagnostics.rsDiagnostic engine — validates documents against the schema and produces LSP diagnostic messages
completion.rsCompletion engine — generates context-aware completion items with snippets based on cursor position and schema
hover.rsHover engine — resolves the field at the cursor position and formats documentation for display
yaml_util.rsYAML utilities — cursor-to-path resolution, node traversal, and YAML-specific helpers

Dependencies

DependencyPurpose
lsp-serverLSP protocol transport layer (JSON-RPC over stdin/stdout)
lsp-typesLSP type definitions (messages, capabilities, diagnostics, completions, etc.)
crossbeam-channelChannel-based message passing for the LSP event loop
yaml-rust2YAML parser for analyzing document structure
serde / serde_jsonJSON serialization for LSP message payloads
log / env_loggerLogging for development and debugging

Built with Go and Rust