Architecture

SharpLsp is built on a three-tier architecture that separates concerns between fast syntax operations and rich semantic analysis.
graph LR
Editor([Editor / IDE])
subgraph T1[Tier 1 β Rust LSP Host]
direction TB
LSP[LSP Server\nJSON-RPC over stdio]
Router[Request Router]
VFS[Virtual File System]
TS[tree-sitter\nC# and F# grammars]
Salsa[salsa cache]
LSP --> Router
LSP --> VFS
VFS --> TS
TS --> Salsa
end
IPC[[IPC\nMessagePack\nnamed pipes / Unix sockets]]
subgraph T2[Tier 2 β C# Sidecar]
direction TB
Roslyn[Roslyn\nMSBuildWorkspace]
Decompiler[ICSharpCode.Decompiler]
CSharpFeatures[completions\ndiagnostics\nrefactoring]
Roslyn --> Decompiler
Roslyn --> CSharpFeatures
end
subgraph T3[Tier 3 β F# Sidecar]
direction TB
FCS[FSharpChecker]
ProjInfo[Ionide.ProjInfo]
Fantomas[Fantomas]
FSharpLint[FSharpLint]
FCS --> ProjInfo
FCS --> Fantomas
FCS --> FSharpLint
end
Editor -- LSP 3.17 --> LSP
Router -- syntax under 5ms --> Salsa
Router -- semantic under 200ms --> IPC
IPC <--> Roslyn
IPC <--> FCS
Tier 1 β Rust LSP Host
The host process handles:
- LSP protocol: JSON-RPC over stdio, targeting LSP 3.17 behavior
- Virtual File System (VFS): In-memory file state with change tracking
- tree-sitter parsing: Incremental C# parsing at sub-millisecond speeds (F# grammar integration is pending; F# syntax features route to the sidecar)
- salsa cache: Incremental computation β only reprocess what changed
- Request routing: Fast syntax requests stay in Rust, semantic requests go to sidecars
Tier 2 β C# Sidecar (Roslyn)
A long-running .NET 10 process providing:
- MSBuildWorkspace for solution/project loading
- Roslyn-backed C# features: completions, diagnostics, code actions, refactoring
- ICSharpCode.Decompiler for go-to-decompiled-source
- MessagePack serialization over named pipes / Unix domain sockets
Tier 3 β F# Sidecar (FCS)
A separate .NET 10 process for F# support:
- FSharpChecker for type checking and analysis
- Ionide.ProjInfo for project system integration
- FSharpLint for additional diagnostics
IPC Protocol
Communication between the Rust host and .NET sidecars uses:
- MessagePack binary serialization (compact, fast)
- Named pipes (Windows) or Unix domain sockets (Linux, macOS)
- 4-byte little-endian length prefix framing
- Target: <500us round-trip overhead
Request Routing
| Category | Handler | Latency Target | Examples |
|---|---|---|---|
| Syntax-only | Rust (tree-sitter) | <5ms | documentSymbol, foldingRange |
| Semantic | Sidecar | <200ms | completion, hover, definition |
| Hybrid | Rust + Sidecar | <100ms | semanticTokens |
| Cached | Rust (salsa) | <1ms | Repeat requests, unchanged docs |