pro_lsp
Unified LSP 3.18 Dart bindings and a typed server/client framework. pro_lsp
is lightweight, transport-agnostic, and strictly type-safe — build Language
Servers and Language Clients in Dart without hand-writing JSON-RPC plumbing.
import 'package:pro_lsp/pro_lsp.dart';
void main() async {
final server = LspServer();
server.general.onInitialize((params, context) async {
return const InitializeResult(
capabilities: ServerCapabilities(hoverProvider: .bool(true)),
serverInfo: ServerInfo(name: 'my-dart-lsp', version: '1.0.0'),
);
});
server.textDocument.onHover((params, context) async {
return Hover(
contents: HoverContents.markupContent(
MarkupContent(kind: .markdown, value: '`${params.textDocument.uri}`'),
),
);
});
// Blocks until the client exits. `shutdown`/`exit` are handled for you.
await server.listen();
}
Never write to
stdoutfrom a stdio server. On stdio,stdoutis the protocol channel — a strayprint()corrupts the JSON-RPC stream. Log tostderror a file, and setserver.onError. See Building a server → Logging.
Why pro_lsp
- Complete LSP 3.18 surface, generated from the official Microsoft
meta-model: Freezed structures (
copyWith, value equality, JSON),extension typeunions, and open/closed enums. - Typed, symmetric API — incoming messages are handlers
(
server.textDocument.onHover(...)); outgoing messages are senders (server.client.window.showMessage(...)). The client mirrors the server. - Lifecycle handled for you — an enforced state machine
(uninitialized → initialized → shuttingDown → exited) with sensible
shutdown/exitdefaults. - Cancellation both ways via
CancellationToken, plustimeouton outgoing requests. - Typed errors — everything surfaces as
LspException; you never touch the transport'sRpcException. - Pluggable & extensible — modular
LspFeatures, middleware, and a built-in service container (DI). - Transport-agnostic framing over stdio, TCP, or any byte stream via
LspByteStreamChannel.
Install
dart pub add pro_lsp
Requires Dart SDK ^3.10 — the generated API uses recent language features,
including dot-shorthands for enums and union factories (.bool(true),
.markdown). Where the target type is known, you can drop the type name and
start with ..
Documentation
The full guide lives in doc/. Start there for concepts,
end-to-end walkthroughs, and a per-method tutorial covering every LSP request
and notification with "what / when / example".
Guides
- Getting started — install, first server, first client
- Core concepts — handlers, senders, context, lifecycle
- Building a server — capabilities, talking back, lifecycle, logging
- Building a client — handshake, calling the server, receiving messages
- Working with models — Freezed structures, unions, enums
- Error handling —
LspException, error codes - Cancellation — incoming and outgoing
- Testing — in-memory client↔server
- Transports — stdio, sockets, custom framing
- Advanced — features, dependency injection, middleware
Method reference (catalog)
- Lifecycle & protocol — initialize, shutdown, progress, trace
- Document sync — didOpen / didChange / didClose / save
- Language features — hover, definition, completion, …
- Call & type hierarchy
- Workspace — symbols, commands, files, configuration, refresh
- Window — messages, progress, show document
- Notebooks
License
MIT — see LICENSE for details.