(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))
;; 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."