From 738d18a81ea544a046a7600f0a3fb8c3ac21a696 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Thu, 3 Apr 2025 11:14:02 +0200 Subject: [PATCH] elisp-mode.el: Optimize xref-backend-references --- lisp/progmodes/elisp-mode.el | 67 +++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 132e0641785..8e7a0293296 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1159,8 +1159,9 @@ confidence." (cl-defmethod xref-backend-references :around ((_backend (eql 'elisp)) identifier) (let* ((pos (get-text-property 0 'pos identifier)) - (enable-local-variables nil)) - (or (elisp-make-xrefs (elisp-local-references pos)) + (enable-local-variables nil) + (gc-cons-threshold (* 1024 1024 1024))) + (or (elisp-make-xrefs (and pos (elisp-local-references pos))) (let (res (types (case (elisp--xref-infer-namespace-1 pos) @@ -1178,37 +1179,28 @@ confidence." (project-files (project-current)))) "Scanning for references" (with-current-buffer (find-file-noselect file) - (let (all) - (save-excursion - (goto-char (point-min)) - (condition-case e - (while t - (scope - (lambda (type beg len &rest _) - (and (or (null types) (memq type types)) - (string= identifier (buffer-substring-no-properties beg (+ beg len))) - (push (cons beg len) all))))) - (end-of-file - (setq res (nconc (elisp-make-xrefs all) res))) - (error (message "Encountered error while scanning %s: %S" file e) nil)))))) - res) + (pcase-dolist (`(,type ,beg ,len . ,_) (elisp-symbols-index)) + (and (or (null types) (memq type types)) + (string= identifier (buffer-substring-no-properties beg (+ beg len))) + (push (elisp-make-xref beg len) res))))) + (nreverse res)) ;; (cl-call-next-method backend identifier) ))) +(defun elisp-make-xref (beg len) + (let* ((beg-end (save-excursion + (goto-char beg) + (cons (pos-bol) (pos-eol)))) + (begg (car beg-end)) + (end (cdr beg-end)) + (line (buffer-substring begg end)) + (cur (- beg begg))) + (add-face-text-property cur (+ len cur) 'xref-match t line) + (xref-make line (xref-make-buffer-location (current-buffer) beg)))) + (defun elisp-make-xrefs (all) (let (res) - (pcase-dolist (`(,sym . ,len) all) - (let* ((beg-end (save-excursion - (goto-char sym) - (cons (pos-bol) (pos-eol)))) - (beg (car beg-end)) - (end (cdr beg-end)) - (line (buffer-substring-no-properties beg end)) - (cur (- sym beg))) - (add-face-text-property cur (+ len cur) 'xref-match t line) - (push (xref-make line (xref-make-buffer-location - (current-buffer) sym)) - res))) + (dolist (ent all) (push (elisp-make-xref (car ent) (cdr ent)) res)) res)) (defun elisp--xref-filter-definitions (definitions namespace symbol) @@ -2672,5 +2664,24 @@ of TARGET." (put 'read-symbol-shorthands 'safe-local-variable #'consp) +(defvar-local elisp-symbols-index-cache nil) + +(defun elisp-symbols-index () + (cdr (if (<= (buffer-chars-modified-tick) + (or (car elisp-symbols-index-cache) 0)) + elisp-symbols-index-cache + (setq elisp-symbols-index-cache + (cons (buffer-chars-modified-tick) + (elisp-symbols-index-1)))))) + +(defun elisp-symbols-index-1 () + (let (all) + (save-excursion + (goto-char (point-min)) + (condition-case e + (while t (scope (lambda (&rest args) (push args all)))) + (end-of-file (nreverse all)) + (error (message "Encountered error while scanning %s: %S" buffer-file-name e) nil))))) + (provide 'elisp-mode) ;;; elisp-mode.el ends here -- 2.39.5