[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot 193c57d 075/139: Half-decent xref support
From: |
João Távora |
Subject: |
[elpa] externals/eglot 193c57d 075/139: Half-decent xref support |
Date: |
Mon, 14 May 2018 09:54:57 -0400 (EDT) |
branch: externals/eglot
commit 193c57d02872f8fd17b652514c553835d932d2e9
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Half-decent xref support
* eglot.el
(eglot--xref-known-symbols): New hacky var.
(eglot--xref-reset-known-symbols): New helper.
(xref-find-definitions, xref-find-references): Advise after to
call the new helper.
(xref-backend-identifier-completion-table): Rework.
(eglot--xref-make): New helper.
(xref-backend-definitions): Use it.
(xref-backend-references, xref-backend-apropos): Implement.
(eglot--obj): Add a debug spec.
(eglot--lambda): Add debug spec.
---
eglot.el | 132 +++++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 90 insertions(+), 42 deletions(-)
diff --git a/eglot.el b/eglot.el
index ad9ad52..cb92361 100644
--- a/eglot.el
+++ b/eglot.el
@@ -33,6 +33,7 @@
(require 'compile) ; for some faces
(require 'warnings)
(require 'flymake)
+(require 'xref)
;;; User tweakable stuff
@@ -171,6 +172,7 @@ CONTACT is as `eglot--contact'. Returns a process object."
(defmacro eglot--obj (&rest what)
"Make WHAT a suitable argument for `json-encode'."
+ (declare (debug (&rest form)))
;; FIXME: maybe later actually do something, for now this just fixes
;; the indenting of literal plists.
`(list ,@what))
@@ -736,7 +738,7 @@ Meaning only return locally if successful, otherwise exit
non-locally."
(mapcar (lambda (e) (apply fun e)) seq))
(cl-defmacro eglot--lambda (cl-lambda-list &body body)
- (declare (indent 1))
+ (declare (indent 1) (debug (sexp &rest form)))
`(cl-function
(lambda ,cl-lambda-list
,@body)))
@@ -1232,16 +1234,46 @@ Calls REPORT-FN maybe if server publishes diagnostics
in time."
(defun eglot-xref-backend () "EGLOT xref backend." 'eglot)
+(defvar eglot--xref-known-symbols nil)
+
+(defun eglot--xref-reset-known-symbols ()
+ "Reset `eglot--xref-reset-known-symbols'."
+ (setq eglot--xref-known-symbols nil))
+
+(advice-add 'xref-find-definitions :after #'eglot--xref-reset-known-symbols)
+(advice-add 'xref-find-references :after #'eglot--xref-reset-known-symbols)
+
+(defun eglot--xref-make (name uri position)
+ "Like `xref-make' but with LSP's NAME, URI and POSITION."
+ (xref-make name
+ (xref-make-file-location
+ (eglot--uri-to-path uri)
+ ;; F!@(#*&#$)CKING OFF-BY-ONE again
+ (1+ (plist-get position :line))
+ (plist-get position :character))))
+
(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot)))
- (eglot--mapply
- (eglot--lambda (&key name _kind _location _containerName)
- ;; a shame we have to throw all that good stuff away
- name)
- (eglot--sync-request
- (eglot--current-process-or-lose)
- :textDocument/documentSymbol
- (eglot--obj
- :textDocument (eglot--current-buffer-TextDocumentIdentifier)))))
+ (let ((proc (eglot--current-process-or-lose))
+ (text-id (eglot--current-buffer-TextDocumentIdentifier)))
+ (completion-table-with-cache
+ (lambda (string)
+ (setq eglot--xref-known-symbols
+ (eglot--mapply
+ (eglot--lambda (&key name kind location containerName)
+ (propertize name
+ :position (plist-get
+ (plist-get location :range)
+ :start)
+ :locations (list location)
+ :textDocument text-id
+ :kind kind
+ :containerName containerName))
+ (eglot--sync-request
+ proc
+ :textDocument/documentSymbol
+ (eglot--obj
+ :textDocument text-id))))
+ (all-completions string eglot--xref-known-symbols)))))
(cl-defmethod xref-backend-identifier-at-point ((_backend (eql eglot)))
(let ((symatpt (symbol-at-point)))
@@ -1251,39 +1283,55 @@ Calls REPORT-FN maybe if server publishes diagnostics
in time."
:position (eglot--pos-to-lsp-position)))))
(cl-defmethod xref-backend-definitions ((_backend (eql eglot)) identifier)
+ (let* ((rich-identifier
+ (car (member identifier eglot--xref-known-symbols)))
+ (location-or-locations
+ (if rich-identifier
+ (get-text-property 0 :locations rich-identifier)
+ (eglot--sync-request (eglot--current-process-or-lose)
+ :textDocument/definition
+ (eglot--obj
+ :textDocument
+ (get-text-property 0 :textDocument
identifier)
+ :position
+ (get-text-property 0 :position
identifier))))))
+ (eglot--mapply
+ (eglot--lambda (&key uri range)
+ (eglot--xref-make identifier uri (plist-get range :start)))
+ location-or-locations)))
+
+(cl-defmethod xref-backend-references ((_backend (eql eglot)) identifier)
+ (let* ((identifier (if (get-text-property 0 :position identifier)
+ identifier
+ (car (member identifier eglot--xref-known-symbols))))
+ (position
+ (and identifier (get-text-property 0 :position identifier)))
+ (textDocument
+ (and identifier (get-text-property 0 :textDocument identifier))))
+ (unless (and position textDocument)
+ (eglot--error "Sorry, can't discover where %s is in the workspace"
+ identifier))
+ (eglot--mapply
+ (eglot--lambda (&key uri range)
+ (eglot--xref-make identifier uri (plist-get range :start)))
+ (eglot--sync-request (eglot--current-process-or-lose)
+ :textDocument/references
+ (eglot--obj
+ :textDocument
+ textDocument
+ :position
+ position
+ :context (eglot--obj :includeDeclaration t))))))
+
+(cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern)
(eglot--mapply
- (eglot--lambda (&key uri range)
- (xref-make identifier
- (xref-make-file-location
- (eglot--uri-to-path uri)
- (plist-get (plist-get range :start) :line)
- (plist-get (plist-get range :start) :character))))
- (or
- ;; `identifier' already has `:locations' property if it was
- ;; computed via `xref-backend-identifier-completion-table'...
- ;;
- (get-text-property 0 :locations identifier)
- ;; otherwise, it came from
- ;; `xref-backend-identifier-at-point', and we have to fetch
- ;; manually
- ;;
- (let ((location-or-locations
- (eglot--sync-request (eglot--current-process-or-lose)
- :textDocument/definition
- (eglot--obj
- :textDocument
- (get-text-property 0 :textDocument identifier)
- :position
- (get-text-property 0 :position identifier)))))
- (if (vectorp (car location-or-locations))
- (car location-or-locations)
- location-or-locations)))))
-
-(cl-defmethod xref-backend-references ((_backend (eql eglot)) _identifier)
- (error "Not implemented"))
-
-(cl-defmethod xref-backend-apropos ((_backend (eql eglot)) _identifier)
- (error "Not implemented"))
+ (eglot--lambda (&key name location &allow-other-keys)
+ (let ((range (plist-get location :range))
+ (uri (plist-get location :uri)))
+ (eglot--xref-make name uri (plist-get range :start))))
+ (eglot--sync-request (eglot--current-process-or-lose)
+ :workspace/symbol
+ (eglot--obj :query pattern))))
;;; Dynamic registration
- [elpa] externals/eglot f76f04e 057/139: More correctly keep track of didOpen/didClose per buffer, (continued)
- [elpa] externals/eglot f76f04e 057/139: More correctly keep track of didOpen/didClose per buffer, João Távora, 2018/05/14
- [elpa] externals/eglot 46bb1c0 049/139: Reorganize file, João Távora, 2018/05/14
- [elpa] externals/eglot ff5a03d 074/139: Very basic xref support, João Távora, 2018/05/14
- [elpa] externals/eglot e9b5e54 077/139: ETOOMANYLAMBDAS, João Távora, 2018/05/14
- [elpa] externals/eglot dda11dd 095/139: Try to fix some textDocument/completion bugs, João Távora, 2018/05/14
- [elpa] externals/eglot ea918ab 066/139: Include source info in diagnostics, João Távora, 2018/05/14
- [elpa] externals/eglot a199c8e 070/139: Honour textDocumentSync, João Távora, 2018/05/14
- [elpa] externals/eglot e86f9b4 073/139: New helper eglot--sync-request, João Távora, 2018/05/14
- [elpa] externals/eglot 1add335 078/139: Workaround two suspected Emacs bugs, João Távora, 2018/05/14
- [elpa] externals/eglot 889ef20 085/139: Tweak the async request engine., João Távora, 2018/05/14
- [elpa] externals/eglot 193c57d 075/139: Half-decent xref support,
João Távora <=
- [elpa] externals/eglot fc6879f 084/139: Explain why didOpen on after-revert-hook is a bad idea, João Távora, 2018/05/14
- [elpa] externals/eglot 24466a9 096/139: When killing server, always wait 3 seconds, João Távora, 2018/05/14
- [elpa] externals/eglot fceb6bb 090/139: Get rid of eglot--special-buffer-process, João Távora, 2018/05/14
- [elpa] externals/eglot d254f97 082/139: Solve another textDocument/didChange bug, João Távora, 2018/05/14
- [elpa] externals/eglot f257d63 089/139: * eglot.el: Reformat to shave off some lines., João Távora, 2018/05/14
- [elpa] externals/eglot c7bd095 118/139: Improve eglot-eldoc-function, João Távora, 2018/05/14
- [elpa] externals/eglot 3e0f1c3 122/139: Misc little adjustments for readability, João Távora, 2018/05/14
- [elpa] externals/eglot 3dcbc30 109/139: Add minimal headers, commentary and autoloads, João Távora, 2018/05/14
- [elpa] externals/eglot 71e47d2 102/139: Fix odd bugs and tweak stuff, João Távora, 2018/05/14
- [elpa] externals/eglot 05c67ee 112/139: Adjust flymake integration, João Távora, 2018/05/14