]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve elisp 'xref-backend-references'.
authorEshel Yaron <me@eshelyaron.com>
Fri, 11 Apr 2025 19:36:14 +0000 (21:36 +0200)
committerEshel Yaron <me@eshelyaron.com>
Fri, 11 Apr 2025 19:36:14 +0000 (21:36 +0200)
lisp/emacs-lisp/subr-x.el
lisp/progmodes/elisp-mode.el
lisp/progmodes/xref.el

index 50b10a324008f1edf94bb7f16f06b711abc1e548..2df580e42119c809dcacc273bf6815734a4c5dec 100644 (file)
@@ -321,6 +321,7 @@ automatically killed, which means that in a such case
         buffer
       (generate-new-buffer " *work*" t))))
 
+;;;###autoload
 (defun work-buffer--release (buffer)
   "Release work BUFFER."
   (if (buffer-live-p buffer)
index a9451fbda193ddc95594fa3938588f106aad84b8..7cb079e75becd9c89d33c43a8774669153c6ef5d 100644 (file)
@@ -850,7 +850,9 @@ in `completion-at-point-functions' (which see)."
 ;;; Xref backend
 
 (declare-function xref-make "progmodes/xref" (summary location))
+(declare-function xref-make-match "progmodes/xref" (summary location length))
 (declare-function xref-item-location "progmodes/xref" (this))
+(declare-function xref-make-file-pos-location "progmodes/xref" (file pos line))
 (declare-function xref-make-buffer-location "progmodes/xref" (buffer position))
 
 (defun elisp--xref-backend () 'elisp)
@@ -1123,11 +1125,25 @@ confidence."
                 (lambda (file) (string= (file-name-extension file) "el"))
                 (project-files (project-current))))
               "Scanning for references"
-            (with-current-buffer (find-file-noselect file)
-              (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)))))
+            (pcase-dolist (`(,type ,beg ,len ,sym . ,_) (elisp-symbols-index file))
+              (and (or (null types) (memq type types))
+                   (string= identifier sym)
+                   (with-work-buffer
+                     (insert-file-contents file)
+                     (goto-char beg)
+                     (push
+                      (let* ((begg (pos-bol))
+                             (endd (pos-eol))
+                             (line (buffer-substring begg endd))
+                             (cur (- beg begg)))
+                        (add-face-text-property
+                         cur (+ len cur) 'xref-match t line)
+                        (xref-make-match
+                         line
+                         (xref-make-file-pos-location
+                          file beg (line-number-at-pos beg))
+                         len))
+                      res)))))
           (nreverse res))
         ;; (cl-call-next-method backend identifier)
         )))
@@ -1141,7 +1157,7 @@ confidence."
          (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))))
+    (xref-make-match line (xref-make-buffer-location (current-buffer) beg) len)))
 
 (defun elisp-make-xrefs (all)
   (let (res)
@@ -2652,22 +2668,31 @@ of TARGET."
 \f
 (put 'read-symbol-shorthands 'safe-local-variable #'consp)
 
-(defvar-local elisp-symbols-index-cache nil)
+(defvar elisp-symbols-index-cache (make-hash-table :test #'equal))
 
-(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 (file)
+  (let ((cached (gethash file elisp-symbols-index-cache))
+        (modtime (file-attribute-modification-time (file-attributes file))))
+    (cdr
+     (if (time-less-p (or (car cached) 0) modtime)
+         (puthash file (cons modtime
+                             (with-work-buffer
+                               (insert-file-contents file)
+                               (elisp-symbols-index-1)))
+                  elisp-symbols-index-cache)
+       cached))))
 
 (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))))
+          (while t
+            (scope
+             (lambda (type beg len &rest _)
+               (push
+                (list type beg len (buffer-substring beg (+ beg len)))
+                all))))
         (end-of-file (nreverse all))
         (error (message "Encountered error while scanning %s: %S" buffer-file-name e) nil)))))
 
index 5ce0e53654a819d3ad06eccfd55b596a36e595a0..0ba209bc72d37f734923cd6dd80b016ea51e41f7 100644 (file)
@@ -165,6 +165,23 @@ Line numbers start from 1 and columns from 0."
             (forward-char column))
           (point-marker))))))
 
+(cl-defstruct (xref-file-pos-location
+               (:constructor xref-make-file-pos-location (file pos line)))
+  "A specific position in a given file."
+  file pos line)
+
+(cl-defmethod xref-location-marker ((l xref-file-pos-location))
+  (with-current-buffer
+      (let ((find-file-suppress-same-file-warnings t))
+        (find-file-noselect (xref-file-pos-location-file l)))
+    (copy-marker (xref-file-pos-location-pos l))))
+
+(cl-defmethod xref-location-group ((l xref-file-pos-location))
+  (xref-file-pos-location-file l))
+
+(cl-defmethod xref-location-line ((l xref-file-pos-location))
+  (xref-file-pos-location-line l))
+
 (cl-defstruct (xref-buffer-location
                (:constructor xref-make-buffer-location (buffer position)))
   buffer position)