From 39c8be6eb760d45105650cb8c3198cd51cb3fdda Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sun, 5 Nov 2023 11:01:49 +0000 Subject: [PATCH] Eglot: use new xref-find-extra feature of Xref 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 | 53 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index eba66503bf7..ca2fae97bc5 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -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) -- 2.39.2