]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement xref-find-references in etags and elisp-mode
authorDmitry Gutov <dgutov@yandex.ru>
Fri, 1 May 2015 18:54:33 +0000 (21:54 +0300)
committerDmitry Gutov <dgutov@yandex.ru>
Fri, 1 May 2015 20:41:27 +0000 (23:41 +0300)
* lisp/progmodes/elisp-mode.el (elisp--xref-find-references): New function.
(elisp-xref-find): Use it.

* lisp/progmodes/etags.el (etags-xref-find): Use `xref-collect-references'.

* lisp/progmodes/xref.el (xref-collect-references):
(xref--collect-reference): New functions.

lisp/progmodes/elisp-mode.el
lisp/progmodes/etags.el
lisp/progmodes/xref.el

index f2890686e799b8446f02f4b2beef3056b65538d5..ef477d64fcc5c1f07b9022f039d88bfd732460b5 100644 (file)
@@ -587,6 +587,8 @@ It can be quoted, or be inside a quoted form."
       (let ((sym (intern-soft id)))
         (when sym
           (elisp--xref-find-definitions sym))))
+    (`references
+     (elisp--xref-find-references id))
     (`apropos
      (elisp--xref-find-apropos id))))
 
@@ -635,6 +637,25 @@ It can be quoted, or be inside a quoted form."
              lst))))
       lst)))
 
+(defun elisp--xref-find-references (symbol)
+  (let* ((dirs (sort
+                (mapcar
+                 (lambda (dir)
+                   (file-name-as-directory (expand-file-name dir)))
+                 (cons package-user-dir load-path))
+                #'string<))
+         (ref dirs))
+    ;; Delete subdirectories from the list.
+    (while (cdr ref)
+      (if (string-prefix-p (car ref) (cadr ref))
+          (setcdr ref (cddr ref))
+        (setq ref (cdr ref))))
+    (mapcan
+     (lambda (dir)
+       (and (file-exists-p dir)
+            (xref-collect-references symbol dir)))
+     dirs)))
+
 (defun elisp--xref-find-apropos (regexp)
   (apply #'nconc
          (let (lst)
index b4ce8b11c9ceafee57fceab0a1793b7aec904417..9a57d8ad88601b47bf3fe65077fc93193a9cc4ac 100644 (file)
@@ -2082,6 +2082,10 @@ for \\[find-tag] (which see)."
 (defun etags-xref-find (action id)
   (pcase action
     (`definitions (etags--xref-find-definitions id))
+    (`references (mapcan
+                  (lambda (file)
+                    (xref-collect-references id (file-name-directory file)))
+                  tags-table-list))
     (`apropos (etags--xref-find-definitions id t))))
 
 (defun etags--xref-find-definitions (pattern &optional regexp?)
index fc27c2688451ac04dbe78f2bd1c91b022b75be33..ea705fc852b079f263799aea57526f9c760bd009 100644 (file)
@@ -674,6 +674,52 @@ and just use etags."
     (setq-local xref-identifier-completion-table-function
                 (cdr xref-etags-mode--saved))))
 
+(declare-function semantic-symref-find-references-by-name "semantic/symref")
+(declare-function semantic-find-file-noselect "semantic/fw")
+
+(defun xref-collect-references (name dir)
+  "Collect mentions of NAME inside DIR.
+Uses the Semantic Symbol Reference API, see
+`semantic-symref-find-references-by-name' for details on which
+tools are used, and when."
+  (require 'semantic/symref)
+  (defvar semantic-symref-tool)
+  (cl-assert (directory-name-p dir))
+  (let* ((default-directory dir)
+         (semantic-symref-tool 'detect)
+         (res (semantic-symref-find-references-by-name name 'subdirs))
+         (hits (and res (oref res :hit-lines)))
+         (orig-buffers (buffer-list))
+         xrefs)
+    (unwind-protect
+        (setq xrefs
+              (mapcar (lambda (hit) (xref--collect-reference hit name))
+                      hits))
+      (mapc #'kill-buffer
+            (cl-set-difference (buffer-list) orig-buffers)))
+    (delq nil xrefs)))
+
+(defun xref--collect-reference (hit name)
+  (pcase-let* ((`(,line . ,file) hit)
+               (buf (or (find-buffer-visiting file)
+                        (semantic-find-file-noselect file))))
+    (with-current-buffer buf
+      (save-excursion
+        (goto-char (point-min))
+        (forward-line (1- line))
+        (when (re-search-forward (format "\\_<%s\\_>"
+                                         (regexp-quote name))
+                                 (line-end-position) t)
+          (goto-char (match-beginning 0))
+          (xref-make (format
+                      "%d: %s"
+                      line
+                      (buffer-substring
+                       (line-beginning-position)
+                       (line-end-position)))
+                     (xref-make-file-location file line
+                                              (current-column))))))))
+
 \f
 (provide 'xref)