]> git.eshelyaron.com Git - emacs.git/commitdiff
Make publishDiagnostics faster by using cached variable
authorTheodor Thornhill <theo@thornhill.no>
Fri, 19 Apr 2024 18:40:25 +0000 (20:40 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 20 Apr 2024 11:08:55 +0000 (14:08 +0300)
* lisp/progmodes/eglot.el (eglot--cached-tdi): Move variable.
(eglot-handle-notification): Expose 'server' and search through managed
buffers for a cached textDocumentIdentifier, which has a file-truename
resolved path.
* test/lisp/progmodes/eglot-tests.el (eglot-test-basic-symlink): Add
regression test for symlink behavior

(cherry picked from commit 49ef173b0287e17273e4476df16dca5f2196b11c)

lisp/progmodes/eglot.el
test/lisp/progmodes/eglot-tests.el

index 29a274fb338f2c6b3656541c5a77a15c823fb0c4..b6cdb2fd51ae0ad05990cf7d0b60e561aab5c1dd 100644 (file)
@@ -2382,8 +2382,11 @@ still unanswered LSP requests to the server\n")))
                         (lambda ()
                           (remhash token (eglot--progress-reporters server))))))))))
 
+(defvar-local eglot--cached-tdi nil
+  "A cached LSP TextDocumentIdentifier URI string.")
+
 (cl-defmethod eglot-handle-notification
-  (_server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics
+  (server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics
            &allow-other-keys) ; FIXME: doesn't respect `eglot-strict-mode'
   "Handle notification publishDiagnostics."
   (cl-flet ((eglot--diag-type (sev)
@@ -2392,9 +2395,18 @@ still unanswered LSP requests to the server\n")))
                     ((= sev 2)  'eglot-warning)
                     (t          'eglot-note)))
             (mess (source code message)
-              (concat source (and code (format " [%s]" code)) ": " message)))
+              (concat source (and code (format " [%s]" code)) ": " message))
+            (find-it (uri)
+              ;; Search the managed buffers for a buffer with the
+              ;; provided diagnostic from the server.  We do this to
+              ;; avoid calling `file-truename' too often, gaining an
+              ;; increase in performance.
+              (cl-loop for b in (eglot--managed-buffers server)
+                       when (with-current-buffer b
+                              (equal eglot--cached-tdi uri))
+                       return b)))
     (if-let* ((path (expand-file-name (eglot-uri-to-path uri)))
-              (buffer (find-buffer-visiting path)))
+              (buffer (find-it uri)))
         (with-current-buffer buffer
           (cl-loop
            initially
@@ -2519,9 +2531,6 @@ THINGS are either registrations or unregisterations (sic)."
      (t (setq success :json-false)))
     `(:success ,success)))
 
-(defvar-local eglot--cached-tdi nil
-  "A cached LSP TextDocumentIdentifier URI string.")
-
 (defun eglot--TextDocumentIdentifier ()
   "Compute TextDocumentIdentifier object for current buffer."
   `(:uri ,(or eglot--cached-tdi
index e501e24f5d21bb830688d689bf9c63ad512f2d1f..28579ccde5cb4246099128437e676f335391aba9 100644 (file)
@@ -436,6 +436,28 @@ directory hierarchy."
         (flymake-goto-next-error 1 '() t)
         (should (eq 'flymake-error (face-at-point)))))))
 
+(ert-deftest eglot-test-basic-symlink ()
+  "Test basic symlink support."
+  (skip-unless (executable-find "clangd"))
+  (eglot--with-fixture
+      `(("symlink-project" .
+         (("main.cpp" . "#include\"foo.h\"\nint main() { return foo(); }")
+          ("foo.h" . "int foo();"))))
+    (with-current-buffer
+        (find-file-noselect "symlink-project/main.cpp")
+      (make-symbolic-link "main.cpp" "mainlink.cpp")
+      (eglot--tests-connect)
+      (find-file-noselect "mainlink.cpp")
+      (with-current-buffer
+          (find-file-noselect "foo.h")
+        (goto-char 5)
+        (xref-find-references "foo")
+        (with-current-buffer (get-buffer "*xref*")
+          (end-of-buffer)
+          ;; Expect the xref buffer to not contain duplicate references to
+          ;; main.c and mainlink.c.  If it did total lines would be 7.
+          (should (= (line-number-at-pos (point)) 5)))))))
+
 (ert-deftest eglot-test-diagnostic-tags-unnecessary-code ()
   "Test rendering of diagnostics tagged \"unnecessary\"."
   (skip-unless (executable-find "clangd"))