lisp/cedet/semantic/analyze.el: Add local vars for autoloading.
[bpt/emacs.git] / lisp / cedet / semantic / find.el
CommitLineData
978c25c6 1;;; semantic/find.el --- Search routines for Semantic
1bd95535
CY
2
3;;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
4;;; Free Software Foundation, Inc.
5
6;; Author: Eric M. Ludlam <zappo@gnu.org>
7;; Keywords: syntax
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;; Routines for searching through lists of tags.
27;; There are several groups of tag search routines:
28;;
29;; 1) semantic-brute-find-tag-by-*
30;; These routines use brute force hierarchical search to scan
31;; through lists of tags. They include some parameters
32;; used for compatibility with the semantic 1.x search routines.
33;;
34;; 1.5) semantic-brute-find-first-tag-by-*
35;; Like 1, except seraching stops on the first match for the given
36;; information.
37;;
38;; 2) semantic-find-tag-by-*
39;; These prefered search routines attempt to scan through lists
40;; in an intelligent way based on questions asked.
41;;
42;; 3) semantic-find-*-overlay
43;; These routines use overlays to return tags based on a buffer position.
44;;
45;; 4) ...
46
978c25c6 47(require 'semantic)
1bd95535
CY
48(require 'semantic/tag)
49
50;;; Code:
51\f
52;;; Overlay Search Routines
53;;
54;; These routines provide fast access to tokens based on a buffer that
55;; has parsed tokens in it. Uses overlays to perform the hard work.
3d9d8486
CY
56
57;;;###autoload
1bd95535
CY
58(defun semantic-find-tag-by-overlay (&optional positionormarker buffer)
59 "Find all tags covering POSITIONORMARKER by using overlays.
60If POSITIONORMARKER is nil, use the current point.
61Optional BUFFER is used if POSITIONORMARKER is a number, otherwise the current
62buffer is used. This finds all tags covering the specified position
63by checking for all overlays covering the current spot. They are then sorted
64from largest to smallest via the start location."
65 (save-excursion
66 (when positionormarker
67 (if (markerp positionormarker)
68 (set-buffer (marker-buffer positionormarker))
69 (if (bufferp buffer)
70 (set-buffer buffer))))
71 (let ((ol (semantic-overlays-at (or positionormarker (point))))
72 (ret nil))
73 (while ol
74 (let ((tmp (semantic-overlay-get (car ol) 'semantic)))
75 (when (and tmp
76 ;; We don't need with-position because no tag w/out
77 ;; a position could exist in an overlay.
78 (semantic-tag-p tmp))
79 (setq ret (cons tmp ret))))
80 (setq ol (cdr ol)))
81 (sort ret (lambda (a b) (< (semantic-tag-start a)
82 (semantic-tag-start b)))))))
83
3d9d8486 84;;;###autoload
1bd95535
CY
85(defun semantic-find-tag-by-overlay-in-region (start end &optional buffer)
86 "Find all tags which exist in whole or in part between START and END.
87Uses overlays to determine positin.
88Optional BUFFER argument specifies the buffer to use."
89 (save-excursion
90 (if buffer (set-buffer buffer))
91 (let ((ol (semantic-overlays-in start end))
92 (ret nil))
93 (while ol
94 (let ((tmp (semantic-overlay-get (car ol) 'semantic)))
95 (when (and tmp
96 ;; See above about position
97 (semantic-tag-p tmp))
98 (setq ret (cons tmp ret))))
99 (setq ol (cdr ol)))
100 (sort ret (lambda (a b) (< (semantic-tag-start a)
101 (semantic-tag-start b)))))))
102
3d9d8486 103;;;###autoload
1bd95535
CY
104(defun semantic-find-tag-by-overlay-next (&optional start buffer)
105 "Find the next tag after START in BUFFER.
106If START is in an overlay, find the tag which starts next,
107not the current tag."
108 (save-excursion
109 (if buffer (set-buffer buffer))
110 (if (not start) (setq start (point)))
111 (let ((os start) (ol nil))
112 (while (and os (< os (point-max)) (not ol))
113 (setq os (semantic-overlay-next-change os))
114 (when os
115 ;; Get overlays at position
116 (setq ol (semantic-overlays-at os))
117 ;; find the overlay that belongs to semantic
118 ;; and starts at the found position.
119 (while (and ol (listp ol))
120 (if (and (semantic-overlay-get (car ol) 'semantic)
121 (semantic-tag-p
122 (semantic-overlay-get (car ol) 'semantic))
123 (= (semantic-overlay-start (car ol)) os))
124 (setq ol (car ol)))
125 (when (listp ol) (setq ol (cdr ol))))))
126 ;; convert ol to a tag
127 (when (and ol (semantic-tag-p (semantic-overlay-get ol 'semantic)))
128 (semantic-overlay-get ol 'semantic)))))
129
3d9d8486 130;;;###autoload
1bd95535
CY
131(defun semantic-find-tag-by-overlay-prev (&optional start buffer)
132 "Find the next tag before START in BUFFER.
133If START is in an overlay, find the tag which starts next,
134not the current tag."
135 (save-excursion
136 (if buffer (set-buffer buffer))
137 (if (not start) (setq start (point)))
138 (let ((os start) (ol nil))
139 (while (and os (> os (point-min)) (not ol))
140 (setq os (semantic-overlay-previous-change os))
141 (when os
142 ;; Get overlays at position
143 (setq ol (semantic-overlays-at (1- os)))
144 ;; find the overlay that belongs to semantic
145 ;; and ENDS at the found position.
146 ;;
147 ;; Use end because we are going backward.
148 (while (and ol (listp ol))
149 (if (and (semantic-overlay-get (car ol) 'semantic)
150 (semantic-tag-p
151 (semantic-overlay-get (car ol) 'semantic))
152 (= (semantic-overlay-end (car ol)) os))
153 (setq ol (car ol)))
154 (when (listp ol) (setq ol (cdr ol))))))
155 ;; convert ol to a tag
156 (when (and ol
157 (semantic-tag-p (semantic-overlay-get ol 'semantic)))
158 (semantic-overlay-get ol 'semantic)))))
159
3d9d8486 160;;;###autoload
1bd95535
CY
161(defun semantic-find-tag-parent-by-overlay (tag)
162 "Find the parent of TAG by overlays.
163Overlays are a fast way of finding this information for active buffers."
164 (let ((tag (nreverse (semantic-find-tag-by-overlay
165 (semantic-tag-start tag)))))
166 ;; This is a lot like `semantic-current-tag-parent', but
167 ;; it uses a position to do it's work. Assumes two tags don't share
168 ;; the same start unless they are siblings.
169 (car (cdr tag))))
170
3d9d8486 171;;;###autoload
1bd95535
CY
172(defun semantic-current-tag ()
173 "Return the current tag in the current buffer.
174If there are more than one in the same location, return the
175smallest tag. Return nil if there is no tag here."
176 (car (nreverse (semantic-find-tag-by-overlay))))
177
55b522b2 178;;;###autoload
1bd95535
CY
179(defun semantic-current-tag-parent ()
180 "Return the current tags parent in the current buffer.
181A tag's parent would be a containing structure, such as a type
182containing a field. Return nil if there is no parent."
183 (car (cdr (nreverse (semantic-find-tag-by-overlay)))))
184
185(defun semantic-current-tag-of-class (class)
186 "Return the current (smallest) tags of CLASS in the current buffer.
187If the smallest tag is not of type CLASS, keep going upwards until one
188is found.
189Uses `semantic-tag-class' for classification."
190 (let ((tags (nreverse (semantic-find-tag-by-overlay))))
191 (while (and tags
192 (not (eq (semantic-tag-class (car tags)) class)))
193 (setq tags (cdr tags)))
194 (car tags)))
195\f
196;;; Search Routines
197;;
198;; These are routines that search a single tags table.
199;;
200;; The original API (see COMPATIBILITY section below) in semantic 1.4
201;; had these usage statistics:
202;;
203;; semantic-find-nonterminal-by-name 17
204;; semantic-find-nonterminal-by-name-regexp 8 - Most doing completion
205;; semantic-find-nonterminal-by-position 13
206;; semantic-find-nonterminal-by-token 21
207;; semantic-find-nonterminal-by-type 2
208;; semantic-find-nonterminal-standard 1
209;;
210;; semantic-find-nonterminal-by-function (not in other searches) 1
211;;
212;; New API: As above w/out `search-parts' or `search-includes' arguments.
213;; Extra fcn: Specific to completion which is what -name-regexp is
214;; mostly used for
215;;
216;; As for the sarguments "search-parts" and "search-includes" here
217;; are stats:
218;;
219;; search-parts: 4 - charting x2, find-doc, senator (sans db)
220;;
221;; Implement command to flatten a tag table. Call new API Fcn w/
222;; flattened table for same results.
223;;
224;; search-include: 2 - analyze x2 (sans db)
225;;
226;; Not used effectively. Not to be re-implemented here.
227
228(defsubst semantic--find-tags-by-function (predicate &optional table)
229 "Find tags for which PREDICATE is non-nil in TABLE.
230PREDICATE is a lambda expression which accepts on TAG.
231TABLE is a semantic tags table. See `semantic-something-to-tag-table'."
232 (let ((tags (semantic-something-to-tag-table table))
233 (result nil))
234; (mapc (lambda (tag) (and (funcall predicate tag)
235; (setq result (cons tag result))))
236; tags)
237 ;; A while loop is actually faster. Who knew
238 (while tags
239 (and (funcall predicate (car tags))
240 (setq result (cons (car tags) result)))
241 (setq tags (cdr tags)))
242 (nreverse result)))
243
244;; I can shave off some time by removing the funcall (see above)
245;; and having the question be inlined in the while loop.
246;; Strangely turning the upper level fcns into macros had a larger
247;; impact.
248(defmacro semantic--find-tags-by-macro (form &optional table)
249 "Find tags for which FORM is non-nil in TABLE.
250TABLE is a semantic tags table. See `semantic-something-to-tag-table'."
251 `(let ((tags (semantic-something-to-tag-table ,table))
252 (result nil))
253 (while tags
254 (and ,form
255 (setq result (cons (car tags) result)))
256 (setq tags (cdr tags)))
257 (nreverse result)))
258
259;;; Top level Searches
3d9d8486
CY
260
261;;;###autoload
262(defun semantic-find-first-tag-by-name (name &optional table)
1bd95535
CY
263 "Find the first tag with NAME in TABLE.
264NAME is a string.
265TABLE is a semantic tags table. See `semantic-something-to-tag-table'.
266This routine uses `assoc' to quickly find the first matching entry."
267 (funcall (if semantic-case-fold 'assoc-ignore-case 'assoc)
268 name (semantic-something-to-tag-table table)))
269
270(defmacro semantic-find-tags-by-name (name &optional table)
271 "Find all tags with NAME in TABLE.
272NAME is a string.
273TABLE is a tag table. See `semantic-something-to-tag-table'."
274 `(let ((case-fold-search semantic-case-fold))
275 (semantic--find-tags-by-macro
276 (string= ,name (semantic-tag-name (car tags)))
277 ,table)))
278
279(defmacro semantic-find-tags-for-completion (prefix &optional table)
280 "Find all tags whos name begins with PREFIX in TABLE.
281PREFIX is a string.
282TABLE is a tag table. See `semantic-something-to-tag-table'.
283While it would be nice to use `try-completion' or `all-completions',
284those functions do not return the tags, only a string.
285Uses `compare-strings' for fast comparison."
286 `(let ((l (length ,prefix)))
287 (semantic--find-tags-by-macro
288 (eq (compare-strings ,prefix 0 nil
289 (semantic-tag-name (car tags)) 0 l
290 semantic-case-fold)
291 t)
292 ,table)))
293
294(defmacro semantic-find-tags-by-name-regexp (regexp &optional table)
295 "Find all tags with name matching REGEXP in TABLE.
296REGEXP is a string containing a regular expression,
297TABLE is a tag table. See `semantic-something-to-tag-table'.
298Consider using `semantic-find-tags-for-completion' if you are
299attempting to do completions."
300 `(let ((case-fold-search semantic-case-fold))
301 (semantic--find-tags-by-macro
302 (string-match ,regexp (semantic-tag-name (car tags)))
303 ,table)))
304
305(defmacro semantic-find-tags-by-class (class &optional table)
306 "Find all tags of class CLASS in TABLE.
307CLASS is a symbol representing the class of the token, such as
308'variable, of 'function..
309TABLE is a tag table. See `semantic-something-to-tag-table'."
310 `(semantic--find-tags-by-macro
311 (eq ,class (semantic-tag-class (car tags)))
312 ,table))
313
314(defmacro semantic-find-tags-by-type (type &optional table)
315 "Find all tags of with a type TYPE in TABLE.
316TYPE is a string or tag representing a data type as defined in the
317language the tags were parsed from, such as \"int\", or perhaps
318a tag whose name is that of a struct or class.
319TABLE is a tag table. See `semantic-something-to-tag-table'."
320 `(semantic--find-tags-by-macro
321 (semantic-tag-of-type-p (car tags) ,type)
322 ,table))
323
324(defmacro semantic-find-tags-of-compound-type (&optional table)
325 "Find all tags which are a compound type in TABLE.
326Compound types are structures, or other data type which
327is not of a primitive nature, such as int or double.
328Used in completion."
329 `(semantic--find-tags-by-macro
330 (semantic-tag-type-compound-p (car tags))
331 ,table))
332
55b522b2 333;;;###autoload
1bd95535
CY
334(define-overloadable-function semantic-find-tags-by-scope-protection (scopeprotection parent &optional table)
335 "Find all tags accessable by SCOPEPROTECTION.
336SCOPEPROTECTION is a symbol which can be returned by the method
337`semantic-tag-protection'. A hard-coded order is used to determine a match.
338PARENT is a tag representing the PARENT slot needed for
339`semantic-tag-protection'.
340TABLE is a list of tags (a subset of PARENT members) to scan. If TABLE is nil,
341the type members of PARENT are used.
342See `semantic-tag-protected-p' for details on which tags are returned."
343 (if (not (eq (semantic-tag-class parent) 'type))
344 (signal 'wrong-type-argument '(semantic-find-tags-by-scope-protection
345 parent
346 semantic-tag-class type))
347 (:override)))
348
978c25c6
CY
349(declare-function semantic-tag-protected-p "semantic/tag-ls")
350
1bd95535
CY
351(defun semantic-find-tags-by-scope-protection-default
352 (scopeprotection parent &optional table)
353 "Find all tags accessable by SCOPEPROTECTION.
354SCOPEPROTECTION is a symbol which can be returned by the method
355`semantic-tag-protection'. A hard-coded order is used to determine a match.
356PARENT is a tag representing the PARENT slot needed for
357`semantic-tag-protection'.
358TABLE is a list of tags (a subset of PARENT members) to scan. If TABLE is nil,
359the type members of PARENT are used.
360See `semantic-tag-protected-p' for details on which tags are returned."
361 (if (not table) (setq table (semantic-tag-type-members parent)))
362 (if (null scopeprotection)
363 table
978c25c6 364 (require 'semantic/tag-ls)
1bd95535
CY
365 (semantic--find-tags-by-macro
366 (not (semantic-tag-protected-p (car tags) scopeprotection parent))
367 table)))
368
369(defsubst semantic-find-tags-included (&optional table)
370 "Find all tags in TABLE that are of the 'include class.
371TABLE is a tag table. See `semantic-something-to-tag-table'."
372 (semantic-find-tags-by-class 'include table))
373
374;;; Deep Searches
375
376(defmacro semantic-deep-find-tags-by-name (name &optional table)
377 "Find all tags with NAME in TABLE.
378Search in top level tags, and their components, in TABLE.
379NAME is a string.
380TABLE is a tag table. See `semantic-flatten-tags-table'.
381See also `semantic-find-tags-by-name'."
382 `(semantic-find-tags-by-name
383 ,name (semantic-flatten-tags-table ,table)))
384
385(defmacro semantic-deep-find-tags-for-completion (prefix &optional table)
386 "Find all tags whos name begins with PREFIX in TABLE.
387Search in top level tags, and their components, in TABLE.
388TABLE is a tag table. See `semantic-flatten-tags-table'.
389See also `semantic-find-tags-for-completion'."
390 `(semantic-find-tags-for-completion
391 ,prefix (semantic-flatten-tags-table ,table)))
392
393(defmacro semantic-deep-find-tags-by-name-regexp (regexp &optional table)
394 "Find all tags with name matching REGEXP in TABLE.
395Search in top level tags, and their components, in TABLE.
396REGEXP is a string containing a regular expression,
397TABLE is a tag table. See `semantic-flatten-tags-table'.
398See also `semantic-find-tags-by-name-regexp'.
399Consider using `semantic-deep-find-tags-for-completion' if you are
400attempting to do completions."
401 `(semantic-find-tags-by-name-regexp
402 ,regexp (semantic-flatten-tags-table ,table)))
403
404;;; Specialty Searches
405;;
978c25c6
CY
406(declare-function semantic-tag-external-member-parent "semantic/sort")
407
1bd95535
CY
408(defun semantic-find-tags-external-children-of-type (type &optional table)
409 "Find all tags in whose parent is TYPE in TABLE.
410These tags are defined outside the scope of the original TYPE declaration.
411TABLE is a tag table. See `semantic-something-to-tag-table'."
412 (semantic--find-tags-by-macro
413 (equal (semantic-tag-external-member-parent (car tags))
414 type)
415 table))
416
417(defun semantic-find-tags-subclasses-of-type (type &optional table)
418 "Find all tags of class type in whose parent is TYPE in TABLE.
419These tags are defined outside the scope of the original TYPE declaration.
420TABLE is a tag table. See `semantic-something-to-tag-table'."
421 (semantic--find-tags-by-macro
422 (and (eq (semantic-tag-class (car tags)) 'type)
423 (or (member type (semantic-tag-type-superclasses (car tags)))
424 (member type (semantic-tag-type-interfaces (car tags)))))
425 table))
426\f
427;;
428;; ************************** Compatibility ***************************
429;;
430
431;;; Old Style Brute Force Search Routines
432;;
433;; These functions will search through tags lists explicity for
434;; desired information.
435
436;; The -by-name nonterminal search can use the built in fcn
437;; `assoc', which is faster than looping ourselves, so we will
438;; not use `semantic-brute-find-tag-by-function' to do this,
439;; instead erroring on the side of speed.
440
441(defun semantic-brute-find-first-tag-by-name
442 (name streamorbuffer &optional search-parts search-include)
443 "Find a tag NAME within STREAMORBUFFER. NAME is a string.
444If SEARCH-PARTS is non-nil, search children of tags.
445If SEARCH-INCLUDE was never implemented.
446
447Use `semantic-find-first-tag-by-name' instead."
448 (let* ((stream (semantic-something-to-tag-table streamorbuffer))
449 (assoc-fun (if semantic-case-fold
450 #'assoc-ignore-case
451 #'assoc))
452 (m (funcall assoc-fun name stream)))
453 (if m
454 m
455 (let ((toklst stream)
456 (children nil))
457 (while (and (not m) toklst)
458 (if search-parts
459 (progn
460 (setq children (semantic-tag-components-with-overlays
461 (car toklst)))
462 (if children
463 (setq m (semantic-brute-find-first-tag-by-name
464 name children search-parts search-include)))))
465 (setq toklst (cdr toklst)))
466 (if (not m)
467 ;; Go to dependencies, and search there.
468 nil)
469 m))))
470
471(defmacro semantic-brute-find-tag-by-class
472 (class streamorbuffer &optional search-parts search-includes)
473 "Find all tags with a class CLASS within STREAMORBUFFER.
474CLASS is a symbol representing the class of the tags to find.
475See `semantic-tag-class'.
476Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
477`semantic-brute-find-tag-by-function'.
478
479Use `semantic-find-tag-by-class' instead."
480 `(semantic-brute-find-tag-by-function
481 (lambda (tag) (eq ,class (semantic-tag-class tag)))
482 ,streamorbuffer ,search-parts ,search-includes))
483
484(defmacro semantic-brute-find-tag-standard
485 (streamorbuffer &optional search-parts search-includes)
486 "Find all tags in STREAMORBUFFER which define simple class types.
487See `semantic-tag-class'.
488Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
489`semantic-brute-find-tag-by-function'."
490 `(semantic-brute-find-tag-by-function
491 (lambda (tag) (member (semantic-tag-class tag)
492 '(function variable type)))
493 ,streamorbuffer ,search-parts ,search-includes))
494
495(defun semantic-brute-find-tag-by-type
496 (type streamorbuffer &optional search-parts search-includes)
497 "Find all tags with type TYPE within STREAMORBUFFER.
498TYPE is a string which is the name of the type of the tags returned.
499See `semantic-tag-type'.
500Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
501`semantic-brute-find-tag-by-function'."
502 (semantic-brute-find-tag-by-function
503 (lambda (tag)
504 (let ((ts (semantic-tag-type tag)))
505 (if (and (listp ts)
506 (or (= (length ts) 1)
507 (eq (semantic-tag-class ts) 'type)))
508 (setq ts (semantic-tag-name ts)))
509 (equal type ts)))
510 streamorbuffer search-parts search-includes))
511
512(defun semantic-brute-find-tag-by-type-regexp
513 (regexp streamorbuffer &optional search-parts search-includes)
514 "Find all tags with type matching REGEXP within STREAMORBUFFER.
515REGEXP is a regular expression which matches the name of the type of the
516tags returned. See `semantic-tag-type'.
517Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
518`semantic-brute-find-tag-by-function'."
519 (semantic-brute-find-tag-by-function
520 (lambda (tag)
521 (let ((ts (semantic-tag-type tag)))
522 (if (listp ts)
523 (setq ts
524 (if (eq (semantic-tag-class ts) 'type)
525 (semantic-tag-name ts)
526 (car ts))))
527 (and ts (string-match regexp ts))))
528 streamorbuffer search-parts search-includes))
529
530(defun semantic-brute-find-tag-by-name-regexp
531 (regex streamorbuffer &optional search-parts search-includes)
532 "Find all tags whose name match REGEX in STREAMORBUFFER.
533Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
534`semantic-brute-find-tag-by-function'."
535 (semantic-brute-find-tag-by-function
536 (lambda (tag) (string-match regex (semantic-tag-name tag)))
537 streamorbuffer search-parts search-includes)
538 )
539
540(defun semantic-brute-find-tag-by-property
541 (property value streamorbuffer &optional search-parts search-includes)
542 "Find all tags with PROPERTY equal to VALUE in STREAMORBUFFER.
543Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
544`semantic-brute-find-tag-by-function'."
545 (semantic-brute-find-tag-by-function
546 (lambda (tag) (equal (semantic--tag-get-property tag property) value))
547 streamorbuffer search-parts search-includes)
548 )
549
550(defun semantic-brute-find-tag-by-attribute
551 (attr streamorbuffer &optional search-parts search-includes)
552 "Find all tags with a given ATTR in STREAMORBUFFER.
553ATTR is a symbol key into the attributes list.
554Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
555`semantic-brute-find-tag-by-function'."
556 (semantic-brute-find-tag-by-function
557 (lambda (tag) (semantic-tag-get-attribute tag attr))
558 streamorbuffer search-parts search-includes)
559 )
560
561(defun semantic-brute-find-tag-by-attribute-value
562 (attr value streamorbuffer &optional search-parts search-includes)
563 "Find all tags with a given ATTR equal to VALUE in STREAMORBUFFER.
564ATTR is a symbol key into the attributes list.
565VALUE is the value that ATTR should match.
566Optional argument SEARCH-PARTS and SEARCH-INCLUDES are passed to
567`semantic-brute-find-tag-by-function'."
568 (semantic-brute-find-tag-by-function
569 (lambda (tag) (equal (semantic-tag-get-attribute tag attr) value))
570 streamorbuffer search-parts search-includes)
571 )
572
573(defun semantic-brute-find-tag-by-function
574 (function streamorbuffer &optional search-parts search-includes)
575 "Find all tags for which FUNCTION's value is non-nil within STREAMORBUFFER.
576FUNCTION must return non-nil if an element of STREAM will be included
577in the new list.
578
579If optional argument SEARCH-PARTS is non-nil, all sub-parts of tags
580are searched. The overloadable function `semantic-tag-componenets' is
581used for the searching child lists. If SEARCH-PARTS is the symbol
582'positiononly, then only children that have positional information are
583searched.
584
585If SEARCH-INCLUDES has not been implemented.
586This parameter hasn't be active for a while and is obsolete."
587 (let ((stream (semantic-something-to-tag-table streamorbuffer))
588 (sl nil) ;list of tag children
589 (nl nil) ;new list
590 (case-fold-search semantic-case-fold))
591 (dolist (tag stream)
592 (if (not (semantic-tag-p tag))
593 ;; `semantic-tag-components-with-overlays' can return invalid
594 ;; tags if search-parts is not equal to 'positiononly
595 nil ;; Ignore them!
596 (if (funcall function tag)
597 (setq nl (cons tag nl)))
598 (and search-parts
599 (setq sl (if (eq search-parts 'positiononly)
600 (semantic-tag-components-with-overlays tag)
601 (semantic-tag-components tag))
602 )
603 (setq nl (nconc nl
604 (semantic-brute-find-tag-by-function
605 function sl
606 search-parts))))))
607 (setq nl (nreverse nl))
608 nl))
609
610(defun semantic-brute-find-first-tag-by-function
611 (function streamorbuffer &optional search-parts search-includes)
612 "Find the first tag which FUNCTION match within STREAMORBUFFER.
613FUNCTION must return non-nil if an element of STREAM will be included
614in the new list.
615
616The following parameters were never implemented.
617
618If optional argument SEARCH-PARTS, all sub-parts of tags are searched.
619The overloadable function `semantic-tag-components' is used for
620searching.
621If SEARCH-INCLUDES is non-nil, then all include files are also
622searched for matches."
623 (let ((stream (semantic-something-to-tag-table streamorbuffer))
624 (found nil)
625 (case-fold-search semantic-case-fold))
626 (while (and (not found) stream)
627 (if (funcall function (car stream))
628 (setq found (car stream)))
629 (setq stream (cdr stream)))
630 found))
631
632
633;;; Old Positional Searches
634;;
635;; Are these useful anymore?
636;;
637(defun semantic-brute-find-tag-by-position (position streamorbuffer
638 &optional nomedian)
639 "Find a tag covering POSITION within STREAMORBUFFER.
640POSITION is a number, or marker. If NOMEDIAN is non-nil, don't do
641the median calculation, and return nil."
642 (save-excursion
643 (if (markerp position) (set-buffer (marker-buffer position)))
644 (let* ((stream (if (bufferp streamorbuffer)
645 (save-excursion
646 (set-buffer streamorbuffer)
647 (semantic-fetch-tags))
648 streamorbuffer))
649 (prev nil)
650 (found nil))
651 (while (and stream (not found))
652 ;; perfect fit
653 (if (and (>= position (semantic-tag-start (car stream)))
654 (<= position (semantic-tag-end (car stream))))
655 (setq found (car stream))
656 ;; Median between to objects.
657 (if (and prev (not nomedian)
658 (>= position (semantic-tag-end prev))
659 (<= position (semantic-tag-start (car stream))))
660 (let ((median (/ (+ (semantic-tag-end prev)
661 (semantic-tag-start (car stream)))
662 2)))
663 (setq found
664 (if (> position median)
665 (car stream)
666 prev)))))
667 ;; Next!!!
668 (setq prev (car stream)
669 stream (cdr stream)))
670 found)))
671
672(defun semantic-brute-find-innermost-tag-by-position
673 (position streamorbuffer &optional nomedian)
674 "Find a list of tags covering POSITION within STREAMORBUFFER.
675POSITION is a number, or marker. If NOMEDIAN is non-nil, don't do
676the median calculation, and return nil.
677This function will find the topmost item, and recurse until no more
678details are available of findable."
679 (let* ((returnme nil)
680 (current (semantic-brute-find-tag-by-position
681 position streamorbuffer nomedian))
682 (nextstream (and current
683 (if (eq (semantic-tag-class current) 'type)
684 (semantic-tag-type-members current)
685 nil))))
686 (while nextstream
687 (setq returnme (cons current returnme))
688 (setq current (semantic-brute-find-tag-by-position
689 position nextstream nomedian))
690 (setq nextstream (and current
691 ;; NOTE TO SELF:
692 ;; Looking at this after several years away,
693 ;; what does this do???
694 (if (eq (semantic-tag-class current) 'token)
695 (semantic-tag-type-members current)
696 nil))))
697 (nreverse (cons current returnme))))
698\f
699;;; Compatibility Aliases
700(semantic-alias-obsolete 'semantic-find-nonterminal-by-overlay
701 'semantic-find-tag-by-overlay)
702
703(semantic-alias-obsolete 'semantic-find-nonterminal-by-overlay-in-region
704 'semantic-find-tag-by-overlay-in-region)
705
706(semantic-alias-obsolete 'semantic-find-nonterminal-by-overlay-next
707 'semantic-find-tag-by-overlay-next)
708
709(semantic-alias-obsolete 'semantic-find-nonterminal-by-overlay-prev
710 'semantic-find-tag-by-overlay-prev)
711
712(semantic-alias-obsolete 'semantic-find-nonterminal-parent-by-overlay
713 'semantic-find-tag-parent-by-overlay)
714
715(semantic-alias-obsolete 'semantic-current-nonterminal
716 'semantic-current-tag)
717
718(semantic-alias-obsolete 'semantic-current-nonterminal-parent
719 'semantic-current-tag-parent)
720
721(semantic-alias-obsolete 'semantic-current-nonterminal-of-type
722 'semantic-current-tag-of-class)
723
724(semantic-alias-obsolete 'semantic-find-nonterminal-by-name
725 'semantic-brute-find-first-tag-by-name)
726
727(semantic-alias-obsolete 'semantic-find-nonterminal-by-token
728 'semantic-brute-find-tag-by-class)
729
730(semantic-alias-obsolete 'semantic-find-nonterminal-standard
731 'semantic-brute-find-tag-standard)
732
733(semantic-alias-obsolete 'semantic-find-nonterminal-by-type
734 'semantic-brute-find-tag-by-type)
735
736(semantic-alias-obsolete 'semantic-find-nonterminal-by-type-regexp
737 'semantic-brute-find-tag-by-type-regexp)
738
739(semantic-alias-obsolete 'semantic-find-nonterminal-by-name-regexp
740 'semantic-brute-find-tag-by-name-regexp)
741
742(semantic-alias-obsolete 'semantic-find-nonterminal-by-property
743 'semantic-brute-find-tag-by-property)
744
745(semantic-alias-obsolete 'semantic-find-nonterminal-by-extra-spec
746 'semantic-brute-find-tag-by-attribute)
747
748(semantic-alias-obsolete 'semantic-find-nonterminal-by-extra-spec-value
749 'semantic-brute-find-tag-by-attribute-value)
750
751(semantic-alias-obsolete 'semantic-find-nonterminal-by-function
752 'semantic-brute-find-tag-by-function)
753
754(semantic-alias-obsolete 'semantic-find-nonterminal-by-function-first-match
755 'semantic-brute-find-first-tag-by-function)
756
757(semantic-alias-obsolete 'semantic-find-nonterminal-by-position
758 'semantic-brute-find-tag-by-position)
759
760(semantic-alias-obsolete 'semantic-find-innermost-nonterminal-by-position
761 'semantic-brute-find-innermost-tag-by-position)
762
763;;; TESTING
764;;
765(defun semantic-find-benchmark ()
766 "Run some simple benchmarks to see how we are doing.
767Optional argument ARG is the number of iterations to run."
768 (interactive)
769 (require 'benchmark)
770 (let ((f-name nil)
771 (b-name nil)
772 (f-comp)
773 (b-comp)
774 (f-regex)
775 )
776 (garbage-collect)
777 (setq f-name
778 (benchmark-run-compiled
779 1000 (semantic-find-first-tag-by-name "class3"
780 "test/test.cpp")))
781 (garbage-collect)
782 (setq b-name
783 (benchmark-run-compiled
784 1000 (semantic-brute-find-first-tag-by-name "class3"
785 "test/test.cpp")))
786 (garbage-collect)
787 (setq f-comp
788 (benchmark-run-compiled
789 1000 (semantic-find-tags-for-completion "method"
790 "test/test.cpp")))
791 (garbage-collect)
792 (setq b-comp
793 (benchmark-run-compiled
794 1000 (semantic-brute-find-tag-by-name-regexp "^method"
795 "test/test.cpp")))
796 (garbage-collect)
797 (setq f-regex
798 (benchmark-run-compiled
799 1000 (semantic-find-tags-by-name-regexp "^method"
800 "test/test.cpp")))
801
802 (message "Name [new old] [ %.3f %.3f ] Complete [newc/new old] [ %.3f/%.3f %.3f ]"
803 (car f-name) (car b-name)
804 (car f-comp) (car f-regex)
805 (car b-comp))
806 ))
807
1bd95535
CY
808(provide 'semantic/find)
809
3d9d8486
CY
810;; Local variables:
811;; generated-autoload-file: "loaddefs.el"
812;; generated-autoload-feature: semantic/loaddefs
813;; End:
814
978c25c6 815;;; semantic/find.el ends here