]> git.eshelyaron.com Git - emacs.git/commitdiff
Support goto-{declaration, implementation, typedefinition}
authorFelicián Németh <felician.nemeth@gmail.com>
Thu, 3 Oct 2019 19:11:18 +0000 (21:11 +0200)
committerJoão Távora <joaotavora@gmail.com>
Fri, 11 Oct 2019 10:11:47 +0000 (11:11 +0100)
Closes https://github.com/joaotavora/eglot/issues/302.

* eglot.el (eglot--xref-definitions-method): New variable.
(xref-backend-definitions): Use it.
(eglot-find-declaration, eglot-find-implementation,
eglot-find-typeDefinition): New functions.

* README.md (Language features): Add new capabilities.

* eglot.el (eglot-client-capabilities): Add new capabilities.
(eglot-ignored-server-capabilites): Add new capability.

lisp/progmodes/eglot.el

index 1dc57113984d2d9cd51bad35a24bb5a433c72258..e3ead963610e1f927558796d5bd6577ec26e7aea 100644 (file)
@@ -491,6 +491,9 @@ treated as in `eglot-dbind'."
                                          (:labelOffsetSupport t)))
              :references         `(:dynamicRegistration :json-false)
              :definition         `(:dynamicRegistration :json-false)
+             :declaration        `(:dynamicRegistration :json-false)
+             :implementation     `(:dynamicRegistration :json-false)
+             :typeDefinition     `(:dynamicRegistration :json-false)
              :documentSymbol     (list
                                   :dynamicRegistration :json-false
                                   :symbolKind `(:valueSet
@@ -1090,6 +1093,7 @@ under cursor."
            (const :tag "Go to definition" :definitionProvider)
            (const :tag "Go to type definition" :typeDefinitionProvider)
            (const :tag "Go to implementation" :implementationProvider)
+           (const :tag "Go to declaration" :implementationProvider)
            (const :tag "Find references" :referencesProvider)
            (const :tag "Highlight symbols automatically" :documentHighlightProvider)
            (const :tag "List symbols in buffer" :documentSymbolProvider)
@@ -1796,6 +1800,36 @@ Try to visit the target file for a richer summary line."
                 :textDocumentPositionParams
                 (eglot--TextDocumentPositionParams))))
 
+(defvar eglot--xref-definitions-method :textDocument/definition
+  "The LSP method to map xref-find-definitions call.")
+
+(defun eglot-find-declaration ()
+  "Find the declaration for the identifier at point.
+See `xref-find-definitions' and `xref-prompt-for-identifier'."
+  (interactive)
+  (eglot--find-location 'declaration))
+
+(defun eglot-find-implementation ()
+  "Find the implementation for the identifier at point.
+See `xref-find-definitions' and `xref-prompt-for-identifier'."
+  (interactive)
+  (eglot--find-location 'implementation))
+
+(defun eglot-find-typeDefinition ()
+  "Find the type definition for the identifier at point.
+See `xref-find-definitions' and `xref-prompt-for-identifier'."
+  (interactive)
+  (eglot--find-location 'typeDefinition))
+
+(defun eglot--find-location (kind)
+  (let* ((method-name (symbol-name kind))
+         (method (intern (concat ":textDocument/" method-name)))
+         (capability (intern (concat ":" method-name "Provider"))))
+    (if (eglot--server-capable capability)
+        (let ((eglot--xref-definitions-method method))
+          (call-interactively #'xref-find-definitions))
+      (eglot--error "Server is not a %sProvider" method-name))))
+
 (cl-defmethod xref-backend-definitions ((_backend (eql eglot)) identifier)
   (let* ((rich-identifier
           (car (member identifier eglot--xref-known-symbols)))
@@ -1803,7 +1837,7 @@ Try to visit the target file for a richer summary line."
           (if rich-identifier
               (get-text-property 0 :locations rich-identifier)
             (jsonrpc-request (eglot--current-server-or-lose)
-                             :textDocument/definition
+                             eglot--xref-definitions-method
                              (get-text-property
                               0 :textDocumentPositionParams identifier))))
          (locations