Eglot: fix jit-lock inlay hint bugs
One of the bugs was straightforward. The timer function of eglot--update-hints must set the correct buffer. The other is much more odd. When using Eglot on Emacs's own src/coding.c, the jit-lock code starts calling its jit-functions over and over again with the same sequence of arguments, like so: ====================================================================== 1 -> (eglot--update-hints 63551 65051) 1 <- eglot--update-hints: [nil 25592 52026 4 ====================================================================== 1 -> (eglot--update-hints 65051 66551) 1 <- eglot--update-hints: [nil 25592 52026 4 ====================================================================== 1 -> (eglot--update-hints-1 63551 66551) 1 <- eglot--update-hints-1: nil ====================================================================== 1 -> (eglot--update-hints 63551 65051) 1 <- eglot--update-hints: [nil 25592 52026 4 ====================================================================== 1 -> (eglot--update-hints 65051 66551) 1 <- eglot--update-hints: [nil 25592 52026 5 ====================================================================== 1 -> (eglot--update-hints-1 63551 66551) 1 <- eglot--update-hints-1: nil This continues forever at a very fast rate and saturates the LSP channel. At first I thought that it was because eglot--update-hints-1 is actually causing the buffer to be modified with overlays sometime in the future, but it is not so! It seems that merely calling (goto-char (eglot--lsp-position-to-point position)) (from the LSP request handler in eglot--update-hints-1) will cause this bug. * lisp/progmodes/eglot.el (eglot--update-hints): Fix bugs.
This commit is contained in:
parent
5db75ec7d3
commit
55d29c9bac
1 changed files with 25 additions and 6 deletions
|
@ -3492,12 +3492,15 @@ If NOERROR, return predicate, else erroring function."
|
|||
(defvar-local eglot--outstanding-inlay-hints-region (cons nil nil)
|
||||
"Jit-lock-calculated (FROM . TO) region with potentially outdated hints")
|
||||
|
||||
(defvar-local eglot--outstanding-inlay-hints-last-region nil)
|
||||
|
||||
(defvar-local eglot--outstanding-inlay-regions-timer nil
|
||||
"Helper timer for `eglot--update-hints'")
|
||||
|
||||
(defun eglot--update-hints (from to)
|
||||
"Jit-lock function for Eglot inlay hints."
|
||||
(cl-symbol-macrolet ((region eglot--outstanding-inlay-hints-region)
|
||||
(last-region eglot--outstanding-inlay-hints-last-region)
|
||||
(timer eglot--outstanding-inlay-regions-timer))
|
||||
(setcar region (min (or (car region) (point-max)) from))
|
||||
(setcdr region (max (or (cdr region) (point-min)) to))
|
||||
|
@ -3513,12 +3516,28 @@ If NOERROR, return predicate, else erroring function."
|
|||
;; not introducing any more delay over jit-lock's timers.
|
||||
(when (= jit-lock-context-unfontify-pos (point-max))
|
||||
(if timer (cancel-timer timer))
|
||||
(setq timer (run-at-time
|
||||
0 nil
|
||||
(lambda ()
|
||||
(eglot--update-hints-1 (max (car region) (point-min))
|
||||
(min (cdr region) (point-max)))
|
||||
(setq region (cons nil nil) timer nil)))))))
|
||||
(let ((buf (current-buffer)))
|
||||
(setq timer (run-at-time
|
||||
0 nil
|
||||
(lambda ()
|
||||
(eglot--when-live-buffer buf
|
||||
;; HACK: In some pathological situations
|
||||
;; (Emacs's own coding.c, for example),
|
||||
;; jit-lock is calling `eglot--update-hints'
|
||||
;; repeatedly with same sequence of
|
||||
;; arguments, which leads to
|
||||
;; `eglot--update-hints-1' being called with
|
||||
;; the same region repeatedly. This happens
|
||||
;; even if the hint-painting code does
|
||||
;; nothing else other than widen, narrow,
|
||||
;; move point then restore these things.
|
||||
;; Possible Emacs bug, but this fixes it.
|
||||
(unless (equal last-region region)
|
||||
(eglot--update-hints-1 (max (car region) (point-min))
|
||||
(min (cdr region) (point-max)))
|
||||
(setq last-region region))
|
||||
(setq region (cons nil nil)
|
||||
timer nil)))))))))
|
||||
|
||||
(defun eglot--update-hints-1 (from to)
|
||||
"Do most work for `eglot--update-hints', including LSP request."
|
||||
|
|
Loading…
Add table
Reference in a new issue