Protocol Overview
The Ori language server implements a subset of the Language Server Protocol (LSP) 3.17.
Lifecycle
Initialization
Client Server
│ │
│──── initialize ──────────────────►│
│ │
│◄─── initialize result ────────────│
│ (capabilities) │
│ │
│──── initialized ─────────────────►│
│ │
Server Capabilities (Phase 1):
{
"capabilities": {
"textDocumentSync": {
"openClose": true,
"change": 1,
"save": { "includeText": false }
},
"documentFormattingProvider": true,
"hoverProvider": true,
"definitionProvider": true,
"completionProvider": {
"triggerCharacters": [".", "@", "$"] // Advertised but not context-aware — see note below
}
}
}
Note on trigger characters: The server advertises
[".", "@", "$"]as completion trigger characters, but the current completion implementation ignores position context. Completions return the same keyword/snippet/function list regardless of which trigger character was typed or where the cursor is.
Shutdown
Client Server
│ │
│──── shutdown ────────────────────►│
│◄─── null ─────────────────────────│
│ │
│──── exit ────────────────────────►│
│ │
Text Document Synchronization
The server uses full sync (TextDocumentSyncKind.Full = 1). On each change, the client sends the entire document text. This is simpler than incremental sync and sufficient for current document sizes.
Document Open
interface DidOpenTextDocumentParams {
textDocument: {
uri: string;
languageId: "ori";
version: number;
text: string;
}
}
On open:
- Store document in memory
- Run diagnostics
- Publish diagnostics to client
Document Change
interface DidChangeTextDocumentParams {
textDocument: { uri: string; version: number };
contentChanges: TextDocumentContentChangeEvent[];
}
On change:
- Replace stored document text with full content from client
- Debounce diagnostic updates (50-100ms)
- Run diagnostics (lex, parse, type check)
- Publish diagnostics to client
Document Close
Remove document from memory. Stop publishing diagnostics.
Request Methods
textDocument/formatting
Request:
interface DocumentFormattingParams {
textDocument: { uri: string };
options: {
tabSize: number; // Ignored (Ori uses 4 spaces)
insertSpaces: boolean; // Ignored (Ori always uses spaces)
}
}
Response:
type TextEdit[] = {
range: Range;
newText: string;
}[];
Implementation:
- Get document text
- Call
ori_fmt::format() - Return single edit replacing entire document (simpler, fast enough)
textDocument/hover
Request:
interface HoverParams {
textDocument: { uri: string };
position: { line: number; character: number };
}
Response:
interface Hover {
contents: MarkupContent;
range?: Range;
}
Implementation:
- Find AST node at position
- Look up type from
ori_types - Format as markdown:
```ori x: int
textDocument/publishDiagnostics
Notification (server → client):
interface PublishDiagnosticsParams {
uri: string;
version?: number;
diagnostics: Diagnostic[];
}
interface Diagnostic {
range: Range;
severity: DiagnosticSeverity;
code?: string;
source: "ori";
message: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
Severity mapping:
| Ori | LSP |
|---|---|
| Error | DiagnosticSeverity.Error (1) |
| Warning | DiagnosticSeverity.Warning (2) |
| Hint | DiagnosticSeverity.Hint (4) |
textDocument/definition
Request:
interface DefinitionParams {
textDocument: { uri: string };
position: Position;
}
// Response: Location | Location[] | LocationLink[]
Implementation:
- Find AST node at position
- Search module for matching definition (function, type, variable)
- Return location of the definition
Future Methods (Phase 2+)
textDocument/references
interface ReferenceParams {
textDocument: { uri: string };
position: Position;
context: { includeDeclaration: boolean };
}
// Response: Location[]
textDocument/completion
interface CompletionParams {
textDocument: { uri: string };
position: Position;
context?: CompletionContext;
}
// Response: CompletionItem[] | CompletionList
Error Handling
LSP errors use standard codes:
| Code | Meaning |
|---|---|
| -32700 | Parse error |
| -32600 | Invalid request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| -32802 | Request cancelled |
For Ori-specific failures:
- Parse errors → publish as diagnostics (don’t fail the request)
- Type errors → publish as diagnostics
- Formatter errors → return empty edit array, publish diagnostic