;;; 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)
(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)
)))
(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)
\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)))))
(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)