]> git.eshelyaron.com Git - emacs.git/commitdiff
elisp-mode.el: Optimize xref-backend-references
authorEshel Yaron <me@eshelyaron.com>
Thu, 3 Apr 2025 09:14:02 +0000 (11:14 +0200)
committerEshel Yaron <me@eshelyaron.com>
Thu, 3 Apr 2025 09:14:02 +0000 (11:14 +0200)
lisp/progmodes/elisp-mode.el

index 132e0641785a1ee639ddeb5c699dc18a21eef120..8e7a0293296fb82d94b20647e63b21b47b82174d 100644 (file)
@@ -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."
 \f
 (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