]> git.eshelyaron.com Git - emacs.git/commitdiff
Eglot: use new xref-find-extra feature of Xref feature/xref-find-extra
authorJoão Távora <joaotavora@gmail.com>
Sun, 5 Nov 2023 11:01:49 +0000 (11:01 +0000)
committerJoão Távora <joaotavora@gmail.com>
Mon, 6 Nov 2023 00:01:56 +0000 (00:01 +0000)
This removes the need of some Eglot hacks to implement the commands
eglot-find-declaration, eglot-find-implementation, and
eglot-find-typeDefinition.

It also allows the new command xref-find-extra to find different kinds
of definitions.

* lisp/progmodes/eglot.el (eglot--xref-kinds-alist): New variable.
(eglot-find-declaration, eglot-find-implementation)
(eglot-find-typeDefinition): Use xref-find-extra.
(xref-backend-definitions): Minor tweak.
(xref-backend-references): Don't use eglot--lsp-xref-refs.
(eglot--lsp-xref-helper): Delete this helper.
(eglot--lsp-xref-refs): Delete this variable.
(xref-backend-extra-kinds, xref-backend-extra-defs): New implementation.

lisp/progmodes/eglot.el

index eba66503bf7d5b5b72a8e860c17de4af47017385..ca2fae97bc5971874922ddcc696bad53dc267d82 100644 (file)
@@ -2905,9 +2905,6 @@ If BUFFER, switch to it before."
                        eglot--workspace-symbols-cache))))
     (if attempt (car attempt) "LSP identifier at point")))
 
-(defvar eglot--lsp-xref-refs nil
-  "`xref' objects for overriding `xref-backend-references''s.")
-
 (cl-defun eglot--lsp-xrefs-for-method (method &key extra-params capability)
   "Make `xref''s for METHOD, EXTRA-PARAMS, check CAPABILITY."
   (eglot-server-capable-or-lose
@@ -2933,45 +2930,44 @@ If BUFFER, switch to it before."
                                                uri range))))))
        (if (vectorp response) response (and response (list response)))))))
 
-(cl-defun eglot--lsp-xref-helper (method &key extra-params capability)
-  "Helper for `eglot-find-declaration' & friends."
-  (let ((eglot--lsp-xref-refs (eglot--lsp-xrefs-for-method
-                               method
-                               :extra-params extra-params
-                               :capability capability)))
-    (if eglot--lsp-xref-refs
-        (xref-find-references "LSP identifier at point.")
-      (eglot--message "%s returned no references" method))))
+(defvar eglot--xref-kinds-alist
+  '((eglot--xref-declaration :declarationProvider :textDocument/declaration)
+    (eglot--xref-definition :definitionProvider :textDocument/definition)
+    (eglot--xref-implementation :implementationProvider :textDocument/implementation)
+    (eglot--xref-type-definition :typeDefinitionProvider :textDocument/typeDefinition)
+    (eglot--xref-references :referencesProvider :textDocument/references
+                            `(:context (:includeDeclaration t))))
+  "Alist of (KIND CAPABILITY METHOD EXTRA-PARAMS)")
 
 (defun eglot-find-declaration ()
   "Find declaration for SYM, the identifier at point."
   (interactive)
-  (eglot--lsp-xref-helper :textDocument/declaration))
+  (xref-find-extra "LSP identifier at point" 'eglot--xref-declaration))
 
 (defun eglot-find-implementation ()
   "Find implementation for SYM, the identifier at point."
   (interactive)
-  (eglot--lsp-xref-helper :textDocument/implementation))
+  (xref-find-extra "LSP identifier at point" 'eglot--xref-implementation))
 
 (defun eglot-find-typeDefinition ()
   "Find type definition for SYM, the identifier at point."
   (interactive)
-  (eglot--lsp-xref-helper :textDocument/typeDefinition))
+  (xref-find-extra "LSP identifier at point" 'eglot--xref-type-definition))
 
-(cl-defmethod xref-backend-definitions ((_backend (eql eglot)) id)
-  (let ((probe (eglot--recover-workspace-symbol-meta id)))
+(cl-defmethod xref-backend-definitions ((_backend (eql eglot)) identifier)
+  (let ((probe (eglot--recover-workspace-symbol-meta identifier)))
     (if probe
         (eglot--dbind ((WorkspaceSymbol) name location)
             (get-text-property 0 'eglot--lsp-workspaceSymbol probe)
           (eglot--dbind ((Location) uri range) location
             (list (eglot--xref-make-match name uri range))))
-      (eglot--lsp-xrefs-for-method :textDocument/definition))))
+      (eglot--lsp-xrefs-for-method :textDocument/definition
+                                   :capability :definitionProvider))))
 
 (cl-defmethod xref-backend-references ((_backend (eql eglot)) _identifier)
-  (or
-   eglot--lsp-xref-refs
-   (eglot--lsp-xrefs-for-method
-    :textDocument/references :extra-params `(:context (:includeDeclaration t)))))
+  (eglot--lsp-xrefs-for-method :textDocument/references
+                               :capability :referencesProvider
+                               :extra-params `(:context (:includeDeclaration t))))
 
 (cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern)
   (when (eglot-server-capable :workspaceSymbolProvider)
@@ -2984,6 +2980,19 @@ If BUFFER, switch to it before."
                        :workspace/symbol
                        `(:query ,pattern))))))
 
+(cl-defmethod xref-backend-extra-kinds ((_backend (eql eglot)) _identifier)
+  (cl-loop for (kind capability _method _extra) in eglot--xref-kinds-alist
+           when (eglot-server-capable capability) collect kind))
+
+(cl-defmethod xref-backend-extra-defs ((_backend (eql eglot)) identifier kind)
+  (cond ((eq kind 'eglot--xref-definition)
+         (xref-backend-definitions 'eglot identifier))
+        (t
+         (pcase-let ((`(,_ ,capability ,method ,extra-params)
+                      (assoc (intern kind) eglot--xref-kinds-alist)))
+           (eglot--lsp-xrefs-for-method method :capability capability
+                                        :extra-params extra-params)))))
+
 (defun eglot-format-buffer ()
   "Format contents of current buffer."
   (interactive)