From 0b75272ea47cea2070116146f30664719b8c8d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Tue, 27 Nov 2018 13:49:30 +0000 Subject: [PATCH] Per https://github.com/joaotavora/eglot/issues/52, https://github.com/joaotavora/eglot/issues/127: Improve performance of xref summary line collection * eglot.el (eglot--temp-location-buffers): New variable. (eglot--handling-xrefs): New macro. (eglot--xref-make): Use eglot--temp-location-buffers. (xref-backend-definitions, xref-backend-references) (xref-backend-apropos): Use eglot--handling-xrefs. --- eglot.el | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/eglot.el b/eglot.el index 8ba483b167..1522935281 100644 --- a/eglot.el +++ b/eglot.el @@ -1478,13 +1478,26 @@ DUMMY is ignored." (advice-add 'xref-find-definitions :after #'eglot--xref-reset-known-symbols) (advice-add 'xref-find-references :after #'eglot--xref-reset-known-symbols) +(defvar eglot--temp-location-buffers (make-hash-table :test #'equal) + "Helper variable for `eglot--handling-xrefs'.") + +(defmacro eglot--handling-xrefs (&rest body) + "Properly sort and handle xrefs produced and returned by BODY." + `(unwind-protect + (sort (progn ,@body) + (lambda (a b) + (< (xref-location-line (xref-item-location a)) + (xref-location-line (xref-item-location b))))) + (maphash (lambda (_uri buf) (kill-buffer buf)) eglot--temp-location-buffers) + (clrhash eglot--temp-location-buffers))) + (defun eglot--xref-make (name uri range) "Like `xref-make' but with LSP's NAME, URI and RANGE. Try to visit the target file for a richer summary line." (pcase-let* - ((`(,beg . ,end) (eglot--range-region range)) - (file (eglot--uri-to-path uri)) - (visiting (find-buffer-visiting file)) + ((file (eglot--uri-to-path uri)) + (visiting (or (find-buffer-visiting file) + (gethash uri eglot--temp-location-buffers))) (collect (lambda () (eglot--widening (pcase-let* ((`(,beg . ,end) (eglot--range-region range)) @@ -1497,19 +1510,16 @@ Try to visit the target file for a richer summary line." (`(,summary ,line ,column) (cond (visiting (with-current-buffer visiting (funcall collect))) - ((file-readable-p file) (with-temp-buffer (insert-file-contents file) - (funcall collect))) + ((file-readable-p file) (with-current-buffer + (puthash uri (generate-new-buffer " *temp*") + eglot--temp-location-buffers) + (insert-file-contents file) + (funcall collect))) (t ;; fall back to the "dumb strategy" (let ((start (cl-getf range :start))) (list name (1+ (cl-getf start :line)) (cl-getf start :character))))))) (xref-make summary (xref-make-file-location file line column)))) -(defun eglot--sort-xrefs (xrefs) - (sort xrefs - (lambda (a b) - (< (xref-location-line (xref-item-location a)) - (xref-location-line (xref-item-location b)))))) - (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot))) (when (eglot--server-capable :documentSymbolProvider) (let ((server (eglot--current-server-or-lose)) @@ -1553,7 +1563,7 @@ Try to visit the target file for a richer summary line." (locations (and definitions (if (vectorp definitions) definitions (vector definitions))))) - (eglot--sort-xrefs + (eglot--handling-xrefs (mapcar (jsonrpc-lambda (&key uri range) (eglot--xref-make identifier uri range)) locations)))) @@ -1567,7 +1577,7 @@ Try to visit the target file for a richer summary line." (and rich (get-text-property 0 :textDocumentPositionParams rich)))))) (unless params (eglot--error "Don' know where %s is in the workspace!" identifier)) - (eglot--sort-xrefs + (eglot--handling-xrefs (mapcar (jsonrpc-lambda (&key uri range) (eglot--xref-make identifier uri range)) @@ -1580,7 +1590,7 @@ Try to visit the target file for a richer summary line." (cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern) (when (eglot--server-capable :workspaceSymbolProvider) - (eglot--sort-xrefs + (eglot--handling-xrefs (mapcar (jsonrpc-lambda (&key name location &allow-other-keys) (cl-destructuring-bind (&key uri range) location