Setting this variable to true causes Eglot to send special
cancellation notification for certain stale client request.
This may help some LSP servers avoid doing costly but ultimately useless
work on behalf of the client, improving overall performance.
Request cancellation is described in
https://microsoft.github.io/language-server-protocol/
specifications/lsp/3.17/specification/#cancelRequest
* lisp/jsonrpc.el (jsonrpc-request): Accept function as value for
CANCEL-ON-INPUT.
* lisp/progmodes/eglot.el (eglot--request): Rework.
* doc/misc/eglot.texi (Customizing Eglot): Mention
eglot-advertise-cancellation.
(cherry picked from commit
7f0ef9655cdc28c3b8055e32c9e84ea57339b139)
from the language server to be handled by Emacs's progress reporting
facilities. If the value is the symbol @code{messages} the message
buffer is used, else the progress is reported in the mode line.
+
+@cindex request cancellation
+@item eglot-advertise-cancellation
+Setting this variable to true causes Eglot to send special cancellation
+notification for certain stale client request. This may help some LSP
+servers avoid doing costly but ultimately useless work on behalf of the
+client, improving overall performance.
@end vtable
@node Other Variables
\f
* Changes in upcoming Eglot
+** New 'eglot-advertise-cancellation' variable
+
+Tweaking this variable may help some LSP servers avoid doing costly but
+ultimately useless work on behalf of the client, improving overall
+performance.
+
\f
* Changes in Eglot 1.18 (20/1/2025)
DEFERRED and TIMEOUT as in `jsonrpc-async-request', which see.
-If CANCEL-ON-INPUT is non-nil and the user inputs something while
-the function is waiting, then it exits immediately, returning
-CANCEL-ON-INPUT-RETVAL. Any future replies (normal or error) are
-ignored."
+If CANCEL-ON-INPUT is non-nil and the user inputs something while the
+function is waiting, then any future replies to the request by the
+remote endpoint (normal or error) are ignored and the function exits
+returning CANCEL-ON-INPUT-RETVAL. If CANCEL-ON-INPUT is a function, it
+is invoked with one argument, an integer identifying the cancelled
+request as specified in the JSONRPC 2.0 spec."
(let* ((tag (cl-gensym "jsonrpc-request-catch-tag")) id-and-timer
canceled
(throw-on-input nil)
(unwind-protect
(let ((inhibit-quit t)) (while (sit-for 30)))
(setq canceled t))
+ (when (functionp cancel-on-input)
+ (funcall cancel-on-input (car id-and-timer)))
`(canceled ,cancel-on-input-retval))
(t (while t (accept-process-output nil 30)))))
;; In normal operation, continuations for error/success is
(const :tag "Execute custom commands" :executeCommandProvider)
(const :tag "Inlay hints" :inlayHintProvider)))
+(defcustom eglot-advertise-cancellation nil
+ "If non-nil, Eglot attemps to inform server of cancelled requests.
+This is done by sending an additional '$/cancelRequest' notification
+every time Eglot decides to forget a request. The effect of this
+notification is implementation defined, and is only useful for some
+servers."
+ :type 'boolean)
+
(defvar eglot-withhold-process-id nil
"If non-nil, Eglot will not send the Emacs process id to the language server.
This can be useful when using docker to run a language server.")
(unless immediate (eglot--signal-textDocument/didChange))
(jsonrpc-request server method params
:timeout timeout
- :cancel-on-input cancel-on-input
+ :cancel-on-input
+ (cond ((and cancel-on-input
+ eglot-advertise-cancellation)
+ (lambda (id)
+ (jsonrpc-notify server '$/cancelRequest `(:id ,id))))
+ (cancel-on-input))
:cancel-on-input-retval cancel-on-input-retval))
\f