1 ;;; semanticdb-search.el --- Searching through semantic databases.
3 ;;; Copyright (C) 2000, 2001, 2002, 2003, 2004 Eric M. Ludlam
5 ;; Author: Eric M. Ludlam <zappo@gnu.org>
7 ;; X-RCS: $Id: semanticdb-search.el,v 1.1 2007-11-26 15:10:47 michaels Exp $
9 ;; This file is not part of GNU Emacs.
11 ;; Semanticdb is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This software is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
28 ;; Databases of various forms can all be searched. These routines
29 ;; cover many common forms of searching.
31 ;; There are three types of searches that can be implemented:
34 ;; These searches allow searching on specific attributes of tags,
35 ;; such as name or type.
38 ;; These are searches that were needed to accomplish some tasks
39 ;; during in utilities. Advanced searches include matching methods
40 ;; defined outside some parent class.
42 ;; The reason for advanced searches are so that external
43 ;; repositories such as the Emacs obarray, or java .class files can
44 ;; quickly answer these needed questions without dumping the entire
45 ;; symbol list into Emacs for a regular semanticdb search.
48 ;; The generic search, `semanticdb-find-nonterminal-by-function'
49 ;; accepts a Emacs Lisp predicate that tests tags in Semantic
50 ;; format. Most external searches cannot perform this search.
53 (require 'semantic-find)
58 (defclass semanticdb-search-results-table (semanticdb-abstract-table)
61 "Table used for search results when there is no file or table association.
62 Examples include search results from external sources such as from
63 Emacs' own symbol table, or from external libraries.")
65 (defmethod semanticdb-refresh-table ((obj semanticdb-search-results-table))
66 "If the tag list associated with OBJ is loaded, refresh it.
67 This will call `semantic-fetch-tags' if that file is in memory."
70 (defmethod semanticdb-printable-name ((table semanticdb-search-results-table))
71 "Return a string which is a short and logical printable name for TABLE.
72 A search result may not have a file assocated with it, so we need to
73 provide a reasonable identification."
74 (concat "System: " (object-name-string table))
79 ;; Convenience routines for searches
80 (defun semanticdb-collect-find-results (result-in-databases
81 result-finding-function
84 "Collect results across RESULT-IN-DATABASES for RESULT-FINDING-FUNCTION.
85 If RESULT-IN-DATABASES is nil, search a range of associated databases
86 calculated by `semanticdb-current-database-list'.
87 RESULT-IN-DATABASES is a list of variable `semanticdb-project-database'
89 RESULT-FINDING-FUNCTION should accept one argument, the database being searched.
90 Argument IGNORE-SYSTEM specifies if any available system databases should
91 be ignored, or searched.
92 Argument FIND-FILE-ON-MATCH indicates that the found databases
93 should be capable of doing so."
94 (if (not (listp result-in-databases))
95 (signal 'wrong-type-argument (list 'listp result-in-databases)))
96 (let* ((semanticdb-search-system-databases
99 semanticdb-search-system-databases))
100 (dbs (or result-in-databases
101 ;; Calculate what database to use.
102 ;; Something simple and dumb for now.
103 (or (semanticdb-current-database-list)
104 (list (semanticdb-current-database)))))
105 (case-fold-search semantic-case-fold)
108 (if (or (not find-file-on-match)
109 (not (child-of-class-p
110 (oref db new-table-class)
111 semanticdb-search-results-table)))
112 (funcall result-finding-function db)))
115 ;; Flatten the list. The DB is unimportant at this stage.
116 (setq res (apply 'append res))
118 ;; Move across results, and throw out empties.
121 (setq out (cons (car res) out)))
122 (setq res (cdr res)))
126 ;;; Programatic interfaces
128 ;; These routines all perform different types of searches, and are
129 ;; interfaces to the database methods used to also perform those searches.
132 (defun semanticdb-find-nonterminal-by-token
133 (token &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
134 "Find all occurances of nonterminals with token TOKEN in databases.
135 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
136 SEARCH-PARTS, SEARCH-INCLUDES, DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
137 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
138 (semanticdb-collect-find-results
141 (semanticdb-find-nonterminal-by-token-method
142 db token search-parts search-includes diff-mode find-file-match))
145 (make-obsolete 'semanticdb-find-nonterminal-by-token
146 "Please don't use this function")
149 (defun semanticdb-find-nonterminal-by-name
150 (name &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
151 "Find all occurances of nonterminals with name NAME in databases.
152 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
153 SEARCH-PARTS, SEARCH-INCLUDES, DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
154 Return a list ((DB-TABLE . TOKEN) ...)."
155 (semanticdb-collect-find-results
158 (semanticdb-find-nonterminal-by-name-method
159 db name search-parts search-includes diff-mode find-file-match))
162 (make-obsolete 'semanticdb-find-nonterminal-by-name
163 "Please don't use this function")
166 (defun semanticdb-find-nonterminal-by-name-regexp
167 (regex &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
168 "Find all occurances of nonterminals with name matching REGEX in databases.
169 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
170 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
171 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
172 (semanticdb-collect-find-results
175 (semanticdb-find-nonterminal-by-name-regexp-method
176 db regex search-parts search-includes diff-mode find-file-match))
179 (make-obsolete 'semanticdb-find-nonterminal-by-name-regexp
180 "Please don't use this function")
184 (defun semanticdb-find-nonterminal-by-type
185 (type &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
186 "Find all nonterminals with a type of TYPE in databases.
187 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
188 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
189 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
190 (semanticdb-collect-find-results
193 (semanticdb-find-nonterminal-by-type-method
194 db type search-parts search-includes diff-mode find-file-match))
197 (make-obsolete 'semanticdb-find-nonterminal-by-type
198 "Please don't use this function")
202 (defun semanticdb-find-nonterminal-by-property
203 (property value &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
204 "Find all nonterminals with a PROPERTY equal to VALUE in databases.
205 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
206 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
207 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
208 (semanticdb-collect-find-results
211 (semanticdb-find-nonterminal-by-property-method
212 db property value search-parts search-includes diff-mode find-file-match))
215 (make-obsolete 'semanticdb-find-nonterminal-by-property
216 "Please don't use this function")
219 (defun semanticdb-find-nonterminal-by-extra-spec
220 (spec &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
221 "Find all nonterminals with a SPEC in databases.
222 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
223 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
224 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
225 (semanticdb-collect-find-results
228 (semanticdb-find-nonterminal-by-extra-spec-method
229 db spec search-parts search-includes diff-mode find-file-match))
232 (make-obsolete 'semanticdb-find-nonterminal-by-extra-spec
233 "Please don't use this function")
236 (defun semanticdb-find-nonterminal-by-extra-spec-value
237 (spec value &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
238 "Find all nonterminals with a SPEC equal to VALUE in databases.
239 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
240 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
241 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
242 (semanticdb-collect-find-results
245 (semanticdb-find-nonterminal-by-extra-spec-value-method
246 db spec value search-parts search-includes diff-mode find-file-match))
249 (make-obsolete 'semanticdb-find-nonterminal-by-extra-spec-value
250 "Please don't use this function")
252 ;;; Advanced Search Routines
254 (defun semanticdb-find-nonterminal-external-children-of-type
255 (type &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
256 "Find all nonterminals which are child elements of TYPE.
257 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
258 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
259 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
260 (semanticdb-collect-find-results
263 (semanticdb-find-nonterminal-external-children-of-type-method
264 db type search-parts search-includes diff-mode find-file-match))
268 ;;; Generic Search routine
272 (defun semanticdb-find-nonterminal-by-function
273 (function &optional databases search-parts search-includes diff-mode find-file-match ignore-system)
274 "Find all occurances of nonterminals which match FUNCTION.
275 Search in all DATABASES. If DATABASES is nil, search a range of
276 associated databases calculated `semanticdb-current-database-list' and
277 DATABASES is a list of variable `semanticdb-project-database' objects.
278 When SEARCH-PARTS is non-nil the search will include children of tags.
279 When SEARCH-INCLUDES is non-nil, the search will include dependency files.
280 When DIFF-MODE is non-nil, search databases which are of a different mode.
281 A Mode is the `major-mode' that file was in when it was last parsed.
282 When FIND-FILE-MATCH is non-nil, the make sure any found token's file is
284 When IGNORE-SYSTEM is non-nil, system libraries are not searched.
285 Return a list ((DB-TABLE . TOKEN-OR-TOKEN-LIST) ...)."
286 (semanticdb-collect-find-results
289 (semanticdb-find-nonterminal-by-function-method
290 db function search-parts search-includes diff-mode find-file-match))
296 ;; These are the base routines for searching semantic databases.
297 ;; Overload these with your subclasses to participate in the searching
299 (defmethod semanticdb-find-nonterminal-by-token-method
300 ((database semanticdb-project-database) token search-parts search-includes diff-mode find-file-match)
301 "In DB, find all occurances of nonterminals with token TOKEN in databases.
302 See `semanticdb-find-nonterminal-by-function-method' for details on,
303 SEARCH-PARTS, SEARCH-INCLUDES, DIFF-MODE, and FIND-FILE-MATCH.
304 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
305 (let ((goofy-token-name token))
306 (semanticdb-find-nonterminal-by-function-method
307 database (lambda (stream sp si)
308 (semantic-brute-find-tag-by-class goofy-token-name stream sp si))
309 search-parts search-includes diff-mode find-file-match)))
311 (defmethod semanticdb-find-nonterminal-by-name-method
312 ((database semanticdb-project-database) name search-parts search-includes diff-mode find-file-match)
313 "Find all occurances of nonterminals with name NAME in databases.
314 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
315 SEARCH-PARTS, SEARCH-INCLUDES, DIFF-MODE, and FIND-FILE-MATCH.
316 Return a list ((DB-TABLE . TOKEN) ...)."
317 (semanticdb-find-nonterminal-by-function-method
319 (lambda (stream sp si)
320 (semantic-brute-find-first-tag-by-name name stream sp si))
321 search-parts search-includes diff-mode find-file-match))
323 (defmethod semanticdb-find-nonterminal-by-name-regexp-method
324 ((database semanticdb-project-database) regex search-parts search-includes diff-mode find-file-match)
325 "Find all occurances of nonterminals with name matching REGEX in databases.
326 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
327 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, and FIND-FILE-MATCH.
328 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
329 (semanticdb-find-nonterminal-by-function-method
331 (lambda (stream sp si)
332 (semantic-brute-find-tag-by-name-regexp regex stream sp si))
333 search-parts search-includes diff-mode find-file-match))
335 (defmethod semanticdb-find-nonterminal-by-type-method
336 ((database semanticdb-project-database) type search-parts search-includes diff-mode find-file-match)
337 "Find all nonterminals with a type of TYPE in databases.
338 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
339 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, and FIND-FILE-MATCH.
340 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
341 (semanticdb-find-nonterminal-by-function-method
343 (lambda (stream sp si)
344 (semantic-brute-find-tag-by-type type stream sp si))
345 search-parts search-includes diff-mode find-file-match))
347 (defmethod semanticdb-find-nonterminal-by-property-method
348 ((database semanticdb-project-database) property value search-parts search-includes diff-mode find-file-match)
349 "Find all nonterminals with a PROPERTY equal to VALUE in databases.
350 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
351 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, and FIND-FILE-MATCH.
352 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
353 (semanticdb-find-nonterminal-by-function-method
355 (lambda (stream sp si)
356 (semantic-brute-find-tag-by-property property value stream sp si))
357 search-parts search-includes diff-mode find-file-match))
359 (defmethod semanticdb-find-nonterminal-by-extra-spec-method
360 ((database semanticdb-project-database) spec search-parts search-includes diff-mode find-file-match)
361 "Find all nonterminals with a SPEC in databases.
362 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
363 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, and FIND-FILE-MATCH.
364 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
365 (semanticdb-find-nonterminal-by-function-method
367 (lambda (stream sp si)
368 (semantic-brute-find-tag-by-attribute spec stream sp si))
369 search-parts search-includes diff-mode find-file-match))
371 (defmethod semanticdb-find-nonterminal-by-extra-spec-value-method
372 ((database semanticdb-project-database) spec value search-parts search-includes diff-mode find-file-match)
373 "Find all nonterminals with a SPEC equal to VALUE in databases.
374 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
375 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, and FIND-FILE-MATCH.
376 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
377 (semanticdb-find-nonterminal-by-function-method
379 (lambda (stream sp si)
380 (semantic-brute-find-tag-by-attribute-value spec value stream sp si))
381 search-parts search-includes diff-mode find-file-match))
383 ;;; Advanced Searches
385 (defmethod semanticdb-find-nonterminal-external-children-of-type-method
386 ((database semanticdb-project-database) type search-parts search-includes diff-mode find-file-match)
387 "Find all nonterminals which are child elements of TYPE
388 See `semanticdb-find-nonterminal-by-function' for details on DATABASES,
389 SEARCH-PARTS, SEARCH-INCLUDES DIFF-MODE, FIND-FILE-MATCH and IGNORE-SYSTEM.
390 Return a list ((DB-TABLE . TOKEN-LIST) ...)."
391 (semanticdb-find-nonterminal-by-function-method
393 `(lambda (stream sp si)
394 (semantic-brute-find-tag-by-function
396 (let ((p (semantic-nonterminal-external-member-parent tok)))
397 (and (stringp p) (string= ,type p)))
404 (defmethod semanticdb-find-nonterminal-by-function-method
405 ((database semanticdb-project-database)
406 function &optional search-parts search-includes diff-mode find-file-match)
407 "In DATABASE, find all occurances of nonterminals which match FUNCTION.
408 When SEARCH-PARTS is non-nil the search will include children of tags.
409 When SEARCH-INCLUDES is non-nil, the search will include dependency files.
410 When DIFF-MODE is non-nil, search databases which are of a different mode.
411 A mode is the `major-mode' that file was in when it was last parsed.
412 When FIND-FILE-MATCH is non-nil, the make sure any found token's file is
414 Return a list of matches."
416 (files (semanticdb-get-database-tables database))
418 (orig-buffer (current-buffer)))
421 (semanticdb-equivalent-mode (car files) orig-buffer))
422 ;; This can cause unneeded refreshes while typing with
423 ;; senator-eldoc mode.
424 ;;(semanticdb-refresh-table (car files))
425 (setq found (funcall function
426 (semanticdb-get-tags (car files))
432 ;; When something is found, make sure we read in that buffer if it
433 ;; had not already been loaded.
435 (save-excursion (semanticdb-set-buffer (car files))))
436 ;; In theory, the database is up-to-date with what is in the file, and
437 ;; these tags are ready to go.
438 ;; There is a bug lurking here I don't have time to fix.
439 (setq ret (cons (cons (car files) found) ret))
441 (setq files (cdr files)))
444 (provide 'semanticdb-search)
446 ;;; semanticdb-search.el ends here