emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/eglot 1ac06d0 10/10: Fix #76: manage cross-referenced f


From: Stefan Monnier
Subject: [elpa] externals/eglot 1ac06d0 10/10: Fix #76: manage cross-referenced files outside project in same server
Date: Wed, 19 May 2021 21:52:14 -0400 (EDT)

branch: externals/eglot
commit 1ac06d0bcc247fb19df6eceb57e2ea3d534806ec
Author: Michael Livshin <repo@cmm.kakpryg.net>
Commit: João Távora <joaotavora@gmail.com>

    Fix #76: manage cross-referenced files outside project in same server
    
    Close #686, Close #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
---
 NEWS.md   | 10 ++++++++++
 README.md |  6 ++++++
 eglot.el  | 32 +++++++++++++++++++++-----------
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index d060ad4..03a22bc 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -7,6 +7,13 @@ Thanks to Brian Cully for the minimalist approach.
 (also thanks to Felipe Lema who conducted many early experiments in
 [#463][github#463])
 
+##### Manage cross-referenced files outside project ([#76][github#76], 
([#686][github#686], ([#695][github#695])
+
+This is activated by a new customization option
+`eglot-extend-to-xref`, which defaults to nil.
+
+Thanks to Michael Livshin for the investigation an elegant solution.
+
 ##### Code action shortcuts ([#411][github#411])
 
 `M-x eglot-code-actions` accepts an optional `action-kind` argument,
@@ -214,6 +221,7 @@ and now said bunch of references-->
 [github#68]: https://github.com/joaotavora/eglot/issues/68
 [github#73]: https://github.com/joaotavora/eglot/issues/73
 [github#74]: https://github.com/joaotavora/eglot/issues/74
+[github#76]: https://github.com/joaotavora/eglot/issues/76
 [github#80]: https://github.com/joaotavora/eglot/issues/80
 [github#81]: https://github.com/joaotavora/eglot/issues/81
 [github#82]: https://github.com/joaotavora/eglot/issues/82
@@ -263,3 +271,5 @@ and now said bunch of references-->
 [github#494]: https://github.com/joaotavora/eglot/issues/494
 [github#637]: https://github.com/joaotavora/eglot/issues/637
 [github#643]: https://github.com/joaotavora/eglot/issues/643
+[github#686]: https://github.com/joaotavora/eglot/issues/686
+[github#695]: https://github.com/joaotavora/eglot/issues/695
diff --git a/README.md b/README.md
index 0ad6d46..302c7f6 100644
--- a/README.md
+++ b/README.md
@@ -319,6 +319,12 @@ lisp:
 - `eglot-stay-out-of`: List of Emacs features that Eglot shouldn't
   automatically try to manage on users' behalf.  Useful when you need
   non-LSP Flymake or Company backends.  See docstring for examples.
+  
+- `eglot-extend-to-xref`: If non-nil and `xref-find-definitions` lands
+  you in a file outside your project -- like a system-installed
+  library or header file -- transiently consider it managed by the
+  same LSP server.  That file is still outside your project
+  (i.e. `project-find-file` won't find it).
 
 # How does Eglot work?
 
diff --git a/eglot.el b/eglot.el
index f17e795..db468d8 100644
--- a/eglot.el
+++ b/eglot.el
@@ -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)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]