Package reference
Four packages. Three of them have no dependencies, and the fourth is the only one that costs you a WebSocket stack.
langserver01
JSON-RPC framing over Content-Length, request and notification handling, and a
handler map keyed by method name. A language module registers the methods it answers
and ignores the rest.
handlers := map[string]langserver.Handler{
"textDocument/completion": completion,
"textDocument/hover": hover,
}A handler receives the session and the raw params, and returns either a result or an
*RPCError. Nothing in the dispatch layer inspects what a method means.
Sessions02
Open documents, their versions and their content are held per connection. A handler is given the text it is being asked about instead of reading from disk and hoping the two agree.
langserver/lsp03
Positions and ranges, including the arithmetic that makes them correct. See Positions, which is the part most worth reading before you write your own.
offset := lsp.OffsetFromPosition(src, lsp.Position{Line: 2, Character: 14})
pos := lsp.PositionFromOffset(src, offset)Bindings04
stdio is how editors launch a server. ws is how a browser reaches one. They are
separate packages so that the dependency the second needs is not paid for by the
first.
The dependency boundary between the core packages and ws is checked in CI. A
convention that is only written down drifts; this one fails the build.
The boundary05
Nothing in the adapter is aware of a grammar, a type system or a symbol table. That is what lets it serve any language, and it is also why it cannot help you with any of them. The intelligence is yours to supply.