diff options
author | Chong Yidong <cyd@stupidchicken.com> | 2009-09-28 15:15:00 +0000 |
---|---|---|
committer | Chong Yidong <cyd@stupidchicken.com> | 2009-09-28 15:15:00 +0000 |
commit | b90caf50d04d2c51742054bb6b0e836f6d425203 (patch) | |
tree | 945883cac64de9ceff0c8207c8b8ec2bc6c11932 /lisp/cedet/semantic/db-find.el | |
parent | 0e7b286792c2879dba8e1dd8b94a4a30293e20b3 (diff) | |
parent | a2095e2edba95e01f3be50ead7cc4b1c53bd40f3 (diff) | |
download | emacs-b90caf50d04d2c51742054bb6b0e836f6d425203.tar.gz |
CEDET (development tools) package merged.
* cedet/*.el:
* cedet/ede/*.el:
* cedet/semantic/*.el:
* cedet/srecode/*.el: New files.
Diffstat (limited to 'lisp/cedet/semantic/db-find.el')
-rw-r--r-- | lisp/cedet/semantic/db-find.el | 1373 |
1 files changed, 1373 insertions, 0 deletions
diff --git a/lisp/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el new file mode 100644 index 00000000000..e7ce7fcbdef --- /dev/null +++ b/lisp/cedet/semantic/db-find.el @@ -0,0 +1,1373 @@ +;;; semantic/db-find.el --- Searching through semantic databases. + +;;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +;;; 2008, 2009 Free Software Foundation, Inc. + +;; Author: Eric M. Ludlam <zappo@gnu.org> +;; Keywords: tags + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: +;; +;; Databases of various forms can all be searched. +;; There are a few types of searches that can be done: +;; +;; Basic Name Search: +;; These searches scan a database table collection for tags based +;; on name. +;; +;; Basic Attribute Search: +;; These searches allow searching on specific attributes of tags, +;; such as name, type, or other attribute. +;; +;; Advanced Search: +;; These are searches that were needed to accomplish some +;; specialized tasks as discovered in utilities. Advanced searches +;; include matching methods defined outside some parent class. +;; +;; The reason for advanced searches are so that external +;; repositories such as the Emacs obarray, or java .class files can +;; quickly answer these needed questions without dumping the entire +;; symbol list into Emacs for additional refinement searches via +;; regular semanticdb search. +;; +;; How databases are decided upon is another important aspect of a +;; database search. When it comes to searching for a name, there are +;; these types of searches: +;; +;; Basic Search: +;; Basic search means that tags looking for a given name start +;; with a specific search path. Names are sought on that path +;; until it is empty or items on the path can no longer be found. +;; Use `semanticdb-dump-all-table-summary' to test this list. +;; Use `semanticdb-find-throttle-custom-list' to refine this list. +;; +;; Deep Search: +;; A deep search will search more than just the global namespace. +;; It will recurse into tags that contain more tags, and search +;; those too. +;; +;; Brute Search: +;; Brute search means that all tables in all databases in a given +;; project are searched. Brute searches are the search style as +;; written for semantic version 1.x. +;; +;; How does the search path work? +;; +;; A basic search starts with three parameters: +;; +;; (FINDME &optional PATH FIND-FILE-MATCH) +;; +;; FINDME is key to be searched for dependent on the type of search. +;; PATH is an indicator of which tables are to be searched. +;; FIND-FILE-MATCH indicates that any time a match is found, the +;; file associated with the tag should be read into a file. +;; +;; The PATH argument is then the most interesting argument. It can +;; have these values: +;; +;; nil - Take the current buffer, and use it's include list +;; buffer - Use that buffer's include list. +;; filename - Use that file's include list. If the file is not +;; in a buffer, see of there is a semanticdb table for it. If +;; not, read that file into a buffer. +;; tag - Get that tag's buffer of file file. See above. +;; table - Search that table, and it's include list. +;; +;; Search Results: +;; +;; Semanticdb returns the results in a specific format. There are a +;; series of routines for using those results, and results can be +;; passed in as a search-path for refinement searches with +;; semanticdb. Apropos for semanticdb.*find-result for more. +;; +;; Application: +;; +;; Here are applications where different searches are needed which +;; exist as of semantic 1.4.x +;; +;; eldoc - popup help +;; => Requires basic search using default path. (Header files ok) +;; tag jump - jump to a named tag +;; => Requires a brute search useing whole project. (Source files only) +;; completion - Completing symbol names in a smart way +;; => Basic search (headers ok) +;; type analysis - finding type definitions for variables & fcns +;; => Basic search (headers ok) +;; Class browser - organize types into some structure +;; => Brute search, or custom navigation. + +;; TODO: +;; During a search, load any unloaded DB files based on paths in the +;; current project. + +(require 'semantic/db) +(require 'semantic/db-ref) +(eval-when-compile + (require 'semantic/find)) + +;;; Code: + +(defvar data-debug-thing-alist) +(declare-function data-debug-insert-stuff-list "data-debug") +(declare-function data-debug-insert-tag-list "data-debug") +(declare-function semantic-scope-reset-cache "semantic/scope") +(declare-function semanticdb-typecache-notify-reset "semantic/db-typecache") +(declare-function ede-current-project "ede") + +(defvar semanticdb-find-throttle-custom-list + '(repeat (radio (const 'local) + (const 'project) + (const 'unloaded) + (const 'system) + (const 'recursive) + (const 'omniscience))) + "Customization values for semanticdb find throttle. +See `semanticdb-find-throttle' for details.") + +;;;###autoload +(defcustom semanticdb-find-default-throttle + '(local project unloaded system recursive) + "The default throttle for `semanticdb-find' routines. +The throttle controls how detailed the list of database +tables is for a symbol lookup. The value is a list with +the following keys: + `file' - The file the search is being performed from. + This option is here for completeness only, and + is assumed to always be on. + `local' - Tables from the same local directory are included. + This includes files directly referenced by a file name + which might be in a different directory. + `project' - Tables from the same local project are included + If `project' is specified, then `local' is assumed. + `unloaded' - If a table is not in memory, load it. If it is not cached + on disk either, get the source, parse it, and create + the table. + `system' - Tables from system databases. These are specifically + tables from system header files, or language equivalent. + `recursive' - For include based searches, includes tables referenced + by included files. + `omniscience' - Included system databases which are omniscience, or + somehow know everything. Omniscience databases are found + in `semanticdb-project-system-databases'. + The Emacs Lisp system DB is an omniscience database." + :group 'semanticdb + :type semanticdb-find-throttle-custom-list) + +(defun semanticdb-find-throttle-active-p (access-type) + "Non-nil if ACCESS-TYPE is an active throttle type." + (or (memq access-type semanticdb-find-default-throttle) + (eq access-type 'file) + (and (eq access-type 'local) + (memq 'project semanticdb-find-default-throttle)) + )) + +;;; Index Class +;; +;; The find routines spend a lot of time looking stuff up. +;; Use this handy search index to cache data between searches. +;; This should allow searches to start running faster. +(defclass semanticdb-find-search-index (semanticdb-abstract-search-index) + ((include-path :initform nil + :documentation + "List of semanticdb tables from the include path.") + (type-cache :initform nil + :documentation + "Cache of all the data types accessible from this file. +Includes all types from all included files, merged namespaces, and +expunge duplicates.") + ) + "Concrete search index for `semanticdb-find'. +This class will cache data derived during various searches.") + +(defmethod semantic-reset ((idx semanticdb-find-search-index)) + "Reset the object IDX." + (require 'semantic/scope) + ;; Clear the include path. + (oset idx include-path nil) + (when (oref idx type-cache) + (semantic-reset (oref idx type-cache))) + ;; Clear the scope. Scope doesn't have the data it needs to track + ;; it's own reset. + (semantic-scope-reset-cache) + ) + +(defmethod semanticdb-synchronize ((idx semanticdb-find-search-index) + new-tags) + "Synchronize the search index IDX with some NEW-TAGS." + ;; Reset our parts. + (semantic-reset idx) + ;; Notify dependants by clearning their indicies. + (semanticdb-notify-references + (oref idx table) + (lambda (tab me) + (semantic-reset (semanticdb-get-table-index tab)))) + ) + +(defmethod semanticdb-partial-synchronize ((idx semanticdb-find-search-index) + new-tags) + "Synchronize the search index IDX with some changed NEW-TAGS." + ;; Only reset if include statements changed. + (if (semantic-find-tags-by-class 'include new-tags) + (progn + (semantic-reset idx) + ;; Notify dependants by clearning their indicies. + (semanticdb-notify-references + (oref idx table) + (lambda (tab me) + (semantic-reset (semanticdb-get-table-index tab)))) + ) + ;; Else, not an include, by just a type. + (when (oref idx type-cache) + (when (semanticdb-partial-synchronize (oref idx type-cache) new-tags) + ;; If the synchronize returns true, we need to notify. + ;; Notify dependants by clearning their indicies. + (semanticdb-notify-references + (oref idx table) + (lambda (tab me) + (let ((tab-idx (semanticdb-get-table-index tab))) + ;; Not a full reset? + (when (oref tab-idx type-cache) + (require 'db-typecache) + (semanticdb-typecache-notify-reset + (oref tab-idx type-cache))) + ))) + )) + )) + + +;;; Path Translations +;; +;;; OVERLOAD Functions +;; +;; These routines needed to be overloaded by specific language modes. +;; They are needed for translating an INCLUDE tag into a semanticdb +;; TABLE object. +;;;###autoload +(define-overloadable-function semanticdb-find-translate-path (path brutish) + "Translate PATH into a list of semantic tables. +Path translation involves identifying the PATH input argument +in one of the following ways: + nil - Take the current buffer, and use it's include list + buffer - Use that buffer's include list. + filename - Use that file's include list. If the file is not + in a buffer, see of there is a semanticdb table for it. If + not, read that file into a buffer. + tag - Get that tag's buffer of file file. See above. + table - Search that table, and it's include list. + find result - Search the results of a previous find. + +In addition, once the base path is found, there is the possibility of +each added table adding yet more tables to the path, so this routine +can return a lengthy list. + +If argument BRUTISH is non-nil, then instead of using the include +list, use all tables found in the parent project of the table +identified by translating PATH. Such searches use brute force to +scan every available table. + +The return value is a list of objects of type `semanticdb-table' or +it's children. In the case of passing in a find result, the result +is returned unchanged. + +This routine uses `semanticdb-find-table-for-include' to translate +specific include tags into a semanticdb table. + +Note: When searching using a non-brutish method, the list of +included files will be cached between runs. Database-references +are used to track which files need to have their include lists +refreshed when things change. See `semanticdb-ref-test'. + +Note for overloading: If you opt to overload this function for your +major mode, and your routine takes a long time, be sure to call + + (semantic-throw-on-input 'your-symbol-here) + +so that it can be called from the idle work handler." + ) + +(defun semanticdb-find-translate-path-default (path brutish) + "Translate PATH into a list of semantic tables. +If BRUTISH is non nil, return all tables associated with PATH. +Default action as described in `semanticdb-find-translate-path'." + (if (semanticdb-find-results-p path) + ;; nil means perform the search over these results. + nil + (if brutish + (semanticdb-find-translate-path-brutish-default path) + (semanticdb-find-translate-path-includes-default path)))) + +;;;###autoload +(define-overloadable-function semanticdb-find-table-for-include (includetag &optional table) + "For a single INCLUDETAG found in TABLE, find a `semanticdb-table' object +INCLUDETAG is a semantic TAG of class 'include. +TABLE is a semanticdb table that identifies where INCLUDETAG came from. +TABLE is optional if INCLUDETAG has an overlay of :filename attribute." + ) + +(defun semanticdb-find-translate-path-brutish-default (path) + "Translate PATH into a list of semantic tables. +Default action as described in `semanticdb-find-translate-path'." + (let ((basedb + (cond ((null path) semanticdb-current-database) + ((semanticdb-table-p path) (oref path parent-db)) + (t (let ((tt (semantic-something-to-tag-table path))) + (save-excursion + ;; @todo - What does this DO ??!?! + (set-buffer (semantic-tag-buffer (car tt))) + semanticdb-current-database)))))) + (apply + #'nconc + (mapcar + (lambda (db) + (let ((tabs (semanticdb-get-database-tables db)) + (ret nil)) + ;; Only return tables of the same language (major-mode) + ;; as the current search environment. + (while tabs + + (semantic-throw-on-input 'translate-path-brutish) + + (if (semanticdb-equivalent-mode-for-search (car tabs) + (current-buffer)) + (setq ret (cons (car tabs) ret))) + (setq tabs (cdr tabs))) + ret)) + ;; FIXME: + ;; This should scan the current project directory list for all + ;; semanticdb files, perhaps handling proxies for them. + (semanticdb-current-database-list + (if basedb (oref basedb reference-directory) + default-directory)))) + )) + +(defun semanticdb-find-incomplete-cache-entries-p (cache) + "Are there any incomplete entries in CACHE?" + (let ((ans nil)) + (dolist (tab cache) + (when (and (semanticdb-table-child-p tab) + (not (number-or-marker-p (oref tab pointmax)))) + (setq ans t)) + ) + ans)) + +(defun semanticdb-find-need-cache-update-p (table) + "Non nil if the semanticdb TABLE cache needs to be updated." + ;; If we were passed in something related to a TABLE, + ;; do a caching lookup. + (let* ((index (semanticdb-get-table-index table)) + (cache (when index (oref index include-path))) + (incom (semanticdb-find-incomplete-cache-entries-p cache)) + (unl (semanticdb-find-throttle-active-p 'unloaded)) + ) + (if (and + cache ;; Must have a cache + (or + ;; If all entries are "full", or if 'unloaded + ;; OR + ;; is not in the throttle, it is ok to use the cache. + (not incom) (not unl) + )) + nil + ;;cache + ;; ELSE + ;; + ;; We need an update. + t)) + ) + +(defun semanticdb-find-translate-path-includes-default (path) + "Translate PATH into a list of semantic tables. +Default action as described in `semanticdb-find-translate-path'." + (let ((table (cond ((null path) + semanticdb-current-table) + ((bufferp path) + (semantic-buffer-local-value 'semanticdb-current-table path)) + ((and (stringp path) (file-exists-p path)) + (semanticdb-file-table-object path t)) + ((semanticdb-abstract-table-child-p path) + path) + (t nil)))) + (if table + ;; If we were passed in something related to a TABLE, + ;; do a caching lookup. + (let ((index (semanticdb-get-table-index table))) + (if (semanticdb-find-need-cache-update-p table) + ;; Lets go look up our indicies + (let ((ans (semanticdb-find-translate-path-includes--internal path))) + (oset index include-path ans) + ;; Once we have our new indicies set up, notify those + ;; who depend on us if we found something for them to + ;; depend on. + (when ans (semanticdb-refresh-references table)) + ans) + ;; ELSE + ;; + ;; Just return the cache. + (oref index include-path))) + ;; If we were passed in something like a tag list, or other boring + ;; searchable item, then instead do the regular thing without caching. + (semanticdb-find-translate-path-includes--internal path)))) + +(defvar semanticdb-find-lost-includes nil + "Include files that we cannot find associated with this buffer.") +(make-variable-buffer-local 'semanticdb-find-lost-includes) + +(defvar semanticdb-find-scanned-include-tags nil + "All include tags scanned, plus action taken on the tag. +Each entry is an alist: + (ACTION . TAG) +where ACTION is one of 'scanned, 'duplicate, 'lost. +and TAG is a clone of the include tag that was found.") +(make-variable-buffer-local 'semanticdb-find-scanned-include-tags) + +(defvar semanticdb-implied-include-tags nil + "Include tags implied for all files of a given mode. +Set this variable with `defvar-mode-local' for a particular mode so +that any symbols that exist for all files for that mode are included. + +Note: This could be used as a way to write a file in a langauge +to declare all the built-ins for that language.") + +(defun semanticdb-find-translate-path-includes--internal (path) + "Internal implementation of `semanticdb-find-translate-path-includes-default'. +This routine does not depend on the cache, but will always derive +a new path from the provided PATH." + (let ((includetags nil) + (curtable nil) + (matchedtables (list semanticdb-current-table)) + (matchedincludes nil) + (lostincludes nil) + (scannedincludes nil) + (incfname nil) + nexttable) + (cond ((null path) + (semantic-refresh-tags-safe) + (setq includetags (append + (semantic-find-tags-included (current-buffer)) + semanticdb-implied-include-tags) + curtable semanticdb-current-table + incfname (buffer-file-name)) + ) + ((semanticdb-table-p path) + (setq includetags (semantic-find-tags-included path) + curtable path + incfname (semanticdb-full-filename path)) + ) + ((bufferp path) + (save-excursion + (set-buffer path) + (semantic-refresh-tags-safe)) + (setq includetags (semantic-find-tags-included path) + curtable (save-excursion (set-buffer path) + semanticdb-current-table) + incfname (buffer-file-name path))) + (t + (setq includetags (semantic-find-tags-included path)) + (when includetags + ;; If we have some tags, derive a table from them. + ;; else we will do nothing, so the table is useless. + + ;; @todo - derive some tables + (message "Need to derive tables for %S in translate-path-includes--default." + path) + ))) + + ;; Make sure each found include tag has an originating file name associated + ;; with it. + (when incfname + (dolist (it includetags) + (semantic--tag-put-property it :filename incfname))) + + ;; Loop over all include tags adding to matchedtables + (while includetags + (semantic-throw-on-input 'semantic-find-translate-path-includes-default) + + ;; If we've seen this include string before, lets skip it. + (if (member (semantic-tag-name (car includetags)) matchedincludes) + (progn + (setq nexttable nil) + (push (cons 'duplicate (semantic-tag-clone (car includetags))) + scannedincludes) + ) + (setq nexttable (semanticdb-find-table-for-include (car includetags) curtable)) + (when (not nexttable) + ;; Save the lost include. + (push (car includetags) lostincludes) + (push (cons 'lost (semantic-tag-clone (car includetags))) + scannedincludes) + ) + ) + + ;; Push the include file, so if we can't find it, we only + ;; can't find it once. + (push (semantic-tag-name (car includetags)) matchedincludes) + + ;; (message "Scanning %s" (semantic-tag-name (car includetags))) + (when (and nexttable + (not (memq nexttable matchedtables)) + (semanticdb-equivalent-mode-for-search nexttable + (current-buffer)) + ) + ;; Add to list of tables + (push nexttable matchedtables) + + ;; Queue new includes to list + (if (semanticdb-find-throttle-active-p 'recursive) + ;; @todo - recursive includes need to have the originating + ;; buffer's location added to the path. + (let ((newtags + (cond + ((semanticdb-table-p nexttable) + (semanticdb-refresh-table nexttable) + ;; Use the method directly, or we will recurse + ;; into ourselves here. + (semanticdb-find-tags-by-class-method + nexttable 'include)) + (t ;; @todo - is this ever possible??? + (message "semanticdb-ftp - how did you do that?") + (semantic-find-tags-included + (semanticdb-get-tags nexttable))) + )) + (newincfname (semanticdb-full-filename nexttable)) + ) + + (push (cons 'scanned (semantic-tag-clone (car includetags))) + scannedincludes) + + ;; Setup new tags so we know where they are. + (dolist (it newtags) + (semantic--tag-put-property it :filename + newincfname)) + + (setq includetags (nconc includetags newtags))) + ;; ELSE - not recursive throttle + (push (cons 'scanned-no-recurse + (semantic-tag-clone (car includetags))) + scannedincludes) + ) + ) + (setq includetags (cdr includetags))) + + (setq semanticdb-find-lost-includes lostincludes) + (setq semanticdb-find-scanned-include-tags (reverse scannedincludes)) + + ;; Find all the omniscient databases for this major mode, and + ;; add them if needed + (when (and (semanticdb-find-throttle-active-p 'omniscience) + semanticdb-search-system-databases) + ;; We can append any mode-specific omniscience databases into + ;; our search list here. + (let ((systemdb semanticdb-project-system-databases) + (ans nil)) + (while systemdb + (setq ans (semanticdb-file-table + (car systemdb) + ;; I would expect most omniscient to return the same + ;; thing reguardless of filename, but we may have + ;; one that can return a table of all things the + ;; current file needs. + (buffer-file-name (current-buffer)))) + (when (not (memq ans matchedtables)) + (setq matchedtables (cons ans matchedtables))) + (setq systemdb (cdr systemdb)))) + ) + (nreverse matchedtables))) + +(define-overloadable-function semanticdb-find-load-unloaded (filename) + "Create a database table for FILENAME if it hasn't been parsed yet. +Assumes that FILENAME exists as a source file. +Assumes that a preexisting table does not exist, even if it +isn't in memory yet." + (if (semanticdb-find-throttle-active-p 'unloaded) + (:override) + (semanticdb-file-table-object filename t))) + +(defun semanticdb-find-load-unloaded-default (filename) + "Load an unloaded file in FILENAME using the default semanticdb loader." + (semanticdb-file-table-object filename)) + +;; The creation of the overload occurs above. +(defun semanticdb-find-table-for-include-default (includetag &optional table) + "Default implementation of `semanticdb-find-table-for-include'. +Uses `semanticdb-current-database-list' as the search path. +INCLUDETAG and TABLE are documented in `semanticdb-find-table-for-include'. +Included databases are filtered based on `semanticdb-find-default-throttle'." + (if (not (eq (semantic-tag-class includetag) 'include)) + (signal 'wrong-type-argument (list includetag 'include))) + + (let ((name + ;; Note, some languages (like Emacs or Java) use include tag names + ;; that don't represent files! We want to have file names. + (semantic-tag-include-filename includetag)) + (originfiledir nil) + (roots nil) + (tmp nil) + (ans nil)) + + ;; INCLUDETAG should have some way to reference where it came + ;; from! If not, TABLE should provide the way. Each time we + ;; look up a tag, we may need to find it in some relative way + ;; and must set our current buffer eto the origin of includetag + ;; or nothing may work. + (setq originfiledir + (cond ((semantic-tag-file-name includetag) + ;; A tag may have a buffer, or a :filename property. + (file-name-directory (semantic-tag-file-name includetag))) + (table + (file-name-directory (semanticdb-full-filename table))) + (t + ;; @todo - what to do here? Throw an error maybe + ;; and fix usage bugs? + default-directory))) + + (cond + ;; Step 1: Relative path name + ;; + ;; If the name is relative, then it should be findable as relative + ;; to the source file that this tag originated in, and be fast. + ;; + ((and (semanticdb-find-throttle-active-p 'local) + (file-exists-p (expand-file-name name originfiledir))) + + (setq ans (semanticdb-find-load-unloaded + (expand-file-name name originfiledir))) + ) + ;; Step 2: System or Project level includes + ;; + ((or + ;; First, if it a system include, we can investigate that tags + ;; dependency file + (and (semanticdb-find-throttle-active-p 'system) + + ;; Sadly, not all languages make this distinction. + ;;(semantic-tag-include-system-p includetag) + + ;; Here, we get local and system files. + (setq tmp (semantic-dependency-tag-file includetag)) + ) + ;; Second, project files are active, we and we have EDE, + ;; we can find it using the same tool. + (and (semanticdb-find-throttle-active-p 'project) + ;; Make sure EDE is available, and we have a project + (featurep 'ede) (ede-current-project originfiledir) + ;; The EDE query is hidden in this call. + (setq tmp (semantic-dependency-tag-file includetag)) + ) + ) + (setq ans (semanticdb-find-load-unloaded tmp)) + ) + ;; Somewhere in our project hierarchy + ;; + ;; Remember: Roots includes system databases which can create + ;; specialized tables we can search. + ;; + ;; NOTE: Not used if EDE is active! + ((and (semanticdb-find-throttle-active-p 'project) + ;; And dont do this if it is a system include. Not supported by all languages, + ;; but when it is, this is a nice fast way to skip this step. + (not (semantic-tag-include-system-p includetag)) + ;; Don't do this if we have an EDE project. + (not (and (featurep 'ede) + ;; Note: We don't use originfiledir here because + ;; we want to know about the source file we are + ;; starting from. + (ede-current-project))) + ) + + (setq roots (semanticdb-current-database-list)) + + (while (and (not ans) roots) + (let* ((ref (if (slot-boundp (car roots) 'reference-directory) + (oref (car roots) reference-directory))) + (fname (cond ((null ref) nil) + ((file-exists-p (expand-file-name name ref)) + (expand-file-name name ref)) + ((file-exists-p (expand-file-name (file-name-nondirectory name) ref)) + (expand-file-name (file-name-nondirectory name) ref))))) + (when (and ref fname) + ;; There is an actual file. Grab it. + (setq ans (semanticdb-find-load-unloaded fname))) + + ;; ELSE + ;; + ;; NOTE: We used to look up omniscient databases here, but that + ;; is now handled one layer up. + ;; + ;; Missing: a database that knows where missing files are. Hmm. + ;; perhaps I need an override function for that? + + ) + + (setq roots (cdr roots)))) + ) + ans)) + + +;;; Perform interactive tests on the path/search mechanisms. +;; +;;;###autoload +(defun semanticdb-find-test-translate-path (&optional arg) + "Call and output results of `semanticdb-find-translate-path'. +With ARG non-nil, specify a BRUTISH translation. +See `semanticdb-find-default-throttle' and `semanticdb-project-roots' +for details on how this list is derived." + (interactive "P") + (semantic-fetch-tags) + (require 'data-debug) + (let ((start (current-time)) + (p (semanticdb-find-translate-path nil arg)) + (end (current-time)) + ) + (data-debug-new-buffer "*SEMANTICDB FTP ADEBUG*") + (message "Search of tags took %.2f seconds." + (semantic-elapsed-time start end)) + + (data-debug-insert-stuff-list p "*"))) + +(defun semanticdb-find-test-translate-path-no-loading (&optional arg) + "Call and output results of `semanticdb-find-translate-path'. +With ARG non-nil, specify a BRUTISH translation. +See `semanticdb-find-default-throttle' and `semanticdb-project-roots' +for details on how this list is derived." + (interactive "P") + (semantic-fetch-tags) + (require 'data-debug) + (let* ((semanticdb-find-default-throttle + (if (featurep 'semantic/db-find) + (remq 'unloaded semanticdb-find-default-throttle) + nil)) + (start (current-time)) + (p (semanticdb-find-translate-path nil arg)) + (end (current-time)) + ) + (data-debug-new-buffer "*SEMANTICDB FTP ADEBUG*") + (message "Search of tags took %.2f seconds." + (semantic-elapsed-time start end)) + + (data-debug-insert-stuff-list p "*"))) + +;;;###autoload +(defun semanticdb-find-adebug-lost-includes () + "Translate the current path, then display the lost includes. +Examines the variable `semanticdb-find-lost-includes'." + (interactive) + (require 'data-debug) + (semanticdb-find-translate-path nil nil) + (let ((lost semanticdb-find-lost-includes) + ) + + (if (not lost) + (message "There are no unknown includes for %s" + (buffer-name)) + + (data-debug-new-buffer "*SEMANTICDB lost-includes ADEBUG*") + (data-debug-insert-tag-list lost "*") + ))) + +(defun semanticdb-find-adebug-insert-scanned-tag-cons (consdata prefix prebuttontext) + "Insert a button representing scanned include CONSDATA. +PREFIX is the text that preceeds the button. +PREBUTTONTEXT is some text between prefix and the overlay button." + (let* ((start (point)) + (end nil) + (mode (car consdata)) + (tag (cdr consdata)) + (name (semantic-tag-name tag)) + (file (semantic-tag-file-name tag)) + (str1 (format "%S %s" mode name)) + (str2 (format " : %s" file)) + (tip nil)) + (insert prefix prebuttontext str1) + (setq end (point)) + (insert str2) + (put-text-property start end 'face + (cond ((eq mode 'scanned) + 'font-lock-function-name-face) + ((eq mode 'duplicate) + 'font-lock-comment-face) + ((eq mode 'lost) + 'font-lock-variable-name-face) + ((eq mode 'scanned-no-recurse) + 'font-lock-type-face))) + (put-text-property start end 'ddebug (cdr consdata)) + (put-text-property start end 'ddebug-indent(length prefix)) + (put-text-property start end 'ddebug-prefix prefix) + (put-text-property start end 'help-echo tip) + (put-text-property start end 'ddebug-function + 'data-debug-insert-tag-parts-from-point) + (insert "\n") + ) + ) + +(defun semanticdb-find-adebug-scanned-includes () + "Translate the current path, then display the lost includes. +Examines the variable `semanticdb-find-lost-includes'." + (interactive) + (require 'data-debug) + (semanticdb-find-translate-path nil nil) + (let ((scanned semanticdb-find-scanned-include-tags) + (data-debug-thing-alist + (cons + '((lambda (thing) (and (consp thing) + (symbolp (car thing)) + (memq (car thing) + '(scanned scanned-no-recurse + lost duplicate)))) + . semanticdb-find-adebug-insert-scanned-tag-cons) + data-debug-thing-alist)) + ) + + (if (not scanned) + (message "There are no includes scanned %s" + (buffer-name)) + + (data-debug-new-buffer "*SEMANTICDB scanned-includes ADEBUG*") + (data-debug-insert-stuff-list scanned "*") + ))) + +;;; API Functions +;; +;; Once you have a search result, use these routines to operate +;; on the search results at a higher level + +;;;###autoload +(defun semanticdb-strip-find-results (results &optional find-file-match) + "Strip a semanticdb search RESULTS to exclude objects. +This makes it appear more like the results of a `semantic-find-' call. +Optional FIND-FILE-MATCH loads all files associated with RESULTS +into buffers. This has the side effect of enabling `semantic-tag-buffer' to +return a value. +If FIND-FILE-MATCH is 'name, then only the filename is stored +in each tag instead of loading each file into a buffer. +If the input RESULTS are not going to be used again, and if +FIND-FILE-MATCH is nil, you can use `semanticdb-fast-strip-find-results' +instead." + (if find-file-match + ;; Load all files associated with RESULTS. + (let ((tmp results) + (output nil)) + (while tmp + (let ((tab (car (car tmp))) + (tags (cdr (car tmp)))) + (dolist (T tags) + ;; Normilzation gives specialty database tables a chance + ;; to convert into a more stable tag format. + (let* ((norm (semanticdb-normalize-one-tag tab T)) + (ntab (car norm)) + (ntag (cdr norm)) + (nametable ntab)) + + ;; If it didn't normalize, use what we had. + (if (not norm) + (setq nametable tab) + (setq output (append output (list ntag)))) + + ;; Find-file-match allows a tool to make sure the tag is + ;; 'live', somewhere in a buffer. + (cond ((eq find-file-match 'name) + (let ((f (semanticdb-full-filename nametable))) + (semantic--tag-put-property ntag :filename f))) + ((and find-file-match ntab) + (semanticdb-get-buffer ntab)) + ) + )) + ) + (setq tmp (cdr tmp))) + output) + ;; @todo - I could use nconc, but I don't know what the caller may do with + ;; RESULTS after this is called. Right now semantic-complete will + ;; recycling the input after calling this routine. + (apply #'append (mapcar #'cdr results)))) + +(defun semanticdb-fast-strip-find-results (results) + "Destructively strip a semanticdb search RESULTS to exclude objects. +This makes it appear more like the results of a `semantic-find-' call. +This is like `semanticdb-strip-find-results', except the input list RESULTS +will be changed." + (apply #'nconc (mapcar #'cdr results))) + +(defun semanticdb-find-results-p (resultp) + "Non-nil if RESULTP is in the form of a semanticdb search result. +This query only really tests the first entry in the list that is RESULTP, +but should be good enough for debugging assertions." + (and (listp resultp) + (listp (car resultp)) + (semanticdb-abstract-table-child-p (car (car resultp))) + (or (semantic-tag-p (car (cdr (car resultp)))) + (null (car (cdr (car resultp))))))) + +(defun semanticdb-find-result-prin1-to-string (result) + "Presuming RESULT satisfies `semanticdb-find-results-p', provide a short PRIN1 output." + (if (< (length result) 2) + (concat "#<FIND RESULT " + (mapconcat (lambda (a) + (concat "(" (object-name (car a) ) " . " + "#<TAG LIST " (number-to-string (length (cdr a))) ">)")) + result + " ") + ">") + ;; Longer results should have an abreviated form. + (format "#<FIND RESULT %d TAGS in %d FILES>" + (semanticdb-find-result-length result) + (length result)))) + +(defun semanticdb-find-result-with-nil-p (resultp) + "Non-nil of RESULTP is in the form of a semanticdb search result. +nil is a valid value where a TABLE usually is, but only if the TAG +results include overlays. +This query only really tests the first entry in the list that is RESULTP, +but should be good enough for debugging assertions." + (and (listp resultp) + (listp (car resultp)) + (let ((tag-to-test (car-safe (cdr (car resultp))))) + (or (and (semanticdb-abstract-table-child-p (car (car resultp))) + (or (semantic-tag-p tag-to-test) + (null tag-to-test))) + (and (null (car (car resultp))) + (or (semantic-tag-with-position-p tag-to-test) + (null tag-to-test)))) + ))) + +;;;###autoload +(defun semanticdb-find-result-length (result) + "Number of tags found in RESULT." + (let ((count 0)) + (mapc (lambda (onetable) + (setq count (+ count (1- (length onetable))))) + result) + count)) + +;;;###autoload +(defun semanticdb-find-result-nth (result n) + "In RESULT, return the Nth search result. +This is a 0 based search result, with the first match being element 0. + +The returned value is a cons cell: (TAG . TABLE) where TAG +is the tag at the Nth position. TABLE is the semanticdb table where +the TAG was found. Sometimes TABLE can be nil." + (let ((ans nil) + (anstable nil)) + ;; Loop over each single table hit. + (while (and (not ans) result) + ;; For each table result, get local length, and modify + ;; N to be that much less. + (let ((ll (length (cdr (car result))))) ;; local length + (if (> ll n) + ;; We have a local match. + (setq ans (nth n (cdr (car result))) + anstable (car (car result))) + ;; More to go. Decrement N. + (setq n (- n ll)))) + ;; Keep moving. + (setq result (cdr result))) + (cons ans anstable))) + +(defun semanticdb-find-result-test (result) + "Test RESULT by accessing all the tags in the list." + (if (not (semanticdb-find-results-p result)) + (error "Does not pass `semanticdb-find-results-p.\n")) + (let ((len (semanticdb-find-result-length result)) + (i 0)) + (while (< i len) + (let ((tag (semanticdb-find-result-nth result i))) + (if (not (semantic-tag-p (car tag))) + (error "%d entry is not a tag" i))) + (setq i (1+ i))))) + +;;;###autoload +(defun semanticdb-find-result-nth-in-buffer (result n) + "In RESULT, return the Nth search result. +Like `semanticdb-find-result-nth', except that only the TAG +is returned, and the buffer it is found it will be made current. +If the result tag has no position information, the originating buffer +is still made current." + (let* ((ret (semanticdb-find-result-nth result n)) + (ans (car ret)) + (anstable (cdr ret))) + ;; If we have a hit, double-check the find-file + ;; entry. If the file must be loaded, then gat that table's + ;; source file into a buffer. + + (if anstable + (let ((norm (semanticdb-normalize-one-tag anstable ans))) + (when norm + ;; The normalized tags can now be found based on that + ;; tags table. + (semanticdb-set-buffer (car norm)) + ;; Now reset ans + (setq ans (cdr norm)) + )) + ) + ;; Return the tag. + ans)) + +(defun semanticdb-find-result-mapc (fcn result) + "Apply FCN to each element of find RESULT for side-effects only. +FCN takes two arguments. The first is a TAG, and the +second is a DB from wence TAG originated. +Returns result." + (mapc (lambda (sublst) + (mapc (lambda (tag) + (funcall fcn tag (car sublst))) + (cdr sublst))) + result) + result) + +;;; Search Logging +;; +;; Basic logging to see what the search routines are doing. +(defvar semanticdb-find-log-flag nil + "Non-nil means log the process of searches.") + +(defvar semanticdb-find-log-buffer-name "*SemanticDB Find Log*" + "The name of the logging buffer.") + +(defun semanticdb-find-toggle-logging () + "Toggle sematnicdb logging." + (interactive) + (setq semanticdb-find-log-flag (null semanticdb-find-log-flag)) + (message "Semanticdb find logging is %sabled" + (if semanticdb-find-log-flag "en" "dis"))) + +(defun semanticdb-reset-log () + "Reset the log buffer." + (interactive) + (when semanticdb-find-log-flag + (save-excursion + (set-buffer (get-buffer-create semanticdb-find-log-buffer-name)) + (erase-buffer) + ))) + +(defun semanticdb-find-log-move-to-end () + "Move to the end of the semantic log." + (let ((cb (current-buffer)) + (cw (selected-window))) + (unwind-protect + (progn + (set-buffer semanticdb-find-log-buffer-name) + (if (get-buffer-window (current-buffer) 'visible) + (select-window (get-buffer-window (current-buffer) 'visible))) + (goto-char (point-max))) + (if cw (select-window cw)) + (set-buffer cb)))) + +(defun semanticdb-find-log-new-search (forwhat) + "Start a new search FORWHAT." + (when semanticdb-find-log-flag + (save-excursion + (set-buffer (get-buffer-create semanticdb-find-log-buffer-name)) + (insert (format "New Search: %S\n" forwhat)) + ) + (semanticdb-find-log-move-to-end))) + +(defun semanticdb-find-log-activity (table result) + "Log that TABLE has been searched and RESULT was found." + (when semanticdb-find-log-flag + (save-excursion + (set-buffer semanticdb-find-log-buffer-name) + (insert "Table: " (object-print table) + " Result: " (int-to-string (length result)) " tags" + "\n") + ) + (semanticdb-find-log-move-to-end))) + +;;; Semanticdb find API functions +;; These are the routines actually used to perform searches. +;; +(defun semanticdb-find-tags-collector (function &optional path find-file-match + brutish) + "Collect all tags returned by FUNCTION over PATH. +The FUNCTION must take two arguments. The first is TABLE, +which is a semanticdb table containing tags. The second argument +to FUNCTION is TAGS. TAGS may be a list of tags. If TAGS is non-nil, then +FUNCTION should search the TAG list, not through TABLE. + +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer. + +Note: You should leave FIND-FILE-MATCH as nil. It is far more +efficient to take the results from any search and use +`semanticdb-strip-find-results' instead. This argument is here +for backward compatibility. + +If optional argument BRUTISH is non-nil, then ignore include statements, +and search all tables in this project tree." + (let (found match) + (save-excursion + ;; If path is a buffer, set ourselves up in that buffer + ;; so that the override methods work correctly. + (when (bufferp path) (set-buffer path)) + (if (semanticdb-find-results-p path) + ;; When we get find results, loop over that. + (dolist (tableandtags path) + (semantic-throw-on-input 'semantic-find-translate-path) + ;; If FIND-FILE-MATCH is non-nil, skip tables of class + ;; `semanticdb-search-results-table', since those are system + ;; databases and not associated with a file. + (unless (and find-file-match + (obj-of-class-p + (car tableandtags) semanticdb-search-results-table)) + (when (setq match (funcall function + (car tableandtags) (cdr tableandtags))) + (when find-file-match + (save-excursion (semanticdb-set-buffer (car tableandtags)))) + (push (cons (car tableandtags) match) found))) + ) + ;; Only log searches across data bases. + (semanticdb-find-log-new-search nil) + ;; If we get something else, scan the list of tables resulting + ;; from translating it into a list of objects. + (dolist (table (semanticdb-find-translate-path path brutish)) + (semantic-throw-on-input 'semantic-find-translate-path) + ;; If FIND-FILE-MATCH is non-nil, skip tables of class + ;; `semanticdb-search-results-table', since those are system + ;; databases and not associated with a file. + (unless (and find-file-match + (obj-of-class-p table semanticdb-search-results-table)) + (when (and table (setq match (funcall function table nil))) + (semanticdb-find-log-activity table match) + (when find-file-match + (save-excursion (semanticdb-set-buffer table))) + (push (cons table match) found)))))) + ;; At this point, FOUND has had items pushed onto it. + ;; This means items are being returned in REVERSE order + ;; of the tables searched, so if you just get th CAR, then + ;; too-bad, you may have some system-tag that has no + ;; buffer associated with it. + + ;; It must be reversed. + (nreverse found))) + +;;;###autoload +(defun semanticdb-find-tags-by-name (name &optional path find-file-match) + "Search for all tags matching NAME on PATH. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-by-name-method table name tags)) + path find-file-match)) + +;;;###autoload +(defun semanticdb-find-tags-by-name-regexp (regexp &optional path find-file-match) + "Search for all tags matching REGEXP on PATH. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-by-name-regexp-method table regexp tags)) + path find-file-match)) + +;;;###autoload +(defun semanticdb-find-tags-for-completion (prefix &optional path find-file-match) + "Search for all tags matching PREFIX on PATH. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-for-completion-method table prefix tags)) + path find-file-match)) + +;;;###autoload +(defun semanticdb-find-tags-by-class (class &optional path find-file-match) + "Search for all tags of CLASS on PATH. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-by-class-method table class tags)) + path find-file-match)) + +;;; Deep Searches +(defun semanticdb-deep-find-tags-by-name (name &optional path find-file-match) + "Search for all tags matching NAME on PATH. +Search also in all components of top level tags founds. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-deep-find-tags-by-name-method table name tags)) + path find-file-match)) + +(defun semanticdb-deep-find-tags-by-name-regexp (regexp &optional path find-file-match) + "Search for all tags matching REGEXP on PATH. +Search also in all components of top level tags founds. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-deep-find-tags-by-name-regexp-method table regexp tags)) + path find-file-match)) + +(defun semanticdb-deep-find-tags-for-completion (prefix &optional path find-file-match) + "Search for all tags matching PREFIX on PATH. +Search also in all components of top level tags founds. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-deep-find-tags-for-completion-method table prefix tags)) + path find-file-match)) + +;;; Brutish Search Routines +;; +(defun semanticdb-brute-deep-find-tags-by-name (name &optional path find-file-match) + "Search for all tags matching NAME on PATH. +See `semanticdb-find-translate-path' for details on PATH. +The argument BRUTISH will be set so that searching includes all tables +in the current project. +FIND-FILE-MATCH indicates that any time a matchi is found, the file +associated wit that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-deep-find-tags-by-name-method table name tags)) + path find-file-match t)) + +(defun semanticdb-brute-deep-find-tags-for-completion (prefix &optional path find-file-match) + "Search for all tags matching PREFIX on PATH. +See `semanticdb-find-translate-path' for details on PATH. +The argument BRUTISH will be set so that searching includes all tables +in the current project. +FIND-FILE-MATCH indicates that any time a matchi is found, the file +associated wit that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-deep-find-tags-for-completion-method table prefix tags)) + path find-file-match t)) + +(defun semanticdb-brute-find-tags-by-class (class &optional path find-file-match) + "Search for all tags of CLASS on PATH. +See `semanticdb-find-translate-path' for details on PATH. +The argument BRUTISH will be set so that searching includes all tables +in the current project. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-by-class-method table class tags)) + path find-file-match t)) + +;;; Specialty Search Routines +(defun semanticdb-find-tags-external-children-of-type + (type &optional path find-file-match) + "Search for all tags defined outside of TYPE w/ TYPE as a parent. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-external-children-of-type-method table type tags)) + path find-file-match)) + +(defun semanticdb-find-tags-subclasses-of-type + (type &optional path find-file-match) + "Search for all tags of class type defined that subclass TYPE. +See `semanticdb-find-translate-path' for details on PATH. +FIND-FILE-MATCH indicates that any time a match is found, the file +associated with that tag should be loaded into a buffer." + (semanticdb-find-tags-collector + (lambda (table tags) + (semanticdb-find-tags-subclasses-of-type-method table type tags)) + path find-file-match t)) + +;;; METHODS +;; +;; Default methods for semanticdb database and table objects. +;; Override these with system databases to as new types of back ends. + +;;; Top level Searches +(defmethod semanticdb-find-tags-by-name-method ((table semanticdb-abstract-table) name &optional tags) + "In TABLE, find all occurances of tags with NAME. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (semantic-find-tags-by-name name (or tags (semanticdb-get-tags table)))) + +(defmethod semanticdb-find-tags-by-name-regexp-method ((table semanticdb-abstract-table) regexp &optional tags) + "In TABLE, find all occurances of tags matching REGEXP. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (semantic-find-tags-by-name-regexp regexp (or tags (semanticdb-get-tags table)))) + +(defmethod semanticdb-find-tags-for-completion-method ((table semanticdb-abstract-table) prefix &optional tags) + "In TABLE, find all occurances of tags matching PREFIX. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (semantic-find-tags-for-completion prefix (or tags (semanticdb-get-tags table)))) + +(defmethod semanticdb-find-tags-by-class-method ((table semanticdb-abstract-table) class &optional tags) + "In TABLE, find all occurances of tags of CLASS. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table)))) + +(defmethod semanticdb-find-tags-external-children-of-type-method ((table semanticdb-abstract-table) parent &optional tags) + "In TABLE, find all occurances of tags whose parent is the PARENT type. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (require 'semantic/find) + (semantic-find-tags-external-children-of-type parent (or tags (semanticdb-get-tags table)))) + +(defmethod semanticdb-find-tags-subclasses-of-type-method ((table semanticdb-abstract-table) parent &optional tags) + "In TABLE, find all occurances of tags whose parent is the PARENT type. +Optional argument TAGS is a list of tags to search. +Returns a table of all matching tags." + (require 'semantic/find) + (semantic-find-tags-subclasses-of-type parent (or tags (semanticdb-get-tags table)))) + +;;; Deep Searches +(defmethod semanticdb-deep-find-tags-by-name-method ((table semanticdb-abstract-table) name &optional tags) + "In TABLE, find all occurances of tags with NAME. +Search in all tags in TABLE, and all components of top level tags in +TABLE. +Optional argument TAGS is a list of tags to search. +Return a table of all matching tags." + (semantic-find-tags-by-name name (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) + +(defmethod semanticdb-deep-find-tags-by-name-regexp-method ((table semanticdb-abstract-table) regexp &optional tags) + "In TABLE, find all occurances of tags matching REGEXP. +Search in all tags in TABLE, and all components of top level tags in +TABLE. +Optional argument TAGS is a list of tags to search. +Return a table of all matching tags." + (semantic-find-tags-by-name-regexp regexp (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) + +(defmethod semanticdb-deep-find-tags-for-completion-method ((table semanticdb-abstract-table) prefix &optional tags) + "In TABLE, find all occurances of tags matching PREFIX. +Search in all tags in TABLE, and all components of top level tags in +TABLE. +Optional argument TAGS is a list of tags to search. +Return a table of all matching tags." + (semantic-find-tags-for-completion prefix (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) + +(provide 'semantic/db-find) + +;; Local variables: +;; generated-autoload-file: "loaddefs.el" +;; generated-autoload-feature: semantic/loaddefs +;; generated-autoload-load-name: "semantic/db-find" +;; End: + +;;; semantic/db-find.el ends here |