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