diff options
| author | João Távora | 2025-11-14 15:43:25 +0000 |
|---|---|---|
| committer | João Távora | 2025-11-14 15:45:37 +0000 |
| commit | f83c35788aedf3f60a112e34c656df554c46ef09 (patch) | |
| tree | 5c7b82ecbf54a31dd3ff7e02bbe72c347ec3d177 | |
| parent | d81bb68ed09821d9c9e771e7c1ce34b2bf212823 (diff) | |
| download | emacs-f83c35788aedf3f60a112e34c656df554c46ef09.tar.gz emacs-f83c35788aedf3f60a112e34c656df554c46ef09.zip | |
Eglot: invalidate local semtok cache at server's bidding
When the server sends workspace/semanticTokens/refresh, calling
font-lock-flush isn't enough. It will trigger a new
eglot--semtok-font-lock call, but we can't assume anything about
the validity of eglot--semtok-cache.
Clangd seems to send workspace/semanticTokens/refresh when
complicated enough changes happen in an LSP document. If the
buffer-local eglot--semtok-cache isn't flushed we'll likely
request a delta, and clangd may still supply it, but it won't
apply correctly to the outdated local state.
* lisp/progmodes/eglot.el (eglot--semtok-cache)
(eglot--semtok-inflight): Move up here.
(eglot-handle-request): Flush the eglot--semtok-cache.
| -rw-r--r-- | lisp/progmodes/eglot.el | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index f089745e817..d5a4ca096f3 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -4620,12 +4620,20 @@ If NOERROR, return predicate, else erroring function." | |||
| 4620 | semtok-cache) | 4620 | semtok-cache) |
| 4621 | probe)))) | 4621 | probe)))) |
| 4622 | 4622 | ||
| 4623 | (defvar-local eglot--semtok-cache nil | ||
| 4624 | "Cache of the last response from the server.") | ||
| 4625 | |||
| 4626 | (defvar-local eglot--semtok-inflight nil | ||
| 4627 | "List of (BEG . END) regions of inflight semtok requests.") | ||
| 4628 | |||
| 4623 | (cl-defmethod eglot-handle-request | 4629 | (cl-defmethod eglot-handle-request |
| 4624 | (server (_method (eql workspace/semanticTokens/refresh))) | 4630 | (server (_method (eql workspace/semanticTokens/refresh))) |
| 4625 | "Handle a semanticTokens/refresh request from SERVER." | 4631 | "Handle a semanticTokens/refresh request from SERVER." |
| 4626 | (dolist (buffer (eglot--managed-buffers server)) | 4632 | (dolist (buffer (eglot--managed-buffers server)) |
| 4627 | (eglot--when-live-buffer buffer | 4633 | (eglot--when-live-buffer buffer |
| 4628 | (unless (zerop eglot--versioned-identifier) (font-lock-flush))))) | 4634 | (unless (zerop eglot--versioned-identifier) |
| 4635 | (setq eglot--semtok-cache nil) | ||
| 4636 | (font-lock-flush))))) | ||
| 4629 | 4637 | ||
| 4630 | (define-minor-mode eglot-semantic-tokens-mode | 4638 | (define-minor-mode eglot-semantic-tokens-mode |
| 4631 | "Minor mode for fontifying buffer with LSP server's semantic tokens." | 4639 | "Minor mode for fontifying buffer with LSP server's semantic tokens." |
| @@ -4639,12 +4647,6 @@ If NOERROR, return predicate, else erroring function." | |||
| 4639 | (font-lock-remove-keywords nil '((eglot--semtok-font-lock))) | 4647 | (font-lock-remove-keywords nil '((eglot--semtok-font-lock))) |
| 4640 | (font-lock-flush)))) | 4648 | (font-lock-flush)))) |
| 4641 | 4649 | ||
| 4642 | (defvar-local eglot--semtok-cache nil | ||
| 4643 | "Cache of the last response from the server.") | ||
| 4644 | |||
| 4645 | (defvar-local eglot--semtok-inflight nil | ||
| 4646 | "List of (BEG . END) regions of inflight semtok requests.") | ||
| 4647 | |||
| 4648 | (defsubst eglot--semtok-apply-delta-edits (old-data edits) | 4650 | (defsubst eglot--semtok-apply-delta-edits (old-data edits) |
| 4649 | "Apply EDITS obtained from full/delta request to OLD-DATA." | 4651 | "Apply EDITS obtained from full/delta request to OLD-DATA." |
| 4650 | (cl-loop | 4652 | (cl-loop |