]> git.eshelyaron.com Git - emacs.git/commitdiff
Manage cross-referenced files outside project in same server
authorMichael Livshin <mlivshin@gmail.com>
Sat, 15 Dec 2018 01:17:32 +0000 (01:17 +0000)
committerJoão Távora <joaotavora@gmail.com>
Sun, 16 May 2021 10:44:26 +0000 (11:44 +0100)
Close https://github.com/joaotavora/eglot/issues/686, Close https://github.com/joaotavora/eglot/issues/695.

Co-authored-by: João Távora <joaotavora@gmail.com>
* eglot.el (eglot-extend-to-xref): new defcustom, default to
nil.
(eglot--servers-by-xrefed-file): new hash table, mapping file names
to servers.
(eglot--managed-mode): use eglot-current-server, instead of
eglot--cached-server directly.
(eglot--current-server-or-lose): ditto.
(eglot--maybe-activate-editing-mode): ditto.
(eglot-current-server): move all cached-server update logic here -- if
eglot--cached-server is nil, try to find it using current project or
(optionally) xref location.
(eglot--xref-make-match): record the xref location.

* README.md (Customization): Mention new defcustom.

* NEWS.md: Mention new feature

GitHub-reference: fix https://github.com/joaotavora/eglot/issues/76

lisp/progmodes/eglot.el

index f17e795bfb5056a9b0c560663b5947c4a62477e7..db468d83c14a58d4f8430d228b29f8bc1e8af0ff 100644 (file)
@@ -237,6 +237,10 @@ let the buffer grow forever."
   :type '(choice (const :tag "Don't show confirmation prompt" nil)
                  (symbol :tag "Show confirmation prompt" 'confirm)))
 
+(defcustom eglot-extend-to-xref nil
+  "If non-nil, activate Eglot in cross-referenced non-project files."
+  :type 'boolean)
+
 ;; Customizable via `completion-category-overrides'.
 (when (assoc 'flex completion-styles-alist)
   (add-to-list 'completion-category-defaults '(eglot (styles flex basic))))
@@ -832,6 +836,9 @@ be guessed."
 (put 'eglot-lsp-context 'variable-documentation
      "Dynamically non-nil when searching for projects in LSP context.")
 
+(defvar eglot--servers-by-xrefed-file
+  (make-hash-table :test 'equal :weakness 'value))
+
 (defun eglot--current-project ()
   "Return a project object for Eglot's LSP purposes.
 This relies on `project-current' and thus on
@@ -1495,7 +1502,7 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
                     #'eglot-imenu))
     (flymake-mode 1)
     (eldoc-mode 1)
-    (cl-pushnew (current-buffer) (eglot--managed-buffers eglot--cached-server)))
+    (cl-pushnew (current-buffer) (eglot--managed-buffers (eglot-current-server))))
    (t
     (remove-hook 'after-change-functions 'eglot--after-change t)
     (remove-hook 'before-change-functions 'eglot--before-change t)
@@ -1533,11 +1540,19 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
 
 (defun eglot-current-server ()
   "Return logical EGLOT server for current buffer, nil if none."
-  eglot--cached-server)
+  (setq eglot--cached-server
+        (or eglot--cached-server
+            (cl-find major-mode
+                     (gethash (eglot--current-project) eglot--servers-by-project)
+                     :key #'eglot--major-mode)
+            (and eglot-extend-to-xref
+                 buffer-file-name
+                 (gethash (expand-file-name buffer-file-name) 
+                          eglot--servers-by-xrefed-file)))))
 
 (defun eglot--current-server-or-lose ()
   "Return current logical EGLOT server connection or error."
-  (or eglot--cached-server
+  (or (eglot-current-server)
       (jsonrpc-error "No current JSON-RPC connection")))
 
 (defvar-local eglot--unreported-diagnostics nil
@@ -1555,14 +1570,7 @@ If it is activated, also signal textDocument/didOpen."
   (unless eglot--managed-mode
     ;; Called when `revert-buffer-in-progress-p' is t but
     ;; `revert-buffer-preserve-modes' is nil.
-    (when (and buffer-file-name
-               (or
-                eglot--cached-server
-                (setq eglot--cached-server
-                      (cl-find major-mode
-                               (gethash (eglot--current-project)
-                                        eglot--servers-by-project)
-                               :key #'eglot--major-mode))))
+    (when (and buffer-file-name (eglot-current-server))
       (setq eglot--unreported-diagnostics `(:just-opened . nil))
       (eglot--managed-mode)
       (eglot--signal-textDocument/didOpen))))
@@ -2101,6 +2109,8 @@ Try to visit the target file for a richer summary line."
                  (start-pos (cl-getf start :character))
                  (end-pos (cl-getf (cl-getf range :end) :character)))
             (list name line start-pos (- end-pos start-pos)))))))
+    (setf (gethash (expand-file-name file) eglot--servers-by-xrefed-file)
+          (eglot--current-server-or-lose))
     (xref-make-match summary (xref-make-file-location file line column) length)))
 
 (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot)))