Overview

Implementation Status: This document describes the LSP design roadmap. The current implementation is a minimal MVP — see individual feature docs for actual implementation status.

This documentation describes the design and implementation of the Ori Language Server (ori_lsp). The language server provides IDE features via the Language Server Protocol (LSP).

Implementation Status

The LSP server is implemented at tools/ori-lsp/ using:

  • tower-lsp crate for async LSP protocol implementation
  • DashMap for concurrent document storage
  • tokio for async runtime

Current Features:

  • ✅ Diagnostics (lex, parse, and type errors via oric::type_check())
  • ✅ Go to Definition (textDocument/definition)
  • ⚠️ Partial — Hover (function signatures and type definitions only)
  • ⚠️ Partial — Completions (keywords, snippets, and functions from current document)
  • ✅ Formatting (full document formatting via ori_fmt)

Not Yet Implemented:

  • ⚠ WASM compilation for browser playground (the Playground currently uses a separate runtime WASM module at website/playground-wasm/, not the LSP server compiled to WASM)
  • ⚠ Find References
  • ⚠ Document Symbols
  • ⚠ Code Actions
  • ⚠ Semantic Tokens

Goals

  1. Single implementation, multiple clients — One LSP server serves VS Code, Neovim, and any LSP-compatible editor
  2. Integrated — Leverages existing compiler infrastructure (ori_fmt, ori_types, etc.)
  3. Incremental — Start with essential features, expand over time

Reference Implementations

The Ori LSP design draws from established language server implementations:

LanguageKey Patterns Adopted
GleamFileSystemProxy, Response pattern
rust-analyzerSnapshot pattern, single main loop with select!, execution mode dispatch
Go (gopls)Structured diagnostics with SuggestedFix, modular analyzer design

Why These References

  • Gleam: Rust-based, similar scale, clean separation of LSP from compiler
  • rust-analyzer: Production-grade patterns for threading and cancellation
  • Go: Pioneered structured diagnostics with machine-applicable fixes

Architecture

flowchart TD
    subgraph LSP["ori-lsp (tools/ori-lsp/)"]
        direction TB
        Main["main.rs<br/>(Tokio runtime)"]
        Server["server.rs<br/>(OriLanguageServer)"]
        Docs["DashMap<Url, Document>"]

        Main --> Server
        Server --> Docs
    end

    Server --> oric["oric crate<br/>(lexer, parser, type_check, format)"]

    LSP --> Native["Native binary<br/>(VS Code, Neovim)"]
    LSP -.-> WASM["WASM module<br/>(Planned — NOT the Playground WASM)"]

Feature Roadmap

Phase 1: Foundation

FeatureLSP MethodPriorityStatus
FormattingtextDocument/formattingP0✅ Implemented
DiagnosticstextDocument/publishDiagnosticsP0✅ Implemented (lex, parse, type errors)
HovertextDocument/hoverP0⚠️ Partial
Go to DefinitiontextDocument/definitionP0✅ Implemented
CompletionstextDocument/completionP0⚠️ Partial (keywords, snippets, document functions)

Phase 2: Navigation

FeatureLSP MethodPriority
Find ReferencestextDocument/referencesP1
Document SymbolstextDocument/documentSymbolP1

Phase 3: Editing

FeatureLSP MethodPriority
CompletiontextDocument/completionP2
Signature HelptextDocument/signatureHelpP2
RenametextDocument/renameP2

Phase 4: Advanced

FeatureLSP MethodPriority
Code ActionstextDocument/codeActionP3
Inlay HintstextDocument/inlayHintP3
Semantic TokenstextDocument/semanticTokensP3

Documentation Sections

Protocol

Architecture

Features

Integration

Crate Location

tools/ori-lsp/
├── Cargo.toml
└── src/
    ├── main.rs          # Entry point with Tokio runtime
    └── server.rs        # OriLanguageServer implementation

Dependencies

Compiler Crates

CratePurpose
oricCompiler orchestration, type checking, formatting
ori_irAST and spans

LSP Infrastructure

CratePurpose
tower-lspAsync LSP protocol implementation
tokioAsync runtime
dashmapConcurrent HashMap for document storage
lsp-types(via tower-lsp) LSP protocol type definitions

Architecture Choice

We use tower-lsp for:

  • Async/await patterns with Tokio
  • Built-in concurrent request handling
  • Simpler trait-based handler implementation

Design Principles

  1. Leverage existing infrastructure — Use ori_fmt for formatting, ori_types for type info
  2. Async with tower-lsp — Concurrent request handling via Tokio
  3. DashMap for documents — Thread-safe concurrent document storage
  4. Full document sync — Simple full-text sync (incremental sync planned)
  5. Fast feedback — Prioritize responsiveness over completeness
  6. Graceful degradation — Partial results better than failure

Current Architecture

Document Storage

Documents are stored in a concurrent DashMap:

pub struct OriLanguageServer {
    client: Client,
    documents: DashMap<Url, Document>,
}

pub struct Document {
    pub text: String,
    pub module: Option<Module>,
    pub diagnostics: Vec<Diagnostic>,
}

Request Handling

tower-lsp handles concurrent requests automatically:

#[tower_lsp::async_trait]
impl LanguageServer for OriLanguageServer {
    async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
        // Access documents via DashMap
        let doc = self.documents.get(&uri)?;
        // ...
    }
}

Future Enhancements

Not Yet Implemented:

  • FileSystemProxy pattern (for unsaved edits across files)
  • Snapshot pattern (for parallel analysis)
  • Structured diagnostics with SuggestedFix
  • Incremental document sync