1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

Eglot: adjust semtok delta request debouncing

When a response to a semtok request is received, it's important
to remember which regions to flush.  Font-lock logic will then
do its magic and coalesce those regions into one before invoking
eglot--semtok-font-lock, and eglot--semtok-font-lock-1 will have
up-to-date data to work with.

* lisp/progmodes/eglot.el (eglot--semtok-request): Rework.
(eglot--semtok-inflight): Adjust docstring.
This commit is contained in:
João Távora 2025-11-12 20:47:34 +00:00
parent c34e32e4b0
commit b55e6b77eb

View file

@ -4626,7 +4626,7 @@ If NOERROR, return predicate, else erroring function."
"Cache of the last response from the server.")
(defvar-local eglot--semtok-inflight nil
"Non nil if there's an inflight full-buffer delta semtok request.")
"List of (BEG . END) regions of inflight semtok requests.")
(defsubst eglot--semtok-apply-delta-edits (old-data edits)
"Apply EDITS obtained from full/delta request to OLD-DATA."
@ -4656,7 +4656,6 @@ If NOERROR, return predicate, else erroring function."
;; "data: "
;; (length (cl-getf response :data)))
(eglot--when-live-buffer buf
(setq eglot--semtok-inflight nil)
;; A user edit may have come in while the request
;; was inflight, changing the state of the buffer...
(when (eq id eglot--versioned-identifier)
@ -4669,25 +4668,27 @@ If NOERROR, return predicate, else erroring function."
;; this response is out-of-date,
;; `eglot--semtok-font-lock' should just trigger
;; another request.
(font-lock-flush beg end)))
(cl-loop for (b . e) in eglot--semtok-inflight
do (font-lock-flush b e))
;; (trace-values "Flushed" (length eglot--semtok-inflight)
;; "regions")
(setq eglot--semtok-inflight nil)))
:hint method))
(cache-get (&rest path)
(let ((x eglot--semtok-cache))
(dolist (op path x) (setq x (if (natnump op) (aref x op)
(plist-get x op)))))))
(push (cons beg end) eglot--semtok-inflight)
(cond
((and (eglot-server-capable :semanticTokensProvider :full :delta)
(cache-get :response :data)
(not (eq :textDocument/semanticTokens/range (cache-get :method))))
;; JT@2025-11-12: many back-to-back calls for
;; `eglot--semtok-request' and small regions occur even on trivial
;; fast edits. Even though it's cheap and harmless to send many
;; delta rquests, it's nicer to just send just one. The
;; debouncing from jsonrpc-async-request (which see) almost
;; suffices, but sometimes two requests creep in. Use this
;; simple flag to avoid.
(when eglot--semtok-inflight (cl-return-from eglot--semtok-request))
(setq eglot--semtok-inflight t)
;; `eglot--semtok-request' and small regions occur even on
;; trivial/fast edits. Even though it's fairly cheap to send
;; multiple delta requests, it's nicer to just send just one.
(when (cdr eglot--semtok-inflight)
(cl-return-from eglot--semtok-request))
(req :textDocument/semanticTokens/full/delta (point-min) (point-max)
(list :textDocument (eglot--TextDocumentIdentifier)
:previousResultId (cache-get :response :resultId))