[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot ff5a03d 074/139: Very basic xref support
From: |
João Távora |
Subject: |
[elpa] externals/eglot ff5a03d 074/139: Very basic xref support |
Date: |
Mon, 14 May 2018 09:54:57 -0400 (EDT) |
branch: externals/eglot
commit ff5a03dd81d543847cee9679a20bdb39539f1a70
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Very basic xref support
* eglot.el (eglot--pos-to-lisp-position): Move up.
(eglot--mapply, eglot--lambda): New helpers.
(eglot--uri-to-path): New helper.
(eglot--managed-mode): Manage xref-backend-functions.
(eglot-xref-backend): New function.
(xref-backend-identifier-completion-table)
(xref-backend-identifier-at-point)
(xref-backend-definitions): New methods.
(xref-backend-references)
(xref-backend-apropos): New methods, still unimplemented.
---
eglot.el | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 82 insertions(+), 11 deletions(-)
diff --git a/eglot.el b/eglot.el
index 34ce0f8..ad9ad52 100644
--- a/eglot.el
+++ b/eglot.el
@@ -721,12 +721,36 @@ Meaning only return locally if successful, otherwise exit
non-locally."
(apply #'format format args)
:warning)))
+(defun eglot--pos-to-lsp-position (&optional pos)
+ "Convert point POS to LSP position."
+ (save-excursion
+ (eglot--obj :line
+ ;; F!@(#*&#$)CKING OFF-BY-ONE
+ (1- (line-number-at-pos pos t))
+ :character
+ (- (goto-char (or pos (point)))
+ (line-beginning-position)))))
+
+(defun eglot--mapply (fun seq)
+ "Apply FUN to every element of SEQ."
+ (mapcar (lambda (e) (apply fun e)) seq))
+
+(cl-defmacro eglot--lambda (cl-lambda-list &body body)
+ (declare (indent 1))
+ `(cl-function
+ (lambda ,cl-lambda-list
+ ,@body)))
+
(defun eglot--path-to-uri (path)
"Urify PATH."
(url-hexify-string
(concat "file://" (file-truename path))
url-path-allowed-chars))
+(defun eglot--uri-to-path (uri)
+ "Convert URI to a file path."
+ (url-filename (url-generic-parse-url (url-unhex-string uri))))
+
;;; Minor modes
;;;
@@ -750,6 +774,7 @@ Meaning only return locally if successful, otherwise exit
non-locally."
;; (add-hook 'after-revert-hook 'eglot--signal-textDocument/didOpen nil t)
(add-hook 'before-save-hook 'eglot--signal-textDocument/willSave nil t)
(add-hook 'after-save-hook 'eglot--signal-textDocument/didSave nil t)
+ (add-hook 'xref-backend-functions 'eglot-xref-backend nil t)
(flymake-mode 1))
(t
(remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
@@ -759,7 +784,8 @@ Meaning only return locally if successful, otherwise exit
non-locally."
(remove-hook 'before-revert-hook 'eglot--signal-textDocument/didClose t)
;; (remove-hook 'after-revert-hook 'eglot--signal-textDocument/didOpen t)
(remove-hook 'before-save-hook 'eglot--signal-textDocument/willSave t)
- (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t))))
+ (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
+ (remove-hook 'xref-backend-functions 'eglot-xref-backend t))))
(define-minor-mode eglot-mode
"Minor mode for all buffers managed by EGLOT in some way." nil
@@ -1080,16 +1106,6 @@ running. INTERACTIVE is t if called interactively."
(widen)
(buffer-substring-no-properties (point-min) (point-max))))))
-(defun eglot--pos-to-lsp-position (pos)
- "Convert point POS to LSP position."
- (save-excursion
- (eglot--obj :line
- ;; F!@(#*&#$)CKING OFF-BY-ONE
- (1- (line-number-at-pos pos t))
- :character
- (- (goto-char pos)
- (line-beginning-position)))))
-
(defun eglot--before-change (start end)
"Hook onto `before-change-functions'.
Records START and END, crucially convert them into
@@ -1214,6 +1230,61 @@ Calls REPORT-FN maybe if server publishes diagnostics in
time."
;; make the server report new diagnostics.
(eglot--signal-textDocument/didChange))
+(defun eglot-xref-backend () "EGLOT xref backend." 'eglot)
+
+(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)))))
+
+(cl-defmethod xref-backend-identifier-at-point ((_backend (eql eglot)))
+ (let ((symatpt (symbol-at-point)))
+ (when symatpt
+ (propertize (symbol-name symatpt)
+ :textDocument (eglot--current-buffer-TextDocumentIdentifier)
+ :position (eglot--pos-to-lsp-position)))))
+
+(cl-defmethod xref-backend-definitions ((_backend (eql eglot)) identifier)
+ (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"))
+
;;; Dynamic registration
;;;
- [elpa] externals/eglot df5d76d 065/139: Reply to client/registerCapability (don't handle it yet), (continued)
- [elpa] externals/eglot df5d76d 065/139: Reply to client/registerCapability (don't handle it yet), João Távora, 2018/05/14
- [elpa] externals/eglot c2862f4 063/139: Don't auto-reconnect if last attempt lasted less than 3 seconds, João Távora, 2018/05/14
- [elpa] externals/eglot f1b6485 053/139: Trim some edges and add a bunch of boring RPC methods, João Távora, 2018/05/14
- [elpa] externals/eglot 0e95167 042/139: Watch for files opened under umbrella of existing process, João Távora, 2018/05/14
- [elpa] externals/eglot 4d4b85d 061/139: eglot-editing-mode becomes eglot--managed-mode, João Távora, 2018/05/14
- [elpa] externals/eglot e7ffc31 067/139: Make reported capabilities into its own function, João Távora, 2018/05/14
- [elpa] externals/eglot 79a2a1e 069/139: Be quite explicit about our lack of capabilities right now, João Távora, 2018/05/14
- [elpa] externals/eglot 95187cf 058/139: Connect to LSP server via TCP, João Távora, 2018/05/14
- [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 <=
- [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, 2018/05/14
- [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