123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- (require 'semantic)
- (require 'semantic/analyze)
- (require 'semantic/db-find)
- (eval-when-compile (require 'semantic/find))
- (declare-function data-debug-new-buffer "data-debug")
- (declare-function data-debug-insert-object-slots "eieio-datadebug")
- (declare-function semantic-momentary-highlight-tag "semantic/decorate")
- (defclass semantic-analyze-references ()
- ((tag :initarg :tag
- :type semantic-tag
- :documentation
- "The starting TAG we are providing references analysis for.")
- (tagdb :initarg :tagdb
- :documentation
- "The database that tag can be found in.")
- (scope :initarg :scope
- :documentation "A Scope object.")
- (rawsearchdata :initarg :rawsearchdata
- :documentation
- "The raw search data for TAG's name across all databases.")
-
-
- )
- "Class containing data from a semantic analysis.")
- (define-overloadable-function semantic-analyze-tag-references (tag &optional db)
- "Analyze the references for TAG.
- Returns a class with information about TAG.
- Optional argument DB is a database. It will be used to help
- locate TAG.
- Use `semantic-analyze-current-tag' to debug this fcn.")
- (defun semantic-analyze-tag-references-default (tag &optional db)
- "Analyze the references for TAG.
- Returns a class with information about TAG.
- Optional argument DB is a database. It will be used to help
- locate TAG.
- Use `semantic-analyze-current-tag' to debug this fcn."
- (when (not (semantic-tag-p tag)) (signal 'wrong-type-argument (list 'semantic-tag-p tag)))
- (let ((allhits nil)
- (scope nil)
- )
- (save-excursion
- (semantic-go-to-tag tag db)
- (setq scope (semantic-calculate-scope))
- (setq allhits (semantic--analyze-refs-full-lookup tag scope))
- (semantic-analyze-references (semantic-tag-name tag)
- :tag tag
- :tagdb db
- :scope scope
- :rawsearchdata allhits)
- )))
- (defmethod semantic-analyze-refs-impl ((refs semantic-analyze-references) &optional in-buffer)
- "Return the implementations derived in the reference analyzer REFS.
- Optional argument IN-BUFFER indicates that the returned tag should be in an active buffer."
- (let ((allhits (oref refs rawsearchdata))
- (tag (oref refs :tag))
- (impl nil)
- )
- (semanticdb-find-result-mapc
- (lambda (T DB)
- "Examine T in the database DB, and sont it."
- (let* ((ans (semanticdb-normalize-one-tag DB T))
- (aT (cdr ans))
- (aDB (car ans))
- )
- (when (and (not (semantic-tag-prototype-p aT))
- (semantic-tag-similar-p tag aT :prototype-flag :parent))
- (when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
- (push aT impl))))
- allhits)
- impl))
- (defmethod semantic-analyze-refs-proto ((refs semantic-analyze-references) &optional in-buffer)
- "Return the prototypes derived in the reference analyzer REFS.
- Optional argument IN-BUFFER indicates that the returned tag should be in an active buffer."
- (let ((allhits (oref refs rawsearchdata))
- (tag (oref refs :tag))
- (proto nil))
- (semanticdb-find-result-mapc
- (lambda (T DB)
- "Examine T in the database DB, and sort it."
- (let* ((ans (semanticdb-normalize-one-tag DB T))
- (aT (cdr ans))
- (aDB (car ans))
- )
- (when (and (semantic-tag-prototype-p aT)
- (semantic-tag-similar-p tag aT :prototype-flag :parent))
- (when in-buffer (save-excursion (semantic-go-to-tag aT aDB)))
- (push aT proto))))
- allhits)
- proto))
- (defun semantic--analyze-refs-full-lookup (tag scope)
- "Perform a full lookup for all occurrences of TAG in the current project.
- TAG should be the tag currently under point.
- SCOPE is the scope the cursor is in. From this a list of parents is
- derived. If SCOPE does not have parents, then only a simple lookup is done."
- (if (not (oref scope parents))
-
- (semantic--analyze-refs-full-lookup-simple tag)
-
-
- (semantic--analyze-refs-full-lookup-with-parents tag scope)
- ))
- (defun semantic--analyze-refs-find-child-in-find-results (find-results name class)
- "Find in FIND-RESULT a tag NAME which is a child of a tag in FIND-RESULTS.
- CLASS is the class of the tag that ought to be returned."
- (let ((ans nil)
- (subans nil))
-
- (dolist (FDB find-results)
- (setq subans nil)
-
- (dolist (T (cdr FDB))
-
- (let* ((chil (semantic-tag-type-members T))
- (match (semantic-find-tags-by-name name chil)))
-
- (dolist (M match)
- (when (semantic-tag-of-class-p M class)
- (push M subans)))))
-
- (when subans
- (push (cons (car FDB) subans) ans))
- )
- ans))
- (defun semantic--analyze-refs-find-tags-with-parent (find-results parents)
- "Find in FIND-RESULTS all tags with PARENTS.
- NAME is the name of the tag needing finding.
- PARENTS is a list of names."
- (let ((ans nil) (usingnames nil))
-
- (semanticdb-find-result-mapc
- (lambda (tag db)
- (let* ((p (semantic-tag-named-parent tag))
- (ps (when (stringp p) (semantic-analyze-split-name p))))
- (when (stringp ps) (setq ps (list ps)))
- (when ps
-
- (if (equal ps parents)
- (push (list db tag) ans))
-
-
- (save-excursion
- (semantic-go-to-tag tag db)
- (setq usingnames nil)
- (let ((imports (semantic-ctxt-imported-packages)))
-
- (mapc (lambda (T)
- (setq usingnames
- (cons (semantic-format-tag-name-from-anything T) usingnames)))
- imports))
- (dolist (UN usingnames)
- (when (equal (cons UN ps) parents)
- (push (list db tag) ans)
- (setq usingnames (cdr usingnames))))
- ))))
- find-results)
- ans))
- (defun semantic--analyze-refs-full-lookup-with-parents (tag scope)
- "Perform a lookup for all occurrences of TAG based on TAG's SCOPE.
- TAG should be the tag currently under point."
- (let* ((classmatch (semantic-tag-class tag))
- (plist (mapcar (lambda (T) (semantic-tag-name T)) (oref scope parents)))
-
- (name (car plist))
-
- (simple (semantic--analyze-refs-full-lookup-simple tag t))
-
- (brute (semanticdb-find-tags-collector
- (lambda (table tags)
- (semanticdb-deep-find-tags-by-name-method table name tags)
- )
- nil nil t))
-
- (answer (semantic--analyze-refs-find-tags-with-parent simple plist))
- )
-
- (setq plist (cdr plist))
-
-
-
-
- (while (and plist brute)
-
- (let* ((direct (semantic--analyze-refs-find-child-in-find-results
- brute (semantic-tag-name tag) classmatch))
- (pdirect (semantic--analyze-refs-find-tags-with-parent
- direct plist)))
- (setq answer (append pdirect answer)))
-
- (setq brute (semantic--analyze-refs-find-child-in-find-results
- brute (car plist) 'type))
- (setq plist (cdr plist)))
-
- (let* ((direct (semantic--analyze-refs-find-child-in-find-results
- brute (semantic-tag-name tag) classmatch))
- )
- (setq answer (append direct answer)))
- answer))
- (defun semantic--analyze-refs-full-lookup-simple (tag &optional noerror)
- "Perform a simple lookup for occurrences of TAG in the current project.
- TAG should be the tag currently under point.
- Optional NOERROR means don't throw errors on failure to find something.
- This only compares the tag name, and does not infer any matches in namespaces,
- or parts of some other data structure.
- Only works for tags in the global namespace."
- (let* ((name (semantic-tag-name tag))
- (brute (semanticdb-find-tags-collector
- (lambda (table tags)
- (semanticdb-find-tags-by-name-method table name tags)
- )
- nil
- nil t))
- )
- (when (and (not brute) (not noerror))
-
- (error "Cannot find any references to %s in wide search" name))
- (let* ((classmatch (semantic-tag-class tag))
- (RES
- (semanticdb-find-tags-collector
- (lambda (table tags)
- (semantic-find-tags-by-class classmatch tags)
-
- )
- brute nil)))
- (when (and (not RES) (not noerror))
- (error "Cannot find any definitions for %s in wide search"
- (semantic-tag-name tag)))
-
- RES)))
- (defun semantic-analyze-current-tag ()
- "Analyze the tag under point."
- (interactive)
- (let* ((tag (semantic-current-tag))
- (start (current-time))
- (sac (semantic-analyze-tag-references tag))
- (end (current-time))
- )
- (message "Analysis took %.2f seconds." (semantic-elapsed-time start end))
- (if sac
- (progn
- (require 'eieio-datadebug)
- (data-debug-new-buffer "*Analyzer Reference ADEBUG*")
- (data-debug-insert-object-slots sac "]"))
- (message "No Context to analyze here."))))
- (defun semantic-analyze-proto-impl-toggle ()
- "Toggle between the implementation, and a prototype of tag under point."
- (interactive)
- (require 'semantic/decorate)
- (semantic-fetch-tags)
- (let* ((tag (semantic-current-tag))
- (sar (if tag
- (semantic-analyze-tag-references tag)
- (error "Point must be in a declaration")))
- (target (if (semantic-tag-prototype-p tag)
- (car (semantic-analyze-refs-impl sar t))
- (car (semantic-analyze-refs-proto sar t))))
- )
- (when (not target)
- (error "Could not find suitable %s"
- (if (semantic-tag-prototype-p tag) "implementation" "prototype")))
- (push-mark)
- (semantic-go-to-tag target)
- (switch-to-buffer (current-buffer))
- (semantic-momentary-highlight-tag target))
- )
- (provide 'semantic/analyze/refs)
|