From 9c27bac61df9b26b4cea580691e698bc51976684 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Mon, 15 Sep 2025 15:07:04 -0400 Subject: [PATCH] Handle inlay hint requests asynchronously Inlay hints on Dockerfiles need to fetch data so it can take some time before the result can be returned. This means that everything else gets blocked because all JSON-RPC messages are being handled synchronously at the moment. To alleviate this problem, we will check for inlay hint requests and then handle them in a goroutine asynchronously so that other messages can continue to be processed. Other messages may be changed to be handled asynchronously in the future but only inlay hint requests will be done this way for the time being. We want to be careful about introducing drastic changes to how messages are being handled as it is critical for the operation of the language server. Signed-off-by: Remy Suen --- CHANGELOG.md | 3 +++ internal/tliron/glsp/server/handler.go | 23 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3acb36..78d3f74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ All notable changes to the Docker Language Server will be documented in this fil ### Fixed +- Dockerfile + - textDocument/inlayHint + - handle inlay hints asynchronously so that it does not block other LSP messages when trying to fetch image data ([#467](https://github.com/docker/docker-language-server/issues/467)) - Compose - textDocument/documentLink - return document links for files referenced in the short-form `volumes` attribute of a service object ([#460](https://github.com/docker/docker-language-server/issues/460)) diff --git a/internal/tliron/glsp/server/handler.go b/internal/tliron/glsp/server/handler.go index 9eeeb37..a8e0551 100644 --- a/internal/tliron/glsp/server/handler.go +++ b/internal/tliron/glsp/server/handler.go @@ -6,13 +6,34 @@ import ( "fmt" "github.com/docker/docker-language-server/internal/tliron/glsp" + "github.com/docker/docker-language-server/internal/tliron/glsp/protocol" "github.com/sourcegraph/jsonrpc2" ) +// AsynchronousRequestHandler will selectively process some JSON-RPC +// messages asynchronously. +type AsynchronousRequestHandler struct { + handler jsonrpc2.Handler +} + +func asynchronousRequest(req *jsonrpc2.Request) bool { + // handle textDocument/inlayHint requests asynchronously + return !req.Notif && req.Method == protocol.MethodTextDocumentInlayHint +} + +func (h *AsynchronousRequestHandler) Handle(ctx contextpkg.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) { + if asynchronousRequest(req) { + go h.handler.Handle(ctx, conn, req) + } else { + // handle notifications synchronously so that the document changes do not overlap each other + h.handler.Handle(ctx, conn, req) + } +} + // See: https://github.com/sourcegraph/go-langserver/blob/master/langserver/handler.go#L206 func (self *Server) newHandler() jsonrpc2.Handler { - return jsonrpc2.HandlerWithError(self.handle) + return &AsynchronousRequestHandler{handler: jsonrpc2.HandlerWithError(self.handle)} } func (self *Server) handle(context contextpkg.Context, connection *jsonrpc2.Conn, request *jsonrpc2.Request) (any, error) {