Skip to content

Migrate JSON-RPC layer to gumeniukcom/golang-jsonrpc2 - #170

Open
gumeniukcom wants to merge 1 commit into
vito:mainfrom
gumeniukcom:migrate-to-golang-jsonrpc2
Open

Migrate JSON-RPC layer to gumeniukcom/golang-jsonrpc2#170
gumeniukcom wants to merge 1 commit into
vito:mainfrom
gumeniukcom:migrate-to-golang-jsonrpc2

Conversation

@gumeniukcom

Copy link
Copy Markdown

Closes #169

Follow-up to #169 — promoting the migration branch to a PR so it's easier to review. Happy to adjust anything.

Summary

Replaces creachadair/jrpc2 with github.com/gumeniukcom/golang-jsonrpc2/v2 + its jsonrpcstdio transport. Net effect: −305/+176 lines across 22 files — the migration shrinks the code.

  • cmd/dang/main.go: jrpc2.NewServer/channel.LSP/stdrwcjsonrpcstdio.Serve(ctx, rpc, FramingContentLength, os.Stdin, os.Stdout).
  • pkg/lsp/handler.go: the Assigner map → declarative Register(rpc) with 17 RegisterTyped registrations; each handle_*.go gets typed params instead of req.UnmarshalParams boilerplate.
  • publishDiagnostics goes through the transport's Pusher taken from the request context — the server back-reference field and SetServer wiring are deleted entirely.
  • Existing tests are adapted to an in-process dispatcher harness with a test pusher; no assertions were weakened.

Semantics notes

  • Dispatch is sequential by default, which is stronger than jrpc2's notification barrier — the ordering guarantees LSP assumes (e.g. didChange fully applied before a subsequent hover) are preserved.
  • Request timeout is set to 15 minutes: the first didOpen in a project can legitimately take a while (dagger session + schema introspection), and jrpc2 had no timeout at all.
  • Handler error texts are logged server-side; clients receive standard JSON-RPC error codes. jrpc2's wire-level tracing hook did not survive the migration (can be re-added via middleware if you want it).

Test plan

  • go test ./... passes
  • Live LSP handshake verified (initialize → didOpen with a real textDocument/publishDiagnostics push on the wire → hover → shutdown, responses in order, exit 0)
  • Maintainer smoke test against a real dagger workspace

Replaces creachadair/jrpc2 with github.com/gumeniukcom/golang-jsonrpc2/v2
(jsonrpcstdio transport + typed method registration). The Assigner switch
becomes declarative RegisterTyped calls; each handler drops its
HasParams/UnmarshalParams boilerplate and takes typed params directly.
publishDiagnostics pushes through the transport's per-connection Pusher
from the request context instead of a stored *jrpc2.Server, so the
SetServer wiring disappears.

Parity kept: Content-Length framing (channel.LSP equivalent), all 17
methods with identical names and param types, shutdown's null result,
notification silence, clean-EOF lifecycle, server push. Dispatch is now
strictly sequential and in-order (the transport default) — stronger than
jrpc2's notification barrier and what LSP ordering assumes; a generous
15-minute per-request bound replaces jrpc2's absence of one (the library
defaults to 30s, too tight for the first didOpen's dagger session).

Behavior notes: handler error texts stay in server logs (clients receive
stable generic codes; formatting's document-not-found keeps -32602 via
RPCError), wire-level trace logging is replaced by handler-error logging,
and handler panics are now recovered and answered instead of crashing.
Tests migrated to drive the new dispatcher in-process with a test Pusher;
all assertions unchanged. Verified against a live LSP session
(initialize/didOpen with publishDiagnostics push/hover/shutdown).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: migrate the LSP's JSON-RPC layer to golang-jsonrpc2 (working branch, -305/+176 lines)

1 participant