From c6da051706942b7606cb69232bb693cf4ec1ede2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 18 Apr 2024 03:55:17 -0500 Subject: [PATCH] Revert "Don't use file-truepath in Eglot (bug#70036)" This reverts commit 08c80c45ddea17df87fc768a39dff353ccc13d3b. It introduces bugs when a project contains symlinked files. The server will be informed of duplicate documents which are really the same and it frequently has no means to deduplicate such information. This leads to bugs such as excessive textDocument/references to a function. * lisp/progmodes/eglot.el (eglot-lsp-server): Revert change. (eglot-uri-to-path): Revert change. (eglot--on-shutdown): Revert change. (eglot--managed-mode): Revert change. (eglot-handle-notification textDocument/publishDiagnostics): Revert change. (cherry picked from commit 306feb7d967ecea9c916dd6e25b2e84a3f1c714e) --- lisp/progmodes/eglot.el | 42 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 24c5dd842bd..fbae5aadd78 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1058,8 +1058,8 @@ ACTION is an LSP object of either `CodeAction' or `Command' type." :documentation "Map (DIR -> (WATCH ID1 ID2...)) for `didChangeWatchedFiles'." :initform (make-hash-table :test #'equal) :accessor eglot--file-watches) (managed-buffers - :documentation "Map (PATH -> BUFFER) for buffers managed by server." - :initform (make-hash-table :test #'equal) + :initform nil + :documentation "List of buffers managed by server." :accessor eglot--managed-buffers) (saved-initargs :documentation "Saved initargs for reconnection purposes." @@ -1090,12 +1090,12 @@ ACTION is an LSP object of either `CodeAction' or `Command' type." (defun eglot-path-to-uri (path) "Convert PATH, a file name, to LSP URI string and return it." - (let ((expanded-path (expand-file-name path))) + (let ((truepath (file-truename path))) (if (and (url-type (url-generic-parse-url path)) ;; It might be MS Windows path which includes a drive ;; letter that looks like a URL scheme (bug#59338) (not (and (eq system-type 'windows-nt) - (file-name-absolute-p expanded-path)))) + (file-name-absolute-p truepath)))) ;; Path is already a URI, so forward it to the LSP server ;; untouched. The server should be able to handle it, since ;; it provided this URI to clients in the first place. @@ -1103,11 +1103,11 @@ ACTION is an LSP object of either `CodeAction' or `Command' type." (concat "file://" ;; Add a leading "/" for local MS Windows-style paths. (if (and (eq system-type 'windows-nt) - (not (file-remote-p expanded-path))) + (not (file-remote-p truepath))) "/") (url-hexify-string ;; Again watch out for trampy paths. - (directory-file-name (file-local-name expanded-path)) + (directory-file-name (file-local-name truepath)) eglot--uri-path-allowed-chars))))) (defun eglot-range-region (range &optional markers) @@ -1192,7 +1192,7 @@ PRESERVE-BUFFERS as in `eglot-shutdown', which see." (defun eglot--on-shutdown (server) "Called by jsonrpc.el when SERVER is already dead." ;; Turn off `eglot--managed-mode' where appropriate. - (dolist (buffer (map-values (eglot--managed-buffers server))) + (dolist (buffer (eglot--managed-buffers server)) (let (;; Avoid duplicate shutdowns (github#389) (eglot-autoshutdown nil)) (eglot--when-live-buffer buffer (eglot--managed-mode-off)))) @@ -2026,11 +2026,7 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (add-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function nil t) (eldoc-mode 1)) - - (let ((buffer (current-buffer))) - (puthash (expand-file-name (buffer-file-name buffer)) - buffer - (eglot--managed-buffers (eglot-current-server))))) + (cl-pushnew (current-buffer) (eglot--managed-buffers (eglot-current-server)))) (t (when eglot--track-changes (track-changes-unregister eglot--track-changes) @@ -2061,10 +2057,10 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (let ((server eglot--cached-server)) (setq eglot--cached-server nil) (when server - (remhash (expand-file-name (buffer-file-name (current-buffer))) - (eglot--managed-buffers server)) + (setf (eglot--managed-buffers server) + (delq (current-buffer) (eglot--managed-buffers server))) (when (and eglot-autoshutdown - (null (map-values (eglot--managed-buffers server)))) + (null (eglot--managed-buffers server))) (eglot-shutdown server))))))) (defun eglot--managed-mode-off () @@ -2387,7 +2383,7 @@ still unanswered LSP requests to the server\n"))) (remhash token (eglot--progress-reporters server)))))))))) (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) @@ -2398,7 +2394,7 @@ still unanswered LSP requests to the server\n"))) (mess (source code message) (concat source (and code (format " [%s]" code)) ": " message))) (if-let* ((path (expand-file-name (eglot-uri-to-path uri))) - (buffer (gethash path (eglot--managed-buffers server)))) + (buffer (find-buffer-visiting path))) (with-current-buffer buffer (cl-loop initially @@ -2909,7 +2905,7 @@ may be called multiple times (respecting the protocol of Try to visit the target file for a richer summary line." (pcase-let* ((file (eglot-uri-to-path uri)) - (visiting (or (gethash file (eglot--managed-buffers (eglot-current-server))) + (visiting (or (find-buffer-visiting file) (gethash uri eglot--temp-location-buffers))) (collect (lambda () (eglot--widening @@ -3609,14 +3605,13 @@ list ((FILENAME EDITS VERSION)...)." (with-current-buffer (get-buffer-create "*EGLOT proposed server changes*") (buffer-disable-undo (current-buffer)) (let ((inhibit-read-only t) - (target (current-buffer)) - (managed-buffers (eglot--managed-buffers (eglot-current-server)))) + (target (current-buffer))) (diff-mode) (erase-buffer) (pcase-dolist (`(,path ,edits ,_) prepared) (with-temp-buffer (let* ((diff (current-buffer)) - (existing-buf (gethash path (gethash path managed-buffers))) + (existing-buf (find-buffer-visiting path)) (existing-buf-label (prin1-to-string existing-buf))) (with-temp-buffer (if existing-buf @@ -3651,8 +3646,7 @@ edit proposed by the server." (eglot--dbind ((VersionedTextDocumentIdentifier) uri version) textDocument (list (eglot-uri-to-path uri) edits version))) - documentChanges)) - (managed-buffers (eglot--managed-buffers (eglot-current-server)))) + documentChanges))) (unless (and changes documentChanges) ;; We don't want double edits, and some servers send both ;; changes and documentChanges. This unless ensures that we @@ -3660,7 +3654,7 @@ edit proposed by the server." (cl-loop for (uri edits) on changes by #'cddr do (push (list (eglot-uri-to-path uri) edits) prepared))) (cl-flet ((notevery-visited-p () - (cl-notevery (lambda (p) (gethash p managed-buffers)) + (cl-notevery #'find-buffer-visiting (mapcar #'car prepared))) (accept-p () (y-or-n-p -- 2.39.5