emacs-31 83ec0fd8f33: Eglot: prevent showDocument disruption of sync requests (bug#81538)

João Távora <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: emacs-31
commit 83ec0fd8f33e36672032201862cbf500e0063733
Author: João Távora <[email protected]>
Commit: João Távora <[email protected]>

    Eglot: prevent showDocument disruption of sync requests (bug#81538)
    
    This couldn't be reproduced here, but seems nevertheless possible.  The
    previous (run-at-time 0...) technique for the window/showDocument
    handling never really avoided the fact that that timer could kick during
    the accept-process-output of jsonrpc-request, thus happening before the
    response to the original request.  Since the handling evolves a lot of
    output to send to the process, it could be interrupted by the 'throw'
    that's meant to exit abort 'accept-process-output' (and only that).
    
    This commit should ensure the sequence is always this one.
    
    a1. -> adals/ff-thingy sync client request
    b1.   <- window/showDocument server request
    b2.   -> window/showDocument client response (after scheduling 'c')
    a2. <- ada/ff-thingy server response
    c.  -> f-f-no-select, Eglot sends the large didOpen notification
    
    * lisp/progmodes/eglot.el (eglot-handle-request): Maybe use
    "post command" once trick.
---
 lisp/progmodes/eglot.el | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 1f4f6abbd91..e53d2a08159 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2962,19 +2962,22 @@ THINGS are either registrations or unregisterations (sic)."
     (cond
      ((eq external t) (browse-url uri))
      ((file-readable-p (setq filename (eglot-uri-to-path uri)))
-      ;; Use run-with-timer to avoid nested client requests like the
-      ;; "synchronous imenu" floated in bug#62116 presumably caused by
-      ;; which-func-mode.
-      (run-with-timer
-       0 nil
-       (lambda ()
-         (with-current-buffer (find-file-noselect filename)
-           (cond (takeFocus
-                  (pop-to-buffer (current-buffer))
-                  (select-frame-set-input-focus (selected-frame)))
-                 ((display-buffer (current-buffer))))
-           (when selection
-             (eglot--goto selection))))))
+      ;; Really ensure this runs when it is safe to run it.
+      ;; run-with-timer avoid nested client requests like the
+      ;; "synchronous imenu" floated in bug#62116, while the
+      ;; "post-command once" trick is for bug#81538.
+      (cl-labels ((findit ()
+                  (remove-hook 'post-command-hook #'findit)
+                  (with-current-buffer (find-file-noselect filename)
+                    (cond (takeFocus
+                           (pop-to-buffer (current-buffer))
+                           (select-frame-set-input-focus (selected-frame)))
+                          ((display-buffer (current-buffer))))
+                    (when selection
+                      (eglot--goto selection)))))
+                (if this-command
+                    (add-hook 'post-command-hook #'findit)
+                  (run-at-time 0 nil #'findit))))
      (t (setq success :json-false)))
     `(:success ,success)))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.