diff options
| author | Theodor Thornhill | 2024-04-19 20:40:25 +0200 |
|---|---|---|
| committer | Theodor Thornhill | 2024-04-19 22:21:38 +0200 |
| commit | 49ef173b0287e17273e4476df16dca5f2196b11c (patch) | |
| tree | 965fe6ee54b2cc69684354485ee19d30c74e2e09 | |
| parent | 82775f21413681b09c888527b5d2fb15354f0793 (diff) | |
| download | emacs-49ef173b0287e17273e4476df16dca5f2196b11c.tar.gz emacs-49ef173b0287e17273e4476df16dca5f2196b11c.zip | |
Make publishDiagnostics faster by using cached variable
* 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
| -rw-r--r-- | lisp/progmodes/eglot.el | 21 | ||||
| -rw-r--r-- | test/lisp/progmodes/eglot-tests.el | 22 |
2 files changed, 37 insertions, 6 deletions
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index d8eb1f1ee83..b78916e7f1d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -2381,8 +2381,11 @@ still unanswered LSP requests to the server\n"))) | |||
| 2381 | (lambda () | 2381 | (lambda () |
| 2382 | (remhash token (eglot--progress-reporters server)))))))))) | 2382 | (remhash token (eglot--progress-reporters server)))))))))) |
| 2383 | 2383 | ||
| 2384 | (defvar-local eglot--cached-tdi nil | ||
| 2385 | "A cached LSP TextDocumentIdentifier URI string.") | ||
| 2386 | |||
| 2384 | (cl-defmethod eglot-handle-notification | 2387 | (cl-defmethod eglot-handle-notification |
| 2385 | (_server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics | 2388 | (server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics |
| 2386 | &allow-other-keys) ; FIXME: doesn't respect `eglot-strict-mode' | 2389 | &allow-other-keys) ; FIXME: doesn't respect `eglot-strict-mode' |
| 2387 | "Handle notification publishDiagnostics." | 2390 | "Handle notification publishDiagnostics." |
| 2388 | (cl-flet ((eglot--diag-type (sev) | 2391 | (cl-flet ((eglot--diag-type (sev) |
| @@ -2391,9 +2394,18 @@ still unanswered LSP requests to the server\n"))) | |||
| 2391 | ((= sev 2) 'eglot-warning) | 2394 | ((= sev 2) 'eglot-warning) |
| 2392 | (t 'eglot-note))) | 2395 | (t 'eglot-note))) |
| 2393 | (mess (source code message) | 2396 | (mess (source code message) |
| 2394 | (concat source (and code (format " [%s]" code)) ": " message))) | 2397 | (concat source (and code (format " [%s]" code)) ": " message)) |
| 2398 | (find-it (uri) | ||
| 2399 | ;; Search the managed buffers for a buffer with the | ||
| 2400 | ;; provided diagnostic from the server. We do this to | ||
| 2401 | ;; avoid calling `file-truename' too often, gaining an | ||
| 2402 | ;; increase in performance. | ||
| 2403 | (cl-loop for b in (eglot--managed-buffers server) | ||
| 2404 | when (with-current-buffer b | ||
| 2405 | (equal eglot--cached-tdi uri)) | ||
| 2406 | return b))) | ||
| 2395 | (if-let* ((path (expand-file-name (eglot-uri-to-path uri))) | 2407 | (if-let* ((path (expand-file-name (eglot-uri-to-path uri))) |
| 2396 | (buffer (find-buffer-visiting path))) | 2408 | (buffer (find-it uri))) |
| 2397 | (with-current-buffer buffer | 2409 | (with-current-buffer buffer |
| 2398 | (cl-loop | 2410 | (cl-loop |
| 2399 | initially | 2411 | initially |
| @@ -2518,9 +2530,6 @@ THINGS are either registrations or unregisterations (sic)." | |||
| 2518 | (t (setq success :json-false))) | 2530 | (t (setq success :json-false))) |
| 2519 | `(:success ,success))) | 2531 | `(:success ,success))) |
| 2520 | 2532 | ||
| 2521 | (defvar-local eglot--cached-tdi nil | ||
| 2522 | "A cached LSP TextDocumentIdentifier URI string.") | ||
| 2523 | |||
| 2524 | (defun eglot--TextDocumentIdentifier () | 2533 | (defun eglot--TextDocumentIdentifier () |
| 2525 | "Compute TextDocumentIdentifier object for current buffer." | 2534 | "Compute TextDocumentIdentifier object for current buffer." |
| 2526 | `(:uri ,(or eglot--cached-tdi | 2535 | `(:uri ,(or eglot--cached-tdi |
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index e501e24f5d2..28579ccde5c 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el | |||
| @@ -436,6 +436,28 @@ directory hierarchy." | |||
| 436 | (flymake-goto-next-error 1 '() t) | 436 | (flymake-goto-next-error 1 '() t) |
| 437 | (should (eq 'flymake-error (face-at-point))))))) | 437 | (should (eq 'flymake-error (face-at-point))))))) |
| 438 | 438 | ||
| 439 | (ert-deftest eglot-test-basic-symlink () | ||
| 440 | "Test basic symlink support." | ||
| 441 | (skip-unless (executable-find "clangd")) | ||
| 442 | (eglot--with-fixture | ||
| 443 | `(("symlink-project" . | ||
| 444 | (("main.cpp" . "#include\"foo.h\"\nint main() { return foo(); }") | ||
| 445 | ("foo.h" . "int foo();")))) | ||
| 446 | (with-current-buffer | ||
| 447 | (find-file-noselect "symlink-project/main.cpp") | ||
| 448 | (make-symbolic-link "main.cpp" "mainlink.cpp") | ||
| 449 | (eglot--tests-connect) | ||
| 450 | (find-file-noselect "mainlink.cpp") | ||
| 451 | (with-current-buffer | ||
| 452 | (find-file-noselect "foo.h") | ||
| 453 | (goto-char 5) | ||
| 454 | (xref-find-references "foo") | ||
| 455 | (with-current-buffer (get-buffer "*xref*") | ||
| 456 | (end-of-buffer) | ||
| 457 | ;; Expect the xref buffer to not contain duplicate references to | ||
| 458 | ;; main.c and mainlink.c. If it did total lines would be 7. | ||
| 459 | (should (= (line-number-at-pos (point)) 5))))))) | ||
| 460 | |||
| 439 | (ert-deftest eglot-test-diagnostic-tags-unnecessary-code () | 461 | (ert-deftest eglot-test-diagnostic-tags-unnecessary-code () |
| 440 | "Test rendering of diagnostics tagged \"unnecessary\"." | 462 | "Test rendering of diagnostics tagged \"unnecessary\"." |
| 441 | (skip-unless (executable-find "clangd")) | 463 | (skip-unless (executable-find "clangd")) |