;;; semantic/symref.el --- Symbol Reference API
-;; Copyright (C) 2008-2015 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2016 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <eric@siege-engine.com>
;; Your tool should then create an instance of `semantic-symref-result'.
(require 'semantic)
+(eval-when-compile (require 'semantic/find)) ;For semantic-find-tags-*
+(eval-when-compile (require 'ede/proj)) ;For `metasubproject' warning.
(defvar ede-minor-mode)
(declare-function data-debug-new-buffer "data-debug")
(defun semantic-symref-calculate-rootdir ()
"Calculate the root directory for a symref search.
-Start with and EDE project, or use the default directory."
+Start with an EDE project, or use the default directory."
(let* ((rootproj (when (and (featurep 'ede) ede-minor-mode)
(ede-toplevel)))
(rootdirbase (if rootproj
default-directory)))
(if (and rootproj (condition-case nil
;; Hack for subprojects.
- (oref rootproj :metasubproject)
+ (oref rootproj metasubproject)
(error nil)))
(ede-up-directory rootdirbase)
rootdirbase)))
;;;###autoload
(defun semantic-symref-find-references-by-name (name &optional scope tool-return)
"Find a list of references to NAME in the current project.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'.
;;;###autoload
(defun semantic-symref-find-tags-by-name (name &optional scope)
"Find a list of tags by NAME in the current project.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'."
;;;###autoload
(defun semantic-symref-find-tags-by-regexp (name &optional scope)
"Find a list of references to NAME in the current project.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'."
;;;###autoload
(defun semantic-symref-find-tags-by-completion (name &optional scope)
"Find a list of references to NAME in the current project.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'."
;;;###autoload
(defun semantic-symref-find-file-references-by-name (name &optional scope)
"Find a list of references to NAME in the current project.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'."
;;;###autoload
(defun semantic-symref-find-text (text &optional scope)
"Find a list of occurrences of TEXT in the current project.
-TEXT is a regexp formatted for use with egrep.
-Optional SCOPE specifies which file set to search. Defaults to 'project.
+TEXT is a regexp formatted for use with grep -E.
+Optional SCOPE specifies which file set to search. Defaults to `project'.
Refers to `semantic-symref-tool', to determine the reference tool to use
for the current buffer.
Returns an object of class `semantic-symref-result'."
- (interactive "sEgrep style Regexp: ")
+ (interactive "sGrep -E style Regexp: ")
(let* ((inst (semantic-symref-instantiate
:searchfor text
:searchtype 'regexp
(semantic-symref-data-debug-last-result))))
)
+;;; SYMREF TOOLS
+;;
+;; The base symref tool provides something to hang new tools off of
+;; for finding symbol references.
+(defclass semantic-symref-tool-baseclass ()
+ ((searchfor :initarg :searchfor
+ :type string
+ :documentation "The thing to search for.")
+ (searchtype :initarg :searchtype
+ :type symbol
+ :documentation "The type of search to do.
+Values could be 'symbol, 'regexp, 'tagname, or 'completion.")
+ (searchscope :initarg :searchscope
+ :type symbol
+ :documentation
+ "The scope to search for.
+Can be 'project, 'target, or 'file.")
+ (resulttype :initarg :resulttype
+ :type symbol
+ :documentation
+ "The kind of search results desired.
+Can be 'line, 'file, or 'tag.
+The type of result can be converted from 'line to 'file, or 'line to 'tag,
+but not from 'file to 'line or 'tag.")
+ )
+ "Baseclass for all symbol references tools.
+A symbol reference tool supplies functionality to identify the locations of
+where different symbols are used.
+
+Subclasses should be named `semantic-symref-tool-NAME', where
+NAME is the name of the tool used in the configuration variable
+`semantic-symref-tool'"
+ :abstract t)
+
+(cl-defmethod semantic-symref-get-result ((tool semantic-symref-tool-baseclass))
+ "Calculate the results of a search based on TOOL.
+The symref TOOL should already contain the search criteria."
+ (let ((answer (semantic-symref-perform-search tool))
+ )
+ (when answer
+ (let ((answersym (if (eq (oref tool resulttype) 'file)
+ :hit-files
+ (if (stringp (car answer))
+ :hit-text
+ :hit-lines))))
+ (semantic-symref-result (oref tool searchfor)
+ answersym
+ answer
+ :created-by tool))
+ )
+ ))
+
+(cl-defmethod semantic-symref-perform-search ((_tool semantic-symref-tool-baseclass))
+ "Base search for symref tools should throw an error."
+ (error "Symref tool objects must implement `semantic-symref-perform-search'"))
+
+(cl-defmethod semantic-symref-parse-tool-output ((tool semantic-symref-tool-baseclass)
+ outputbuffer)
+ "Parse the entire OUTPUTBUFFER of a symref tool.
+Calls the method `semantic-symref-parse-tool-output-one-line' over and
+over until it returns nil."
+ (with-current-buffer outputbuffer
+ (goto-char (point-min))
+ (let ((result nil)
+ (hit nil))
+ (while (setq hit (semantic-symref-parse-tool-output-one-line tool))
+ (setq result (cons hit result)))
+ (nreverse result)))
+ )
+
+(cl-defmethod semantic-symref-parse-tool-output-one-line ((_tool semantic-symref-tool-baseclass))
+ "Base tool output parser is not implemented."
+ (error "Symref tool objects must implement `semantic-symref-parse-tool-output-one-line'"))
+
;;; RESULTS
;;
;; The results class and methods provide features for accessing hits.
)
"The results from a symbol reference search.")
-(defmethod semantic-symref-result-get-files ((result semantic-symref-result))
+(cl-defmethod semantic-symref-result-get-files ((result semantic-symref-result))
"Get the list of files from the symref result RESULT."
- (if (slot-boundp result :hit-files)
+ (if (slot-boundp result 'hit-files)
(oref result hit-files)
- (let* ((lines (oref result :hit-lines))
+ (let* ((lines (oref result hit-lines))
(files (mapcar (lambda (a) (cdr a)) lines))
(ans nil))
(setq ans (list (car files))
"List of buffers opened by `semantic-symref-result-get-tags'.")
(defun semantic-symref-cleanup-recent-buffers-fcn ()
- "Hook function to be used in 'post-command-hook' to cleanup buffers.
+ "Hook function to be used in `post-command-hook' to cleanup buffers.
Buffers collected during symref can result in some files being
opened multiple times for one operation. This will keep buffers open
until the next command is executed."
(setq semantic-symref-recently-opened-buffers nil)
(remove-hook 'post-command-hook 'semantic-symref-cleanup-recent-buffers-fcn)
)
-
-(defmethod semantic-symref-result-get-tags ((result semantic-symref-result)
+
+(cl-defmethod semantic-symref-result-get-tags ((result semantic-symref-result)
&optional open-buffers)
"Get the list of tags from the symref result RESULT.
Optional OPEN-BUFFERS indicates that the buffers that the hits are
in should remain open after scanning.
Note: This can be quite slow if most of the hits are not in buffers
already."
- (if (and (slot-boundp result :hit-tags) (oref result hit-tags))
+ (if (and (slot-boundp result 'hit-tags) (oref result hit-tags))
(oref result hit-tags)
;; Calculate the tags.
- (let ((lines (oref result :hit-lines))
- (txt (oref (oref result :created-by) :searchfor))
- (searchtype (oref (oref result :created-by) :searchtype))
+ (let ((lines (oref result hit-lines))
+ (txt (oref (oref result created-by) searchfor))
+ (searchtype (oref (oref result created-by) searchtype))
(ans nil)
(out nil))
(save-excursion
(semantic--tag-put-property (car out) :hit lines)))
))
;; Out is reversed... twice
- (oset result :hit-tags (nreverse out)))))
+ (oset result hit-tags (nreverse out)))))
(defun semantic-symref-hit-to-tag-via-db (hit searchtxt searchtype)
"Convert the symref HIT into a TAG by looking up the tag via a database.
;; tagname, tagregexp, tagcompletions
(if (not (memq searchtype '(tagname tagregexp tagcompletions)))
nil
- (let* ((line (car hit))
- (file (cdr hit))
+ (let* ((file (cdr hit))
;; FAIL here vv - don't load is not obeyed if no table found.
(db (semanticdb-file-table-object file t))
- (found nil)
+ (found
+ (cond ((eq searchtype 'tagname)
+ (semantic-find-tags-by-name searchtxt db))
+ ((eq searchtype 'tagregexp)
+ (semantic-find-tags-by-name-regexp searchtxt db))
+ ((eq searchtype 'tagcompletions)
+ (semantic-find-tags-for-completion searchtxt db))))
(hit nil)
)
- (cond ((eq searchtype 'tagname)
- (setq found (semantic-find-tags-by-name searchtxt db)))
- ((eq searchtype 'tagregexp)
- (setq found (semantic-find-tags-by-name-regexp searchtxt db)))
- ((eq searchtype 'tagcompletions)
- (setq found (semantic-find-tags-for-completion searchtxt db)))
- )
;; Loop over FOUND to see if we can line up a match with a line number.
(when (= (length found) 1)
(setq hit (car found)))
(goto-char (point-min))
(forward-line (1- line))
- ;; Search forward for the matching text
- (when (re-search-forward (regexp-quote searchtxt)
+ ;; Search forward for the matching text.
+ ;; FIXME: This still fails if the regexp uses something specific
+ ;; to the extended syntax, like grouping.
+ (when (re-search-forward (if (memq searchtype '(regexp tagregexp))
+ searchtxt
+ (regexp-quote searchtxt))
(point-at-eol)
t)
(goto-char (match-beginning 0))
(semantic--tag-put-property tag :hit (list line)))
tag))
-;;; SYMREF TOOLS
-;;
-;; The base symref tool provides something to hang new tools off of
-;; for finding symbol references.
-(defclass semantic-symref-tool-baseclass ()
- ((searchfor :initarg :searchfor
- :type string
- :documentation "The thing to search for.")
- (searchtype :initarg :searchtype
- :type symbol
- :documentation "The type of search to do.
-Values could be `symbol, `regexp, 'tagname, or 'completion.")
- (searchscope :initarg :searchscope
- :type symbol
- :documentation
- "The scope to search for.
-Can be 'project, 'target, or 'file.")
- (resulttype :initarg :resulttype
- :type symbol
- :documentation
- "The kind of search results desired.
-Can be 'line, 'file, or 'tag.
-The type of result can be converted from 'line to 'file, or 'line to 'tag,
-but not from 'file to 'line or 'tag.")
- )
- "Baseclass for all symbol references tools.
-A symbol reference tool supplies functionality to identify the locations of
-where different symbols are used.
-
-Subclasses should be named `semantic-symref-tool-NAME', where
-NAME is the name of the tool used in the configuration variable
-`semantic-symref-tool'"
- :abstract t)
-
-(defmethod semantic-symref-get-result ((tool semantic-symref-tool-baseclass))
- "Calculate the results of a search based on TOOL.
-The symref TOOL should already contain the search criteria."
- (let ((answer (semantic-symref-perform-search tool))
- )
- (when answer
- (let ((answersym (if (eq (oref tool :resulttype) 'file)
- :hit-files
- (if (stringp (car answer))
- :hit-text
- :hit-lines))))
- (semantic-symref-result (oref tool searchfor)
- answersym
- answer
- :created-by tool))
- )
- ))
-
-(defmethod semantic-symref-perform-search ((tool semantic-symref-tool-baseclass))
- "Base search for symref tools should throw an error."
- (error "Symref tool objects must implement `semantic-symref-perform-search'"))
-
-(defmethod semantic-symref-parse-tool-output ((tool semantic-symref-tool-baseclass)
- outputbuffer)
- "Parse the entire OUTPUTBUFFER of a symref tool.
-Calls the method `semantic-symref-parse-tool-output-one-line' over and
-over until it returns nil."
- (with-current-buffer outputbuffer
- (goto-char (point-min))
- (let ((result nil)
- (hit nil))
- (while (setq hit (semantic-symref-parse-tool-output-one-line tool))
- (setq result (cons hit result)))
- (nreverse result)))
- )
-
-(defmethod semantic-symref-parse-tool-output-one-line ((tool semantic-symref-tool-baseclass))
- "Base tool output parser is not implemented."
- (error "Symref tool objects must implement `semantic-symref-parse-tool-output-one-line'"))
-
(provide 'semantic/symref)
;; Local variables: