Mercurial > emacs
comparison lisp/cedet/semantic/db-find.el @ 104417:6810f0d84270
cedet/semantic/ctxt.el, cedet/semantic/db-find.el,
cedet/semantic/db-ref.el, cedet/semantic/find.el,
cedet/semantic/format.el, cedet/semantic/sort.el: New files.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Fri, 28 Aug 2009 19:18:35 +0000 |
parents | |
children | da5b2513c225 |
comparison
equal
deleted
inserted
replaced
104416:c13af98da4d6 | 104417:6810f0d84270 |
---|---|
1 ;;; db-find.el --- Searching through semantic databases. | |
2 | |
3 ;;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, | |
4 ;;; 2008, 2009 Free Software Foundation, Inc. | |
5 | |
6 ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
7 ;; Keywords: tags | |
8 | |
9 ;; This file is part of GNU Emacs. | |
10 | |
11 ;; GNU Emacs 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 3 of the License, or | |
14 ;; (at your option) any later version. | |
15 | |
16 ;; GNU Emacs 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. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
23 | |
24 ;;; Commentary: | |
25 ;; | |
26 ;; Databases of various forms can all be searched. | |
27 ;; There are a few types of searches that can be done: | |
28 ;; | |
29 ;; Basic Name Search: | |
30 ;; These searches scan a database table collection for tags based | |
31 ;; on name. | |
32 ;; | |
33 ;; Basic Attribute Search: | |
34 ;; These searches allow searching on specific attributes of tags, | |
35 ;; such as name, type, or other attribute. | |
36 ;; | |
37 ;; Advanced Search: | |
38 ;; These are searches that were needed to accomplish some | |
39 ;; specialized tasks as discovered in utilities. Advanced searches | |
40 ;; include matching methods defined outside some parent class. | |
41 ;; | |
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 additional refinement searches via | |
46 ;; regular semanticdb search. | |
47 ;; | |
48 ;; How databases are decided upon is another important aspect of a | |
49 ;; database search. When it comes to searching for a name, there are | |
50 ;; these types of searches: | |
51 ;; | |
52 ;; Basic Search: | |
53 ;; Basic search means that tags looking for a given name start | |
54 ;; with a specific search path. Names are sought on that path | |
55 ;; until it is empty or items on the path can no longer be found. | |
56 ;; Use `semanticdb-dump-all-table-summary' to test this list. | |
57 ;; Use `semanticdb-find-throttle-custom-list' to refine this list. | |
58 ;; | |
59 ;; Deep Search: | |
60 ;; A deep search will search more than just the global namespace. | |
61 ;; It will recurse into tags that contain more tags, and search | |
62 ;; those too. | |
63 ;; | |
64 ;; Brute Search: | |
65 ;; Brute search means that all tables in all databases in a given | |
66 ;; project are searched. Brute searches are the search style as | |
67 ;; written for semantic version 1.x. | |
68 ;; | |
69 ;; How does the search path work? | |
70 ;; | |
71 ;; A basic search starts with three parameters: | |
72 ;; | |
73 ;; (FINDME &optional PATH FIND-FILE-MATCH) | |
74 ;; | |
75 ;; FINDME is key to be searched for dependent on the type of search. | |
76 ;; PATH is an indicator of which tables are to be searched. | |
77 ;; FIND-FILE-MATCH indicates that any time a match is found, the | |
78 ;; file associated with the tag should be read into a file. | |
79 ;; | |
80 ;; The PATH argument is then the most interesting argument. It can | |
81 ;; have these values: | |
82 ;; | |
83 ;; nil - Take the current buffer, and use it's include list | |
84 ;; buffer - Use that buffer's include list. | |
85 ;; filename - Use that file's include list. If the file is not | |
86 ;; in a buffer, see of there is a semanticdb table for it. If | |
87 ;; not, read that file into a buffer. | |
88 ;; tag - Get that tag's buffer of file file. See above. | |
89 ;; table - Search that table, and it's include list. | |
90 ;; | |
91 ;; Search Results: | |
92 ;; | |
93 ;; Semanticdb returns the results in a specific format. There are a | |
94 ;; series of routines for using those results, and results can be | |
95 ;; passed in as a search-path for refinement searches with | |
96 ;; semanticdb. Apropos for semanticdb.*find-result for more. | |
97 ;; | |
98 ;; Application: | |
99 ;; | |
100 ;; Here are applications where different searches are needed which | |
101 ;; exist as of semantic 1.4.x | |
102 ;; | |
103 ;; eldoc - popup help | |
104 ;; => Requires basic search using default path. (Header files ok) | |
105 ;; tag jump - jump to a named tag | |
106 ;; => Requires a brute search useing whole project. (Source files only) | |
107 ;; completion - Completing symbol names in a smart way | |
108 ;; => Basic search (headers ok) | |
109 ;; type analysis - finding type definitions for variables & fcns | |
110 ;; => Basic search (headers ok) | |
111 ;; Class browser - organize types into some structure | |
112 ;; => Brute search, or custom navigation. | |
113 | |
114 ;; TODO: | |
115 ;; During a search, load any unloaded DB files based on paths in the | |
116 ;; current project. | |
117 | |
118 (require 'semantic/db) | |
119 (require 'semantic/db-ref) | |
120 (eval-when-compile | |
121 (require 'eieio) | |
122 ) | |
123 | |
124 ;;; Code: | |
125 (defvar semanticdb-find-throttle-custom-list | |
126 '(repeat (radio (const 'local) | |
127 (const 'project) | |
128 (const 'unloaded) | |
129 (const 'system) | |
130 (const 'recursive) | |
131 (const 'omniscience))) | |
132 "Customization values for semanticdb find throttle. | |
133 See `semanticdb-find-throttle' for details.") | |
134 | |
135 (defcustom semanticdb-find-default-throttle | |
136 '(local project unloaded system recursive) | |
137 "The default throttle for `semanticdb-find' routines. | |
138 The throttle controls how detailed the list of database | |
139 tables is for a symbol lookup. The value is a list with | |
140 the following keys: | |
141 `file' - The file the search is being performed from. | |
142 This option is here for completeness only, and | |
143 is assumed to always be on. | |
144 `local' - Tables from the same local directory are included. | |
145 This includes files directly referenced by a file name | |
146 which might be in a different directory. | |
147 `project' - Tables from the same local project are included | |
148 If `project' is specified, then `local' is assumed. | |
149 `unloaded' - If a table is not in memory, load it. If it is not cached | |
150 on disk either, get the source, parse it, and create | |
151 the table. | |
152 `system' - Tables from system databases. These are specifically | |
153 tables from system header files, or language equivalent. | |
154 `recursive' - For include based searches, includes tables referenced | |
155 by included files. | |
156 `omniscience' - Included system databases which are omniscience, or | |
157 somehow know everything. Omniscience databases are found | |
158 in `semanticdb-project-system-databases'. | |
159 The Emacs Lisp system DB is an omniscience database." | |
160 :group 'semanticdb | |
161 :type semanticdb-find-throttle-custom-list) | |
162 | |
163 (defun semanticdb-find-throttle-active-p (access-type) | |
164 "Non-nil if ACCESS-TYPE is an active throttle type." | |
165 (or (memq access-type semanticdb-find-default-throttle) | |
166 (eq access-type 'file) | |
167 (and (eq access-type 'local) | |
168 (memq 'project semanticdb-find-default-throttle)) | |
169 )) | |
170 | |
171 ;;; Index Class | |
172 ;; | |
173 ;; The find routines spend a lot of time looking stuff up. | |
174 ;; Use this handy search index to cache data between searches. | |
175 ;; This should allow searches to start running faster. | |
176 (defclass semanticdb-find-search-index (semanticdb-abstract-search-index) | |
177 ((include-path :initform nil | |
178 :documentation | |
179 "List of semanticdb tables from the include path.") | |
180 (type-cache :initform nil | |
181 :documentation | |
182 "Cache of all the data types accessible from this file. | |
183 Includes all types from all included files, merged namespaces, and | |
184 expunge duplicates.") | |
185 ) | |
186 "Concrete search index for `semanticdb-find'. | |
187 This class will cache data derived during various searches.") | |
188 | |
189 (defmethod semantic-reset ((idx semanticdb-find-search-index)) | |
190 "Reset the object IDX." | |
191 ;; Clear the include path. | |
192 (oset idx include-path nil) | |
193 (when (oref idx type-cache) | |
194 (semantic-reset (oref idx type-cache))) | |
195 ;; Clear the scope. Scope doesn't have the data it needs to track | |
196 ;; it's own reset. | |
197 (semantic-scope-reset-cache) | |
198 ) | |
199 | |
200 (defmethod semanticdb-synchronize ((idx semanticdb-find-search-index) | |
201 new-tags) | |
202 "Synchronize the search index IDX with some NEW-TAGS." | |
203 ;; Reset our parts. | |
204 (semantic-reset idx) | |
205 ;; Notify dependants by clearning their indicies. | |
206 (semanticdb-notify-references | |
207 (oref idx table) | |
208 (lambda (tab me) | |
209 (semantic-reset (semanticdb-get-table-index tab)))) | |
210 ) | |
211 | |
212 (defmethod semanticdb-partial-synchronize ((idx semanticdb-find-search-index) | |
213 new-tags) | |
214 "Synchronize the search index IDX with some changed NEW-TAGS." | |
215 ;; Only reset if include statements changed. | |
216 (if (semantic-find-tags-by-class 'include new-tags) | |
217 (progn | |
218 (semantic-reset idx) | |
219 ;; Notify dependants by clearning their indicies. | |
220 (semanticdb-notify-references | |
221 (oref idx table) | |
222 (lambda (tab me) | |
223 (semantic-reset (semanticdb-get-table-index tab)))) | |
224 ) | |
225 ;; Else, not an include, by just a type. | |
226 (when (oref idx type-cache) | |
227 (when (semanticdb-partial-synchronize (oref idx type-cache) new-tags) | |
228 ;; If the synchronize returns true, we need to notify. | |
229 ;; Notify dependants by clearning their indicies. | |
230 (semanticdb-notify-references | |
231 (oref idx table) | |
232 (lambda (tab me) | |
233 (let ((tab-idx (semanticdb-get-table-index tab))) | |
234 ;; Not a full reset? | |
235 (when (oref tab-idx type-cache) | |
236 (semanticdb-typecache-notify-reset | |
237 (oref tab-idx type-cache))) | |
238 ))) | |
239 )) | |
240 )) | |
241 | |
242 | |
243 ;;; Path Translations | |
244 ;; | |
245 ;;; OVERLOAD Functions | |
246 ;; | |
247 ;; These routines needed to be overloaded by specific language modes. | |
248 ;; They are needed for translating an INCLUDE tag into a semanticdb | |
249 ;; TABLE object. | |
250 (define-overloadable-function semanticdb-find-translate-path (path brutish) | |
251 "Translate PATH into a list of semantic tables. | |
252 Path translation involves identifying the PATH input argument | |
253 in one of the following ways: | |
254 nil - Take the current buffer, and use it's include list | |
255 buffer - Use that buffer's include list. | |
256 filename - Use that file's include list. If the file is not | |
257 in a buffer, see of there is a semanticdb table for it. If | |
258 not, read that file into a buffer. | |
259 tag - Get that tag's buffer of file file. See above. | |
260 table - Search that table, and it's include list. | |
261 find result - Search the results of a previous find. | |
262 | |
263 In addition, once the base path is found, there is the possibility of | |
264 each added table adding yet more tables to the path, so this routine | |
265 can return a lengthy list. | |
266 | |
267 If argument BRUTISH is non-nil, then instead of using the include | |
268 list, use all tables found in the parent project of the table | |
269 identified by translating PATH. Such searches use brute force to | |
270 scan every available table. | |
271 | |
272 The return value is a list of objects of type `semanticdb-table' or | |
273 it's children. In the case of passing in a find result, the result | |
274 is returned unchanged. | |
275 | |
276 This routine uses `semanticdb-find-table-for-include' to translate | |
277 specific include tags into a semanticdb table. | |
278 | |
279 Note: When searching using a non-brutish method, the list of | |
280 included files will be cached between runs. Database-references | |
281 are used to track which files need to have their include lists | |
282 refreshed when things change. See `semanticdb-ref-test'. | |
283 | |
284 Note for overloading: If you opt to overload this function for your | |
285 major mode, and your routine takes a long time, be sure to call | |
286 | |
287 (semantic-throw-on-input 'your-symbol-here) | |
288 | |
289 so that it can be called from the idle work handler." | |
290 ) | |
291 | |
292 (defun semanticdb-find-translate-path-default (path brutish) | |
293 "Translate PATH into a list of semantic tables. | |
294 If BRUTISH is non nil, return all tables associated with PATH. | |
295 Default action as described in `semanticdb-find-translate-path'." | |
296 (if (semanticdb-find-results-p path) | |
297 ;; nil means perform the search over these results. | |
298 nil | |
299 (if brutish | |
300 (semanticdb-find-translate-path-brutish-default path) | |
301 (semanticdb-find-translate-path-includes-default path)))) | |
302 | |
303 (defun semanticdb-find-translate-path-brutish-default (path) | |
304 "Translate PATH into a list of semantic tables. | |
305 Default action as described in `semanticdb-find-translate-path'." | |
306 (let ((basedb | |
307 (cond ((null path) semanticdb-current-database) | |
308 ((semanticdb-table-p path) (oref path parent-db)) | |
309 (t (let ((tt (semantic-something-to-tag-table path))) | |
310 (save-excursion | |
311 ;; @todo - What does this DO ??!?! | |
312 (set-buffer (semantic-tag-buffer (car tt))) | |
313 semanticdb-current-database)))))) | |
314 (apply | |
315 #'nconc | |
316 (mapcar | |
317 (lambda (db) | |
318 (let ((tabs (semanticdb-get-database-tables db)) | |
319 (ret nil)) | |
320 ;; Only return tables of the same language (major-mode) | |
321 ;; as the current search environment. | |
322 (while tabs | |
323 | |
324 (semantic-throw-on-input 'translate-path-brutish) | |
325 | |
326 (if (semanticdb-equivalent-mode-for-search (car tabs) | |
327 (current-buffer)) | |
328 (setq ret (cons (car tabs) ret))) | |
329 (setq tabs (cdr tabs))) | |
330 ret)) | |
331 ;; FIXME: | |
332 ;; This should scan the current project directory list for all | |
333 ;; semanticdb files, perhaps handling proxies for them. | |
334 (semanticdb-current-database-list | |
335 (if basedb (oref basedb reference-directory) | |
336 default-directory)))) | |
337 )) | |
338 | |
339 (defun semanticdb-find-incomplete-cache-entries-p (cache) | |
340 "Are there any incomplete entries in CACHE?" | |
341 (let ((ans nil)) | |
342 (dolist (tab cache) | |
343 (when (and (semanticdb-table-child-p tab) | |
344 (not (number-or-marker-p (oref tab pointmax)))) | |
345 (setq ans t)) | |
346 ) | |
347 ans)) | |
348 | |
349 (defun semanticdb-find-need-cache-update-p (table) | |
350 "Non nil if the semanticdb TABLE cache needs to be updated." | |
351 ;; If we were passed in something related to a TABLE, | |
352 ;; do a caching lookup. | |
353 (let* ((index (semanticdb-get-table-index table)) | |
354 (cache (when index (oref index include-path))) | |
355 (incom (semanticdb-find-incomplete-cache-entries-p cache)) | |
356 (unl (semanticdb-find-throttle-active-p 'unloaded)) | |
357 ) | |
358 (if (and | |
359 cache ;; Must have a cache | |
360 (or | |
361 ;; If all entries are "full", or if 'unloaded | |
362 ;; OR | |
363 ;; is not in the throttle, it is ok to use the cache. | |
364 (not incom) (not unl) | |
365 )) | |
366 nil | |
367 ;;cache | |
368 ;; ELSE | |
369 ;; | |
370 ;; We need an update. | |
371 t)) | |
372 ) | |
373 | |
374 (defun semanticdb-find-translate-path-includes-default (path) | |
375 "Translate PATH into a list of semantic tables. | |
376 Default action as described in `semanticdb-find-translate-path'." | |
377 (let ((table (cond ((null path) | |
378 semanticdb-current-table) | |
379 ((bufferp path) | |
380 (semantic-buffer-local-value 'semanticdb-current-table path)) | |
381 ((and (stringp path) (file-exists-p path)) | |
382 (semanticdb-file-table-object path t)) | |
383 ((semanticdb-abstract-table-child-p path) | |
384 path) | |
385 (t nil)))) | |
386 (if table | |
387 ;; If we were passed in something related to a TABLE, | |
388 ;; do a caching lookup. | |
389 (let ((index (semanticdb-get-table-index table))) | |
390 (if (semanticdb-find-need-cache-update-p table) | |
391 ;; Lets go look up our indicies | |
392 (let ((ans (semanticdb-find-translate-path-includes--internal path))) | |
393 (oset index include-path ans) | |
394 ;; Once we have our new indicies set up, notify those | |
395 ;; who depend on us if we found something for them to | |
396 ;; depend on. | |
397 (when ans (semanticdb-refresh-references table)) | |
398 ans) | |
399 ;; ELSE | |
400 ;; | |
401 ;; Just return the cache. | |
402 (oref index include-path))) | |
403 ;; If we were passed in something like a tag list, or other boring | |
404 ;; searchable item, then instead do the regular thing without caching. | |
405 (semanticdb-find-translate-path-includes--internal path)))) | |
406 | |
407 (defvar semanticdb-find-lost-includes nil | |
408 "Include files that we cannot find associated with this buffer.") | |
409 (make-variable-buffer-local 'semanticdb-find-lost-includes) | |
410 | |
411 (defvar semanticdb-find-scanned-include-tags nil | |
412 "All include tags scanned, plus action taken on the tag. | |
413 Each entry is an alist: | |
414 (ACTION . TAG) | |
415 where ACTION is one of 'scanned, 'duplicate, 'lost. | |
416 and TAG is a clone of the include tag that was found.") | |
417 (make-variable-buffer-local 'semanticdb-find-scanned-include-tags) | |
418 | |
419 (defvar semanticdb-implied-include-tags nil | |
420 "Include tags implied for all files of a given mode. | |
421 Set this variable with `defvar-mode-local' for a particular mode so | |
422 that any symbols that exist for all files for that mode are included. | |
423 | |
424 Note: This could be used as a way to write a file in a langauge | |
425 to declare all the built-ins for that language.") | |
426 | |
427 (defun semanticdb-find-translate-path-includes--internal (path) | |
428 "Internal implementation of `semanticdb-find-translate-path-includes-default'. | |
429 This routine does not depend on the cache, but will always derive | |
430 a new path from the provided PATH." | |
431 (let ((includetags nil) | |
432 (curtable nil) | |
433 (matchedtables (list semanticdb-current-table)) | |
434 (matchedincludes nil) | |
435 (lostincludes nil) | |
436 (scannedincludes nil) | |
437 (incfname nil) | |
438 nexttable) | |
439 (cond ((null path) | |
440 (semantic-refresh-tags-safe) | |
441 (setq includetags (append | |
442 (semantic-find-tags-included (current-buffer)) | |
443 semanticdb-implied-include-tags) | |
444 curtable semanticdb-current-table | |
445 incfname (buffer-file-name)) | |
446 ) | |
447 ((semanticdb-table-p path) | |
448 (setq includetags (semantic-find-tags-included path) | |
449 curtable path | |
450 incfname (semanticdb-full-filename path)) | |
451 ) | |
452 ((bufferp path) | |
453 (save-excursion | |
454 (set-buffer path) | |
455 (semantic-refresh-tags-safe)) | |
456 (setq includetags (semantic-find-tags-included path) | |
457 curtable (save-excursion (set-buffer path) | |
458 semanticdb-current-table) | |
459 incfname (buffer-file-name path))) | |
460 (t | |
461 (setq includetags (semantic-find-tags-included path)) | |
462 (when includetags | |
463 ;; If we have some tags, derive a table from them. | |
464 ;; else we will do nothing, so the table is useless. | |
465 | |
466 ;; @todo - derive some tables | |
467 (message "Need to derive tables for %S in translate-path-includes--default." | |
468 path) | |
469 ))) | |
470 | |
471 ;; Make sure each found include tag has an originating file name associated | |
472 ;; with it. | |
473 (when incfname | |
474 (dolist (it includetags) | |
475 (semantic--tag-put-property it :filename incfname))) | |
476 | |
477 ;; Loop over all include tags adding to matchedtables | |
478 (while includetags | |
479 (semantic-throw-on-input 'semantic-find-translate-path-includes-default) | |
480 | |
481 ;; If we've seen this include string before, lets skip it. | |
482 (if (member (semantic-tag-name (car includetags)) matchedincludes) | |
483 (progn | |
484 (setq nexttable nil) | |
485 (push (cons 'duplicate (semantic-tag-clone (car includetags))) | |
486 scannedincludes) | |
487 ) | |
488 (setq nexttable (semanticdb-find-table-for-include (car includetags) curtable)) | |
489 (when (not nexttable) | |
490 ;; Save the lost include. | |
491 (push (car includetags) lostincludes) | |
492 (push (cons 'lost (semantic-tag-clone (car includetags))) | |
493 scannedincludes) | |
494 ) | |
495 ) | |
496 | |
497 ;; Push the include file, so if we can't find it, we only | |
498 ;; can't find it once. | |
499 (push (semantic-tag-name (car includetags)) matchedincludes) | |
500 | |
501 ;; (message "Scanning %s" (semantic-tag-name (car includetags))) | |
502 (when (and nexttable | |
503 (not (memq nexttable matchedtables)) | |
504 (semanticdb-equivalent-mode-for-search nexttable | |
505 (current-buffer)) | |
506 ) | |
507 ;; Add to list of tables | |
508 (push nexttable matchedtables) | |
509 | |
510 ;; Queue new includes to list | |
511 (if (semanticdb-find-throttle-active-p 'recursive) | |
512 ;; @todo - recursive includes need to have the originating | |
513 ;; buffer's location added to the path. | |
514 (let ((newtags | |
515 (cond | |
516 ((semanticdb-table-p nexttable) | |
517 (semanticdb-refresh-table nexttable) | |
518 ;; Use the method directly, or we will recurse | |
519 ;; into ourselves here. | |
520 (semanticdb-find-tags-by-class-method | |
521 nexttable 'include)) | |
522 (t ;; @todo - is this ever possible??? | |
523 (message "semanticdb-ftp - how did you do that?") | |
524 (semantic-find-tags-included | |
525 (semanticdb-get-tags nexttable))) | |
526 )) | |
527 (newincfname (semanticdb-full-filename nexttable)) | |
528 ) | |
529 | |
530 (push (cons 'scanned (semantic-tag-clone (car includetags))) | |
531 scannedincludes) | |
532 | |
533 ;; Setup new tags so we know where they are. | |
534 (dolist (it newtags) | |
535 (semantic--tag-put-property it :filename | |
536 newincfname)) | |
537 | |
538 (setq includetags (nconc includetags newtags))) | |
539 ;; ELSE - not recursive throttle | |
540 (push (cons 'scanned-no-recurse | |
541 (semantic-tag-clone (car includetags))) | |
542 scannedincludes) | |
543 ) | |
544 ) | |
545 (setq includetags (cdr includetags))) | |
546 | |
547 (setq semanticdb-find-lost-includes lostincludes) | |
548 (setq semanticdb-find-scanned-include-tags (reverse scannedincludes)) | |
549 | |
550 ;; Find all the omniscient databases for this major mode, and | |
551 ;; add them if needed | |
552 (when (and (semanticdb-find-throttle-active-p 'omniscience) | |
553 semanticdb-search-system-databases) | |
554 ;; We can append any mode-specific omniscience databases into | |
555 ;; our search list here. | |
556 (let ((systemdb semanticdb-project-system-databases) | |
557 (ans nil)) | |
558 (while systemdb | |
559 (setq ans (semanticdb-file-table | |
560 (car systemdb) | |
561 ;; I would expect most omniscient to return the same | |
562 ;; thing reguardless of filename, but we may have | |
563 ;; one that can return a table of all things the | |
564 ;; current file needs. | |
565 (buffer-file-name (current-buffer)))) | |
566 (when (not (memq ans matchedtables)) | |
567 (setq matchedtables (cons ans matchedtables))) | |
568 (setq systemdb (cdr systemdb)))) | |
569 ) | |
570 (nreverse matchedtables))) | |
571 | |
572 (define-overloadable-function semanticdb-find-load-unloaded (filename) | |
573 "Create a database table for FILENAME if it hasn't been parsed yet. | |
574 Assumes that FILENAME exists as a source file. | |
575 Assumes that a preexisting table does not exist, even if it | |
576 isn't in memory yet." | |
577 (if (semanticdb-find-throttle-active-p 'unloaded) | |
578 (:override) | |
579 (semanticdb-file-table-object filename t))) | |
580 | |
581 (defun semanticdb-find-load-unloaded-default (filename) | |
582 "Load an unloaded file in FILENAME using the default semanticdb loader." | |
583 (semanticdb-file-table-object filename)) | |
584 | |
585 (define-overloadable-function semanticdb-find-table-for-include (includetag &optional table) | |
586 "For a single INCLUDETAG found in TABLE, find a `semanticdb-table' object | |
587 INCLUDETAG is a semantic TAG of class 'include. | |
588 TABLE is a semanticdb table that identifies where INCLUDETAG came from. | |
589 TABLE is optional if INCLUDETAG has an overlay of :filename attribute." | |
590 ) | |
591 | |
592 (defun semanticdb-find-table-for-include-default (includetag &optional table) | |
593 "Default implementation of `semanticdb-find-table-for-include'. | |
594 Uses `semanticdb-current-database-list' as the search path. | |
595 INCLUDETAG and TABLE are documented in `semanticdb-find-table-for-include'. | |
596 Included databases are filtered based on `semanticdb-find-default-throttle'." | |
597 (if (not (eq (semantic-tag-class includetag) 'include)) | |
598 (signal 'wrong-type-argument (list includetag 'include))) | |
599 | |
600 (let ((name | |
601 ;; Note, some languages (like Emacs or Java) use include tag names | |
602 ;; that don't represent files! We want to have file names. | |
603 (semantic-tag-include-filename includetag)) | |
604 (originfiledir nil) | |
605 (roots nil) | |
606 (tmp nil) | |
607 (ans nil)) | |
608 | |
609 ;; INCLUDETAG should have some way to reference where it came | |
610 ;; from! If not, TABLE should provide the way. Each time we | |
611 ;; look up a tag, we may need to find it in some relative way | |
612 ;; and must set our current buffer eto the origin of includetag | |
613 ;; or nothing may work. | |
614 (setq originfiledir | |
615 (cond ((semantic-tag-file-name includetag) | |
616 ;; A tag may have a buffer, or a :filename property. | |
617 (file-name-directory (semantic-tag-file-name includetag))) | |
618 (table | |
619 (file-name-directory (semanticdb-full-filename table))) | |
620 (t | |
621 ;; @todo - what to do here? Throw an error maybe | |
622 ;; and fix usage bugs? | |
623 default-directory))) | |
624 | |
625 (cond | |
626 ;; Step 1: Relative path name | |
627 ;; | |
628 ;; If the name is relative, then it should be findable as relative | |
629 ;; to the source file that this tag originated in, and be fast. | |
630 ;; | |
631 ((and (semanticdb-find-throttle-active-p 'local) | |
632 (file-exists-p (expand-file-name name originfiledir))) | |
633 | |
634 (setq ans (semanticdb-find-load-unloaded | |
635 (expand-file-name name originfiledir))) | |
636 ) | |
637 ;; Step 2: System or Project level includes | |
638 ;; | |
639 ((or | |
640 ;; First, if it a system include, we can investigate that tags | |
641 ;; dependency file | |
642 (and (semanticdb-find-throttle-active-p 'system) | |
643 | |
644 ;; Sadly, not all languages make this distinction. | |
645 ;;(semantic-tag-include-system-p includetag) | |
646 | |
647 ;; Here, we get local and system files. | |
648 (setq tmp (semantic-dependency-tag-file includetag)) | |
649 ) | |
650 ;; Second, project files are active, we and we have EDE, | |
651 ;; we can find it using the same tool. | |
652 (and (semanticdb-find-throttle-active-p 'project) | |
653 ;; Make sure EDE is available, and we have a project | |
654 (featurep 'ede) (ede-current-project originfiledir) | |
655 ;; The EDE query is hidden in this call. | |
656 (setq tmp (semantic-dependency-tag-file includetag)) | |
657 ) | |
658 ) | |
659 (setq ans (semanticdb-find-load-unloaded tmp)) | |
660 ) | |
661 ;; Somewhere in our project hierarchy | |
662 ;; | |
663 ;; Remember: Roots includes system databases which can create | |
664 ;; specialized tables we can search. | |
665 ;; | |
666 ;; NOTE: Not used if EDE is active! | |
667 ((and (semanticdb-find-throttle-active-p 'project) | |
668 ;; And dont do this if it is a system include. Not supported by all languages, | |
669 ;; but when it is, this is a nice fast way to skip this step. | |
670 (not (semantic-tag-include-system-p includetag)) | |
671 ;; Don't do this if we have an EDE project. | |
672 (not (and (featurep 'ede) | |
673 ;; Note: We don't use originfiledir here because | |
674 ;; we want to know about the source file we are | |
675 ;; starting from. | |
676 (ede-current-project))) | |
677 ) | |
678 | |
679 (setq roots (semanticdb-current-database-list)) | |
680 | |
681 (while (and (not ans) roots) | |
682 (let* ((ref (if (slot-boundp (car roots) 'reference-directory) | |
683 (oref (car roots) reference-directory))) | |
684 (fname (cond ((null ref) nil) | |
685 ((file-exists-p (expand-file-name name ref)) | |
686 (expand-file-name name ref)) | |
687 ((file-exists-p (expand-file-name (file-name-nondirectory name) ref)) | |
688 (expand-file-name (file-name-nondirectory name) ref))))) | |
689 (when (and ref fname) | |
690 ;; There is an actual file. Grab it. | |
691 (setq ans (semanticdb-find-load-unloaded fname))) | |
692 | |
693 ;; ELSE | |
694 ;; | |
695 ;; NOTE: We used to look up omniscient databases here, but that | |
696 ;; is now handled one layer up. | |
697 ;; | |
698 ;; Missing: a database that knows where missing files are. Hmm. | |
699 ;; perhaps I need an override function for that? | |
700 | |
701 ) | |
702 | |
703 (setq roots (cdr roots)))) | |
704 ) | |
705 ans)) | |
706 | |
707 | |
708 ;;; Perform interactive tests on the path/search mechanisms. | |
709 ;; | |
710 (defun semanticdb-find-test-translate-path (&optional arg) | |
711 "Call and output results of `semanticdb-find-translate-path'. | |
712 With ARG non-nil, specify a BRUTISH translation. | |
713 See `semanticdb-find-default-throttle' and `semanticdb-project-roots' | |
714 for details on how this list is derived." | |
715 (interactive "P") | |
716 (semantic-fetch-tags) | |
717 (require 'data-debug) | |
718 (let ((start (current-time)) | |
719 (p (semanticdb-find-translate-path nil arg)) | |
720 (end (current-time)) | |
721 ) | |
722 (data-debug-new-buffer "*SEMANTICDB FTP ADEBUG*") | |
723 (message "Search of tags took %.2f seconds." | |
724 (semantic-elapsed-time start end)) | |
725 | |
726 (data-debug-insert-stuff-list p "*"))) | |
727 | |
728 (defun semanticdb-find-test-translate-path-no-loading (&optional arg) | |
729 "Call and output results of `semanticdb-find-translate-path'. | |
730 With ARG non-nil, specify a BRUTISH translation. | |
731 See `semanticdb-find-default-throttle' and `semanticdb-project-roots' | |
732 for details on how this list is derived." | |
733 (interactive "P") | |
734 (semantic-fetch-tags) | |
735 (require 'data-debug) | |
736 (let* ((semanticdb-find-default-throttle | |
737 (if (featurep 'semanticdb-find) | |
738 (remq 'unloaded semanticdb-find-default-throttle) | |
739 nil)) | |
740 (start (current-time)) | |
741 (p (semanticdb-find-translate-path nil arg)) | |
742 (end (current-time)) | |
743 ) | |
744 (data-debug-new-buffer "*SEMANTICDB FTP ADEBUG*") | |
745 (message "Search of tags took %.2f seconds." | |
746 (semantic-elapsed-time start end)) | |
747 | |
748 (data-debug-insert-stuff-list p "*"))) | |
749 | |
750 (defun semanticdb-find-adebug-lost-includes () | |
751 "Translate the current path, then display the lost includes. | |
752 Examines the variable `semanticdb-find-lost-includes'." | |
753 (interactive) | |
754 (require 'data-debug) | |
755 (semanticdb-find-translate-path nil nil) | |
756 (let ((lost semanticdb-find-lost-includes) | |
757 ) | |
758 | |
759 (if (not lost) | |
760 (message "There are no unknown includes for %s" | |
761 (buffer-name)) | |
762 | |
763 (data-debug-new-buffer "*SEMANTICDB lost-includes ADEBUG*") | |
764 (data-debug-insert-tag-list lost "*") | |
765 ))) | |
766 | |
767 (defun semanticdb-find-adebug-insert-scanned-tag-cons (consdata prefix prebuttontext) | |
768 "Insert a button representing scanned include CONSDATA. | |
769 PREFIX is the text that preceeds the button. | |
770 PREBUTTONTEXT is some text between prefix and the overlay button." | |
771 (let* ((start (point)) | |
772 (end nil) | |
773 (mode (car consdata)) | |
774 (tag (cdr consdata)) | |
775 (name (semantic-tag-name tag)) | |
776 (file (semantic-tag-file-name tag)) | |
777 (str1 (format "%S %s" mode name)) | |
778 (str2 (format " : %s" file)) | |
779 (tip nil)) | |
780 (insert prefix prebuttontext str1) | |
781 (setq end (point)) | |
782 (insert str2) | |
783 (put-text-property start end 'face | |
784 (cond ((eq mode 'scanned) | |
785 'font-lock-function-name-face) | |
786 ((eq mode 'duplicate) | |
787 'font-lock-comment-face) | |
788 ((eq mode 'lost) | |
789 'font-lock-variable-name-face) | |
790 ((eq mode 'scanned-no-recurse) | |
791 'font-lock-type-face))) | |
792 (put-text-property start end 'ddebug (cdr consdata)) | |
793 (put-text-property start end 'ddebug-indent(length prefix)) | |
794 (put-text-property start end 'ddebug-prefix prefix) | |
795 (put-text-property start end 'help-echo tip) | |
796 (put-text-property start end 'ddebug-function | |
797 'data-debug-insert-tag-parts-from-point) | |
798 (insert "\n") | |
799 ) | |
800 ) | |
801 | |
802 (defun semanticdb-find-adebug-scanned-includes () | |
803 "Translate the current path, then display the lost includes. | |
804 Examines the variable `semanticdb-find-lost-includes'." | |
805 (interactive) | |
806 (require 'data-debug) | |
807 (semanticdb-find-translate-path nil nil) | |
808 (let ((scanned semanticdb-find-scanned-include-tags) | |
809 (data-debug-thing-alist | |
810 (cons | |
811 '((lambda (thing) (and (consp thing) | |
812 (symbolp (car thing)) | |
813 (memq (car thing) | |
814 '(scanned scanned-no-recurse | |
815 lost duplicate)))) | |
816 . semanticdb-find-adebug-insert-scanned-tag-cons) | |
817 data-debug-thing-alist)) | |
818 ) | |
819 | |
820 (if (not scanned) | |
821 (message "There are no includes scanned %s" | |
822 (buffer-name)) | |
823 | |
824 (data-debug-new-buffer "*SEMANTICDB scanned-includes ADEBUG*") | |
825 (data-debug-insert-stuff-list scanned "*") | |
826 ))) | |
827 | |
828 ;;; FIND results and edebug | |
829 ;; | |
830 (eval-after-load "cedet-edebug" | |
831 '(progn | |
832 (cedet-edebug-add-print-override | |
833 '(semanticdb-find-results-p object) | |
834 '(semanticdb-find-result-prin1-to-string object) ) | |
835 )) | |
836 | |
837 | |
838 | |
839 ;;; API Functions | |
840 ;; | |
841 ;; Once you have a search result, use these routines to operate | |
842 ;; on the search results at a higher level | |
843 | |
844 (defun semanticdb-strip-find-results (results &optional find-file-match) | |
845 "Strip a semanticdb search RESULTS to exclude objects. | |
846 This makes it appear more like the results of a `semantic-find-' call. | |
847 Optional FIND-FILE-MATCH loads all files associated with RESULTS | |
848 into buffers. This has the side effect of enabling `semantic-tag-buffer' to | |
849 return a value. | |
850 If FIND-FILE-MATCH is 'name, then only the filename is stored | |
851 in each tag instead of loading each file into a buffer. | |
852 If the input RESULTS are not going to be used again, and if | |
853 FIND-FILE-MATCH is nil, you can use `semanticdb-fast-strip-find-results' | |
854 instead." | |
855 (if find-file-match | |
856 ;; Load all files associated with RESULTS. | |
857 (let ((tmp results) | |
858 (output nil)) | |
859 (while tmp | |
860 (let ((tab (car (car tmp))) | |
861 (tags (cdr (car tmp)))) | |
862 (dolist (T tags) | |
863 ;; Normilzation gives specialty database tables a chance | |
864 ;; to convert into a more stable tag format. | |
865 (let* ((norm (semanticdb-normalize-one-tag tab T)) | |
866 (ntab (car norm)) | |
867 (ntag (cdr norm)) | |
868 (nametable ntab)) | |
869 | |
870 ;; If it didn't normalize, use what we had. | |
871 (if (not norm) | |
872 (setq nametable tab) | |
873 (setq output (append output (list ntag)))) | |
874 | |
875 ;; Find-file-match allows a tool to make sure the tag is | |
876 ;; 'live', somewhere in a buffer. | |
877 (cond ((eq find-file-match 'name) | |
878 (let ((f (semanticdb-full-filename nametable))) | |
879 (semantic--tag-put-property ntag :filename f))) | |
880 ((and find-file-match ntab) | |
881 (semanticdb-get-buffer ntab)) | |
882 ) | |
883 )) | |
884 ) | |
885 (setq tmp (cdr tmp))) | |
886 output) | |
887 ;; @todo - I could use nconc, but I don't know what the caller may do with | |
888 ;; RESULTS after this is called. Right now semantic-complete will | |
889 ;; recycling the input after calling this routine. | |
890 (apply #'append (mapcar #'cdr results)))) | |
891 | |
892 (defun semanticdb-fast-strip-find-results (results) | |
893 "Destructively strip a semanticdb search RESULTS to exclude objects. | |
894 This makes it appear more like the results of a `semantic-find-' call. | |
895 This is like `semanticdb-strip-find-results', except the input list RESULTS | |
896 will be changed." | |
897 (apply #'nconc (mapcar #'cdr results))) | |
898 | |
899 (defun semanticdb-find-results-p (resultp) | |
900 "Non-nil if RESULTP is in the form of a semanticdb search result. | |
901 This query only really tests the first entry in the list that is RESULTP, | |
902 but should be good enough for debugging assertions." | |
903 (and (listp resultp) | |
904 (listp (car resultp)) | |
905 (semanticdb-abstract-table-child-p (car (car resultp))) | |
906 (or (semantic-tag-p (car (cdr (car resultp)))) | |
907 (null (car (cdr (car resultp))))))) | |
908 | |
909 (defun semanticdb-find-result-prin1-to-string (result) | |
910 "Presuming RESULT satisfies `semanticdb-find-results-p', provide a short PRIN1 output." | |
911 (if (< (length result) 2) | |
912 (concat "#<FIND RESULT " | |
913 (mapconcat (lambda (a) | |
914 (concat "(" (object-name (car a) ) " . " | |
915 "#<TAG LIST " (number-to-string (length (cdr a))) ">)")) | |
916 result | |
917 " ") | |
918 ">") | |
919 ;; Longer results should have an abreviated form. | |
920 (format "#<FIND RESULT %d TAGS in %d FILES>" | |
921 (semanticdb-find-result-length result) | |
922 (length result)))) | |
923 | |
924 (defun semanticdb-find-result-with-nil-p (resultp) | |
925 "Non-nil of RESULTP is in the form of a semanticdb search result. | |
926 nil is a valid value where a TABLE usually is, but only if the TAG | |
927 results include overlays. | |
928 This query only really tests the first entry in the list that is RESULTP, | |
929 but should be good enough for debugging assertions." | |
930 (and (listp resultp) | |
931 (listp (car resultp)) | |
932 (let ((tag-to-test (car-safe (cdr (car resultp))))) | |
933 (or (and (semanticdb-abstract-table-child-p (car (car resultp))) | |
934 (or (semantic-tag-p tag-to-test) | |
935 (null tag-to-test))) | |
936 (and (null (car (car resultp))) | |
937 (or (semantic-tag-with-position-p tag-to-test) | |
938 (null tag-to-test)))) | |
939 ))) | |
940 | |
941 (defun semanticdb-find-result-length (result) | |
942 "Number of tags found in RESULT." | |
943 (let ((count 0)) | |
944 (mapc (lambda (onetable) | |
945 (setq count (+ count (1- (length onetable))))) | |
946 result) | |
947 count)) | |
948 | |
949 (defun semanticdb-find-result-nth (result n) | |
950 "In RESULT, return the Nth search result. | |
951 This is a 0 based search result, with the first match being element 0. | |
952 | |
953 The returned value is a cons cell: (TAG . TABLE) where TAG | |
954 is the tag at the Nth position. TABLE is the semanticdb table where | |
955 the TAG was found. Sometimes TABLE can be nil." | |
956 (let ((ans nil) | |
957 (anstable nil)) | |
958 ;; Loop over each single table hit. | |
959 (while (and (not ans) result) | |
960 ;; For each table result, get local length, and modify | |
961 ;; N to be that much less. | |
962 (let ((ll (length (cdr (car result))))) ;; local length | |
963 (if (> ll n) | |
964 ;; We have a local match. | |
965 (setq ans (nth n (cdr (car result))) | |
966 anstable (car (car result))) | |
967 ;; More to go. Decrement N. | |
968 (setq n (- n ll)))) | |
969 ;; Keep moving. | |
970 (setq result (cdr result))) | |
971 (cons ans anstable))) | |
972 | |
973 (defun semanticdb-find-result-test (result) | |
974 "Test RESULT by accessing all the tags in the list." | |
975 (if (not (semanticdb-find-results-p result)) | |
976 (error "Does not pass `semanticdb-find-results-p.\n")) | |
977 (let ((len (semanticdb-find-result-length result)) | |
978 (i 0)) | |
979 (while (< i len) | |
980 (let ((tag (semanticdb-find-result-nth result i))) | |
981 (if (not (semantic-tag-p (car tag))) | |
982 (error "%d entry is not a tag" i))) | |
983 (setq i (1+ i))))) | |
984 | |
985 (defun semanticdb-find-result-nth-in-buffer (result n) | |
986 "In RESULT, return the Nth search result. | |
987 Like `semanticdb-find-result-nth', except that only the TAG | |
988 is returned, and the buffer it is found it will be made current. | |
989 If the result tag has no position information, the originating buffer | |
990 is still made current." | |
991 (let* ((ret (semanticdb-find-result-nth result n)) | |
992 (ans (car ret)) | |
993 (anstable (cdr ret))) | |
994 ;; If we have a hit, double-check the find-file | |
995 ;; entry. If the file must be loaded, then gat that table's | |
996 ;; source file into a buffer. | |
997 | |
998 (if anstable | |
999 (let ((norm (semanticdb-normalize-one-tag anstable ans))) | |
1000 (when norm | |
1001 ;; The normalized tags can now be found based on that | |
1002 ;; tags table. | |
1003 (semanticdb-set-buffer (car norm)) | |
1004 ;; Now reset ans | |
1005 (setq ans (cdr norm)) | |
1006 )) | |
1007 ) | |
1008 ;; Return the tag. | |
1009 ans)) | |
1010 | |
1011 (defun semanticdb-find-result-mapc (fcn result) | |
1012 "Apply FCN to each element of find RESULT for side-effects only. | |
1013 FCN takes two arguments. The first is a TAG, and the | |
1014 second is a DB from wence TAG originated. | |
1015 Returns result." | |
1016 (mapc (lambda (sublst) | |
1017 (mapc (lambda (tag) | |
1018 (funcall fcn tag (car sublst))) | |
1019 (cdr sublst))) | |
1020 result) | |
1021 result) | |
1022 | |
1023 ;;; Search Logging | |
1024 ;; | |
1025 ;; Basic logging to see what the search routines are doing. | |
1026 (defvar semanticdb-find-log-flag nil | |
1027 "Non-nil means log the process of searches.") | |
1028 | |
1029 (defvar semanticdb-find-log-buffer-name "*SemanticDB Find Log*" | |
1030 "The name of the logging buffer.") | |
1031 | |
1032 (defun semanticdb-find-toggle-logging () | |
1033 "Toggle sematnicdb logging." | |
1034 (interactive) | |
1035 (setq semanticdb-find-log-flag (null semanticdb-find-log-flag)) | |
1036 (message "Semanticdb find logging is %sabled" | |
1037 (if semanticdb-find-log-flag "en" "dis"))) | |
1038 | |
1039 (defun semanticdb-reset-log () | |
1040 "Reset the log buffer." | |
1041 (interactive) | |
1042 (when semanticdb-find-log-flag | |
1043 (save-excursion | |
1044 (set-buffer (get-buffer-create semanticdb-find-log-buffer-name)) | |
1045 (erase-buffer) | |
1046 ))) | |
1047 | |
1048 (defun semanticdb-find-log-move-to-end () | |
1049 "Move to the end of the semantic log." | |
1050 (let ((cb (current-buffer)) | |
1051 (cw (selected-window))) | |
1052 (unwind-protect | |
1053 (progn | |
1054 (set-buffer semanticdb-find-log-buffer-name) | |
1055 (if (get-buffer-window (current-buffer) 'visible) | |
1056 (select-window (get-buffer-window (current-buffer) 'visible))) | |
1057 (goto-char (point-max))) | |
1058 (if cw (select-window cw)) | |
1059 (set-buffer cb)))) | |
1060 | |
1061 (defun semanticdb-find-log-new-search (forwhat) | |
1062 "Start a new search FORWHAT." | |
1063 (when semanticdb-find-log-flag | |
1064 (save-excursion | |
1065 (set-buffer (get-buffer-create semanticdb-find-log-buffer-name)) | |
1066 (insert (format "New Search: %S\n" forwhat)) | |
1067 ) | |
1068 (semanticdb-find-log-move-to-end))) | |
1069 | |
1070 (defun semanticdb-find-log-activity (table result) | |
1071 "Log that TABLE has been searched and RESULT was found." | |
1072 (when semanticdb-find-log-flag | |
1073 (save-excursion | |
1074 (set-buffer semanticdb-find-log-buffer-name) | |
1075 (insert "Table: " (object-print table) | |
1076 " Result: " (int-to-string (length result)) " tags" | |
1077 "\n") | |
1078 ) | |
1079 (semanticdb-find-log-move-to-end))) | |
1080 | |
1081 ;;; Semanticdb find API functions | |
1082 ;; | |
1083 ;; These are the routines actually used to perform searches. | |
1084 ;; | |
1085 (defun semanticdb-find-tags-collector (function &optional path find-file-match | |
1086 brutish) | |
1087 "Collect all tags returned by FUNCTION over PATH. | |
1088 The FUNCTION must take two arguments. The first is TABLE, | |
1089 which is a semanticdb table containing tags. The second argument | |
1090 to FUNCTION is TAGS. TAGS may be a list of tags. If TAGS is non-nil, then | |
1091 FUNCTION should search the TAG list, not through TABLE. | |
1092 | |
1093 See `semanticdb-find-translate-path' for details on PATH. | |
1094 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1095 associated with that tag should be loaded into a buffer. | |
1096 | |
1097 Note: You should leave FIND-FILE-MATCH as nil. It is far more | |
1098 efficient to take the results from any search and use | |
1099 `semanticdb-strip-find-results' instead. This argument is here | |
1100 for backward compatibility. | |
1101 | |
1102 If optional argument BRUTISH is non-nil, then ignore include statements, | |
1103 and search all tables in this project tree." | |
1104 (let (found match) | |
1105 (save-excursion | |
1106 ;; If path is a buffer, set ourselves up in that buffer | |
1107 ;; so that the override methods work correctly. | |
1108 (when (bufferp path) (set-buffer path)) | |
1109 (if (semanticdb-find-results-p path) | |
1110 ;; When we get find results, loop over that. | |
1111 (dolist (tableandtags path) | |
1112 (semantic-throw-on-input 'semantic-find-translate-path) | |
1113 ;; If FIND-FILE-MATCH is non-nil, skip tables of class | |
1114 ;; `semanticdb-search-results-table', since those are system | |
1115 ;; databases and not associated with a file. | |
1116 (unless (and find-file-match | |
1117 (obj-of-class-p | |
1118 (car tableandtags) semanticdb-search-results-table)) | |
1119 (when (setq match (funcall function | |
1120 (car tableandtags) (cdr tableandtags))) | |
1121 (when find-file-match | |
1122 (save-excursion (semanticdb-set-buffer (car tableandtags)))) | |
1123 (push (cons (car tableandtags) match) found))) | |
1124 ) | |
1125 ;; Only log searches across data bases. | |
1126 (semanticdb-find-log-new-search nil) | |
1127 ;; If we get something else, scan the list of tables resulting | |
1128 ;; from translating it into a list of objects. | |
1129 (dolist (table (semanticdb-find-translate-path path brutish)) | |
1130 (semantic-throw-on-input 'semantic-find-translate-path) | |
1131 ;; If FIND-FILE-MATCH is non-nil, skip tables of class | |
1132 ;; `semanticdb-search-results-table', since those are system | |
1133 ;; databases and not associated with a file. | |
1134 (unless (and find-file-match | |
1135 (obj-of-class-p table semanticdb-search-results-table)) | |
1136 (when (and table (setq match (funcall function table nil))) | |
1137 (semanticdb-find-log-activity table match) | |
1138 (when find-file-match | |
1139 (save-excursion (semanticdb-set-buffer table))) | |
1140 (push (cons table match) found)))))) | |
1141 ;; At this point, FOUND has had items pushed onto it. | |
1142 ;; This means items are being returned in REVERSE order | |
1143 ;; of the tables searched, so if you just get th CAR, then | |
1144 ;; too-bad, you may have some system-tag that has no | |
1145 ;; buffer associated with it. | |
1146 | |
1147 ;; It must be reversed. | |
1148 (nreverse found))) | |
1149 | |
1150 (defun semanticdb-find-tags-by-name (name &optional path find-file-match) | |
1151 "Search for all tags matching NAME on PATH. | |
1152 See `semanticdb-find-translate-path' for details on PATH. | |
1153 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1154 associated with that tag should be loaded into a buffer." | |
1155 (semanticdb-find-tags-collector | |
1156 (lambda (table tags) | |
1157 (semanticdb-find-tags-by-name-method table name tags)) | |
1158 path find-file-match)) | |
1159 | |
1160 (defun semanticdb-find-tags-by-name-regexp (regexp &optional path find-file-match) | |
1161 "Search for all tags matching REGEXP on PATH. | |
1162 See `semanticdb-find-translate-path' for details on PATH. | |
1163 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1164 associated with that tag should be loaded into a buffer." | |
1165 (semanticdb-find-tags-collector | |
1166 (lambda (table tags) | |
1167 (semanticdb-find-tags-by-name-regexp-method table regexp tags)) | |
1168 path find-file-match)) | |
1169 | |
1170 (defun semanticdb-find-tags-for-completion (prefix &optional path find-file-match) | |
1171 "Search for all tags matching PREFIX on PATH. | |
1172 See `semanticdb-find-translate-path' for details on PATH. | |
1173 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1174 associated with that tag should be loaded into a buffer." | |
1175 (semanticdb-find-tags-collector | |
1176 (lambda (table tags) | |
1177 (semanticdb-find-tags-for-completion-method table prefix tags)) | |
1178 path find-file-match)) | |
1179 | |
1180 (defun semanticdb-find-tags-by-class (class &optional path find-file-match) | |
1181 "Search for all tags of CLASS on PATH. | |
1182 See `semanticdb-find-translate-path' for details on PATH. | |
1183 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1184 associated with that tag should be loaded into a buffer." | |
1185 (semanticdb-find-tags-collector | |
1186 (lambda (table tags) | |
1187 (semanticdb-find-tags-by-class-method table class tags)) | |
1188 path find-file-match)) | |
1189 | |
1190 ;;; Deep Searches | |
1191 (defun semanticdb-deep-find-tags-by-name (name &optional path find-file-match) | |
1192 "Search for all tags matching NAME on PATH. | |
1193 Search also in all components of top level tags founds. | |
1194 See `semanticdb-find-translate-path' for details on PATH. | |
1195 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1196 associated with that tag should be loaded into a buffer." | |
1197 (semanticdb-find-tags-collector | |
1198 (lambda (table tags) | |
1199 (semanticdb-deep-find-tags-by-name-method table name tags)) | |
1200 path find-file-match)) | |
1201 | |
1202 (defun semanticdb-deep-find-tags-by-name-regexp (regexp &optional path find-file-match) | |
1203 "Search for all tags matching REGEXP on PATH. | |
1204 Search also in all components of top level tags founds. | |
1205 See `semanticdb-find-translate-path' for details on PATH. | |
1206 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1207 associated with that tag should be loaded into a buffer." | |
1208 (semanticdb-find-tags-collector | |
1209 (lambda (table tags) | |
1210 (semanticdb-deep-find-tags-by-name-regexp-method table regexp tags)) | |
1211 path find-file-match)) | |
1212 | |
1213 (defun semanticdb-deep-find-tags-for-completion (prefix &optional path find-file-match) | |
1214 "Search for all tags matching PREFIX on PATH. | |
1215 Search also in all components of top level tags founds. | |
1216 See `semanticdb-find-translate-path' for details on PATH. | |
1217 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1218 associated with that tag should be loaded into a buffer." | |
1219 (semanticdb-find-tags-collector | |
1220 (lambda (table tags) | |
1221 (semanticdb-deep-find-tags-for-completion-method table prefix tags)) | |
1222 path find-file-match)) | |
1223 | |
1224 ;;; Brutish Search Routines | |
1225 (defun semanticdb-brute-deep-find-tags-by-name (name &optional path find-file-match) | |
1226 "Search for all tags matching NAME on PATH. | |
1227 See `semanticdb-find-translate-path' for details on PATH. | |
1228 The argument BRUTISH will be set so that searching includes all tables | |
1229 in the current project. | |
1230 FIND-FILE-MATCH indicates that any time a matchi is found, the file | |
1231 associated wit that tag should be loaded into a buffer." | |
1232 (semanticdb-find-tags-collector | |
1233 (lambda (table tags) | |
1234 (semanticdb-deep-find-tags-by-name-method table name tags)) | |
1235 path find-file-match t)) | |
1236 | |
1237 (defun semanticdb-brute-deep-find-tags-for-completion (prefix &optional path find-file-match) | |
1238 "Search for all tags matching PREFIX on PATH. | |
1239 See `semanticdb-find-translate-path' for details on PATH. | |
1240 The argument BRUTISH will be set so that searching includes all tables | |
1241 in the current project. | |
1242 FIND-FILE-MATCH indicates that any time a matchi is found, the file | |
1243 associated wit that tag should be loaded into a buffer." | |
1244 (semanticdb-find-tags-collector | |
1245 (lambda (table tags) | |
1246 (semanticdb-deep-find-tags-for-completion-method table prefix tags)) | |
1247 path find-file-match t)) | |
1248 | |
1249 (defun semanticdb-brute-find-tags-by-class (class &optional path find-file-match) | |
1250 "Search for all tags of CLASS on PATH. | |
1251 See `semanticdb-find-translate-path' for details on PATH. | |
1252 The argument BRUTISH will be set so that searching includes all tables | |
1253 in the current project. | |
1254 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1255 associated with that tag should be loaded into a buffer." | |
1256 (semanticdb-find-tags-collector | |
1257 (lambda (table tags) | |
1258 (semanticdb-find-tags-by-class-method table class tags)) | |
1259 path find-file-match t)) | |
1260 | |
1261 ;;; Specialty Search Routines | |
1262 (defun semanticdb-find-tags-external-children-of-type | |
1263 (type &optional path find-file-match) | |
1264 "Search for all tags defined outside of TYPE w/ TYPE as a parent. | |
1265 See `semanticdb-find-translate-path' for details on PATH. | |
1266 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1267 associated with that tag should be loaded into a buffer." | |
1268 (semanticdb-find-tags-collector | |
1269 (lambda (table tags) | |
1270 (semanticdb-find-tags-external-children-of-type-method table type tags)) | |
1271 path find-file-match)) | |
1272 | |
1273 (defun semanticdb-find-tags-subclasses-of-type | |
1274 (type &optional path find-file-match) | |
1275 "Search for all tags of class type defined that subclass TYPE. | |
1276 See `semanticdb-find-translate-path' for details on PATH. | |
1277 FIND-FILE-MATCH indicates that any time a match is found, the file | |
1278 associated with that tag should be loaded into a buffer." | |
1279 (semanticdb-find-tags-collector | |
1280 (lambda (table tags) | |
1281 (semanticdb-find-tags-subclasses-of-type-method table type tags)) | |
1282 path find-file-match t)) | |
1283 | |
1284 ;;; METHODS | |
1285 ;; | |
1286 ;; Default methods for semanticdb database and table objects. | |
1287 ;; Override these with system databases to as new types of back ends. | |
1288 | |
1289 ;;; Top level Searches | |
1290 (defmethod semanticdb-find-tags-by-name-method ((table semanticdb-abstract-table) name &optional tags) | |
1291 "In TABLE, find all occurances of tags with NAME. | |
1292 Optional argument TAGS is a list of tags to search. | |
1293 Returns a table of all matching tags." | |
1294 (semantic-find-tags-by-name name (or tags (semanticdb-get-tags table)))) | |
1295 | |
1296 (defmethod semanticdb-find-tags-by-name-regexp-method ((table semanticdb-abstract-table) regexp &optional tags) | |
1297 "In TABLE, find all occurances of tags matching REGEXP. | |
1298 Optional argument TAGS is a list of tags to search. | |
1299 Returns a table of all matching tags." | |
1300 (semantic-find-tags-by-name-regexp regexp (or tags (semanticdb-get-tags table)))) | |
1301 | |
1302 (defmethod semanticdb-find-tags-for-completion-method ((table semanticdb-abstract-table) prefix &optional tags) | |
1303 "In TABLE, find all occurances of tags matching PREFIX. | |
1304 Optional argument TAGS is a list of tags to search. | |
1305 Returns a table of all matching tags." | |
1306 (semantic-find-tags-for-completion prefix (or tags (semanticdb-get-tags table)))) | |
1307 | |
1308 (defmethod semanticdb-find-tags-by-class-method ((table semanticdb-abstract-table) class &optional tags) | |
1309 "In TABLE, find all occurances of tags of CLASS. | |
1310 Optional argument TAGS is a list of tags to search. | |
1311 Returns a table of all matching tags." | |
1312 (semantic-find-tags-by-class class (or tags (semanticdb-get-tags table)))) | |
1313 | |
1314 (defmethod semanticdb-find-tags-external-children-of-type-method ((table semanticdb-abstract-table) parent &optional tags) | |
1315 "In TABLE, find all occurances of tags whose parent is the PARENT type. | |
1316 Optional argument TAGS is a list of tags to search. | |
1317 Returns a table of all matching tags." | |
1318 (semantic-find-tags-external-children-of-type parent (or tags (semanticdb-get-tags table)))) | |
1319 | |
1320 (defmethod semanticdb-find-tags-subclasses-of-type-method ((table semanticdb-abstract-table) parent &optional tags) | |
1321 "In TABLE, find all occurances of tags whose parent is the PARENT type. | |
1322 Optional argument TAGS is a list of tags to search. | |
1323 Returns a table of all matching tags." | |
1324 (semantic-find-tags-subclasses-of-type parent (or tags (semanticdb-get-tags table)))) | |
1325 | |
1326 ;;; Deep Searches | |
1327 (defmethod semanticdb-deep-find-tags-by-name-method ((table semanticdb-abstract-table) name &optional tags) | |
1328 "In TABLE, find all occurances of tags with NAME. | |
1329 Search in all tags in TABLE, and all components of top level tags in | |
1330 TABLE. | |
1331 Optional argument TAGS is a list of tags to search. | |
1332 Return a table of all matching tags." | |
1333 (semantic-find-tags-by-name name (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) | |
1334 | |
1335 (defmethod semanticdb-deep-find-tags-by-name-regexp-method ((table semanticdb-abstract-table) regexp &optional tags) | |
1336 "In TABLE, find all occurances of tags matching REGEXP. | |
1337 Search in all tags in TABLE, and all components of top level tags in | |
1338 TABLE. | |
1339 Optional argument TAGS is a list of tags to search. | |
1340 Return a table of all matching tags." | |
1341 (semantic-find-tags-by-name-regexp regexp (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) | |
1342 | |
1343 (defmethod semanticdb-deep-find-tags-for-completion-method ((table semanticdb-abstract-table) prefix &optional tags) | |
1344 "In TABLE, find all occurances of tags matching PREFIX. | |
1345 Search in all tags in TABLE, and all components of top level tags in | |
1346 TABLE. | |
1347 Optional argument TAGS is a list of tags to search. | |
1348 Return a table of all matching tags." | |
1349 (semantic-find-tags-for-completion prefix (semantic-flatten-tags-table (or tags (semanticdb-get-tags table))))) | |
1350 | |
1351 (provide 'semantic/db-find) | |
1352 | |
1353 ;;; semanticdb-find.el ends here |