1
2
3
4
5
6 """
7 defines base class for L{namespace_t} and L{class_t} classes
8 """
9
10 import time
11 import algorithm
12 import filtering
13 import templates
14 import declaration
15 import mdecl_wrapper
16 from pygccxml import utils
17 import matcher as matcher_module
18
20 """Base class for L{namespace_t} and L{class_t} classes.
21
22 This is the base class for all declaration classes that may have
23 children nodes. The children can be accessed via the C{declarations}
24 property.
25
26 Also this class provides "get/select/find" interface. Using this class you
27 can get instance or instances of internal declaration(s).
28
29 You can find declaration(s) using next criteria:
30 1. name - declaration name, could be full qualified name
31 2. header_dir - directory, to which belongs file, that the declaration was declarated in.
32 header_dir should be absolute path.
33 3. header_file - file that the declaration was declarated in.
34 4. function - user ( your ) custom criteria. The interesting thing is that
35 this function will be joined with other arguments ( criteria ).
36 5. recursive - the search declaration range, if True will be search in
37 internal declarations too.
38
39 Every "select" API you can invoke and pass as first argument at declaration
40 name or function. This class will find out correctly what argument represents.
41
42 Example::
43 ns - referrers to global namespace
44 ns.member_function( "do_something ) - will return reference to member
45 function named "do_something". If there is no such function exception
46 will be raised. If there is more then one function exception will be
47 raised too.
48
49 Example 2::
50 ns - referers to global namespace
51 do_smths = ns.member_functions( "do_something ) - will return instance
52 of L{mdecl_wrapper_t} object. This object allows you few things:
53
54 1. To iterate on selected declarations
55 2. To set some property to desired value using one line of code only:
56 do_smths.call_policies = x
57 3. To call some function on every instance using one line of code:
58 do_smths.exclude()
59
60 Pay attention: you can not use "get" functions or properties.
61 """
62
63 RECURSIVE_DEFAULT = True
64 ALLOW_EMPTY_MDECL_WRAPPER = False
65
66 declaration_not_found_t = matcher_module.matcher.declaration_not_found_t
67 multiple_declarations_found_t = matcher_module.matcher.multiple_declarations_found_t
68
69 _impl_matchers = {}
70 _impl_decl_types = {}
71 _impl_all_decl_types = []
72
74 declaration.declaration_t.__init__( self, name )
75
76 self._optimized = False
77 self._type2decls = {}
78 self._type2name2decls = {}
79 self._type2decls_nr = {}
80 self._type2name2decls_nr = {}
81 self._all_decls = None
82 self._all_decls_not_recursive = None
83
86 _logger = property( _get_logger, doc="reference to C{queries_engine} logger" )
87
89 """implementation details"""
90 raise NotImplementedError()
91
93 """implementation details"""
94 items = []
95 if self._optimized:
96
97 items.append( self._sorted_list( self._all_decls_not_recursive ) )
98 else:
99 items.append( self._sorted_list( self.declarations ) )
100 items.extend( self._get__cmp__scope_items() )
101 return items
102
108
109
110
111
112
113
114
115
116
118 raise NotImplementedError()
119
121 if True == self._optimized:
122 return self._all_decls_not_recursive
123 else:
124 return self._get_declarations_impl()
125 declarations = property( _get_declarations, doc="list of children L{declarations<declaration_t>}" )
126
128 raise NotImplementedError()
129
148
150 """Cleans query optimizer state"""
151 self._optimized = False
152 self._type2decls = {}
153 self._type2name2decls = {}
154 self._type2decls_nr = {}
155 self._type2name2decls_nr = {}
156 self._all_decls = None
157 self._all_decls_not_recursive = None
158
159 map( lambda decl: decl.clear_optimizer()
160 , filter( lambda decl: isinstance( decl, scopedef_t )
161 , self.declarations ) )
162
164 """Initializes query optimizer state.
165 There are 4 internals hash tables:
166 1. from type to declarations
167 2. from type to declarations for non-recursive queries
168 3. from type to name to declarations
169 4. from type to name to declarations for non-recursive queries
170
171 Almost every query includes declaration type information. Also very
172 common query is to search some declaration(s) by name or full name.
173 Those hashtables allows to search declaration very quick.
174 """
175 if self.name == '::':
176 self._logger.debug( "preparing data structures for query optimizer - started" )
177 start_time = time.clock()
178
179 self.clear_optimizer()
180
181 for dtype in scopedef_t._impl_all_decl_types:
182 self._type2decls[ dtype ] = []
183 self._type2decls_nr[ dtype ] = []
184 self._type2name2decls[ dtype ] = {}
185 self._type2name2decls_nr[ dtype ] = {}
186
187 self._all_decls_not_recursive = self.declarations
188 self._all_decls = algorithm.make_flatten( self._all_decls_not_recursive )
189 for decl in self._all_decls:
190 types = self.__decl_types( decl )
191 for type_ in types:
192 self._type2decls[ type_ ].append( decl )
193 name2decls = self._type2name2decls[ type_ ]
194 if not name2decls.has_key( decl.name ):
195 name2decls[ decl.name ] = []
196 name2decls[ decl.name ].append( decl )
197 if self is decl.parent:
198 self._type2decls_nr[ type_ ].append( decl )
199 name2decls_nr = self._type2name2decls_nr[ type_ ]
200 if not name2decls_nr.has_key( decl.name ):
201 name2decls_nr[ decl.name ] = []
202 name2decls_nr[ decl.name ].append( decl )
203
204 map( lambda decl: decl.init_optimizer()
205 , filter( lambda decl: isinstance( decl, scopedef_t )
206 , self._all_decls_not_recursive ) )
207 if self.name == '::':
208 self._logger.debug( "preparing data structures for query optimizer - done( %f seconds ). "
209 % ( time.clock() - start_time ) )
210 self._optimized = True
211
213 if callable( name ):
214 return name
215 else:
216 return function
217
219 """implementation details"""
220 def add_operator( sym ):
221 if 'new' in sym or 'delete' in sym:
222 return 'operator ' + sym
223 else:
224 return 'operator'+ sym
225 if callable( name ) and None is function:
226 name = None
227 if name:
228 if not 'operator' in name:
229 name = add_operator( name )
230 return name
231 elif symbol:
232 return add_operator( symbol )
233 return name
234
238
239
240
241
242
243
244
246 """implementation details"""
247 if callable( keywds['name'] ) and None is keywds['function']:
248 keywds['function'] = keywds['name']
249 keywds['name'] = None
250 return keywds
251
253 """implementation details"""
254 if None is keywds[ 'recursive' ]:
255 return self.RECURSIVE_DEFAULT
256 else:
257 return keywds[ 'recursive' ]
258
260 """implementation details"""
261 if None is keywds[ 'allow_empty' ]:
262 return self.ALLOW_EMPTY_MDECL_WRAPPER
263 else:
264 return keywds[ 'allow_empty' ]
265
267 """implementation details"""
268 if keywds.has_key( 'decl_type' ):
269 return keywds['decl_type']
270
271 matcher_args = keywds.copy()
272 del matcher_args['function']
273 del matcher_args['recursive']
274 if matcher_args.has_key('allow_empty'):
275 del matcher_args['allow_empty']
276
277 matcher = match_class( **matcher_args )
278 if matcher.decl_type:
279 return matcher.decl_type
280 return None
281
283 """implementation details"""
284 matcher_args = keywds.copy()
285 del matcher_args['function']
286 del matcher_args['recursive']
287 if matcher_args.has_key('allow_empty'):
288 del matcher_args['allow_empty']
289
290 matcher = match_class( **matcher_args )
291 if keywds['function']:
292 self._logger.debug( 'running query: %s and <user defined function>' % str( matcher ) )
293 return lambda decl: matcher( decl ) and keywds['function'](decl)
294 else:
295 self._logger.debug( 'running query: %s' % str( matcher ) )
296 return matcher
297
299 """implementation details"""
300 if not self._optimized:
301 self._logger.debug( 'running non optimized query - optimization has not been done' )
302 decls = self.declarations
303 if recursive:
304 decls = algorithm.make_flatten( self.declarations )
305 if decl_type:
306 decls = filter( lambda d: isinstance( d, decl_type ), decls )
307 return decls
308
309 if name and templates.is_instantiation( name ):
310
311
312 name = None
313
314 if name and decl_type:
315 matcher = scopedef_t._impl_matchers[ scopedef_t.decl ]( name=name )
316 if matcher.is_full_name():
317 name = matcher.decl_name_only
318 if recursive:
319 self._logger.debug( 'query has been optimized on type and name' )
320 if self._type2name2decls[decl_type].has_key( name ):
321 return self._type2name2decls[decl_type][name]
322 else:
323 return []
324 else:
325 self._logger.debug( 'non recursive query has been optimized on type and name' )
326 if self._type2name2decls_nr[decl_type].has_key( name ):
327 return self._type2name2decls_nr[decl_type][name]
328 else:
329 return []
330 elif decl_type:
331 if recursive:
332 self._logger.debug( 'query has been optimized on type' )
333 return self._type2decls[ decl_type ]
334 else:
335 self._logger.debug( 'non recursive query has been optimized on type' )
336 return self._type2decls_nr[ decl_type ]
337 else:
338 if recursive:
339 self._logger.debug( 'query has not been optimized ( hint: query does not contain type and/or name )' )
340 return self._all_decls
341 else:
342 self._logger.debug( 'non recursive query has not been optimized ( hint: query does not contain type and/or name )' )
343 return self._all_decls_not_recursive
344
346 """implementation details"""
347 self._logger.debug( 'find single query execution - started' )
348 start_time = time.clock()
349 norm_keywds = self.__normalize_args( **keywds )
350 matcher = self.__create_matcher( match_class, **norm_keywds )
351 dtype = self.__findout_decl_type( match_class, **norm_keywds )
352 recursive_ = self.__findout_recursive( **norm_keywds )
353 decls = self.__findout_range( norm_keywds['name'], dtype, recursive_ )
354 found = matcher_module.matcher.get_single( matcher, decls, False )
355 self._logger.debug( 'find single query execution - done( %f seconds )' % ( time.clock() - start_time ) )
356 return found
357
359 """implementation details"""
360 self._logger.debug( 'find all query execution - started' )
361 start_time = time.clock()
362 norm_keywds = self.__normalize_args( **keywds )
363 matcher = self.__create_matcher( match_class, **norm_keywds )
364 dtype = self.__findout_decl_type( match_class, **norm_keywds )
365 recursive_ = self.__findout_recursive( **norm_keywds )
366 allow_empty = self.__findout_allow_empty( **norm_keywds )
367 decls = self.__findout_range( norm_keywds['name'], dtype, recursive_ )
368 found = matcher_module.matcher.find( matcher, decls, False )
369 mfound = mdecl_wrapper.mdecl_wrapper_t( found )
370 self._logger.debug( '%d declaration(s) that match query' % len(mfound) )
371 self._logger.debug( 'find single query execution - done( %f seconds )'
372 % ( time.clock() - start_time ) )
373 if not mfound and not allow_empty:
374 raise RuntimeError( "Multi declaration query returned 0 declarations." )
375 return mfound
376
377 - def decl( self, name=None, function=None, decl_type=None, header_dir=None, header_file=None, recursive=None ):
378 """returns reference to declaration, that is matched defined criterias"""
379 return self._find_single( self._impl_matchers[ scopedef_t.decl ]
380 , name=name
381 , function=function
382 , decl_type=decl_type
383 , header_dir=header_dir
384 , header_file=header_file
385 , recursive=recursive)
386
387 - def decls( self, name=None, function=None, decl_type=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
388 """returns a set of declarations, that are matched defined criterias"""
389 return self._find_multiple( self._impl_matchers[ scopedef_t.decl ]
390 , name=name
391 , function=function
392 , decl_type=decl_type
393 , header_dir=header_dir
394 , header_file=header_file
395 , recursive=recursive
396 , allow_empty=allow_empty)
397
398 - def class_( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ):
407
408 - def classes( self, name=None, function=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
418
419 - def variable( self, name=None, function=None, type=None, header_dir=None, header_file=None, recursive=None ):
428 var = variable
429
430 - def variables( self, name=None, function=None, type=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
431 """returns a set of variable declarations, that are matched defined criterias"""
432 return self._find_multiple( self._impl_matchers[ scopedef_t.variable ]
433 , name=name
434 , function=function
435 , type=type
436 , header_dir=header_dir
437 , header_file=header_file
438 , recursive=recursive
439 , allow_empty=allow_empty)
440 vars = variables
441
442 - def calldef( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
453
454 - def calldefs( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
455 """returns a set of calldef declarations, that are matched defined criterias"""
456 return self._find_multiple( self._impl_matchers[ scopedef_t.calldef ]
457 , name=name
458 , function=function
459 , decl_type=self._impl_decl_types[ scopedef_t.calldef ]
460 , return_type=return_type
461 , arg_types=arg_types
462 , header_dir=header_dir
463 , header_file=header_file
464 , recursive=recursive
465 , allow_empty=allow_empty)
466
467 - def operator( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
468 """returns reference to operator declaration, that is matched defined criterias"""
469 return self._find_single( self._impl_matchers[ scopedef_t.operator ]
470 , name=self._build_operator_name( name, function, symbol )
471 , symbol=symbol
472 , function=self._build_operator_function( name, function )
473 , decl_type=self._impl_decl_types[ scopedef_t.operator ]
474 , return_type=return_type
475 , arg_types=arg_types
476 , header_dir=header_dir
477 , header_file=header_file
478 , recursive=recursive )
479
480 - def operators( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
481 """returns a set of operator declarations, that are matched defined criterias"""
482 return self._find_multiple( self._impl_matchers[ scopedef_t.operator ]
483 , name=self._build_operator_name( name, function, symbol )
484 , symbol=symbol
485 , function=self._build_operator_function( name, function )
486 , decl_type=self._impl_decl_types[ scopedef_t.operator ]
487 , return_type=return_type
488 , arg_types=arg_types
489 , header_dir=header_dir
490 , header_file=header_file
491 , recursive=recursive
492 , allow_empty=allow_empty)
493
494 - def member_function( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
505 mem_fun = member_function
506
507 - def member_functions( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
508 """returns a set of member function declarations, that are matched defined criterias"""
509 return self._find_multiple( self._impl_matchers[ scopedef_t.member_function ]
510 , name=name
511 , function=function
512 , decl_type=self._impl_decl_types[ scopedef_t.member_function ]
513 , return_type=return_type
514 , arg_types=arg_types
515 , header_dir=header_dir
516 , header_file=header_file
517 , recursive=recursive
518 , allow_empty=allow_empty)
519 mem_funs = member_functions
520
521 - def constructor( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
532
533 - def constructors( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
534 """returns a set of constructor declarations, that are matched defined criterias"""
535 return self._find_multiple( self._impl_matchers[ scopedef_t.constructor ]
536 , name=name
537 , function=function
538 , decl_type=self._impl_decl_types[ scopedef_t.constructor ]
539 , return_type=return_type
540 , arg_types=arg_types
541 , header_dir=header_dir
542 , header_file=header_file
543 , recursive=recursive
544 , allow_empty=allow_empty)
545
546 - def member_operator( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
547 """returns reference to member operator declaration, that is matched defined criterias"""
548 return self._find_single( self._impl_matchers[ scopedef_t.member_operator ]
549 , name=self._build_operator_name( name, function, symbol )
550 , symbol=symbol
551 , function=self._build_operator_function( name, function )
552 , decl_type=self._impl_decl_types[ scopedef_t.member_operator ]
553 , return_type=return_type
554 , arg_types=arg_types
555 , header_dir=header_dir
556 , header_file=header_file
557 , recursive=recursive )
558 mem_oper = member_operator
559 - def member_operators( self, name=None, function=None, symbol=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
560 """returns a set of member operator declarations, that are matched defined criterias"""
561 return self._find_multiple( self._impl_matchers[ scopedef_t.member_operator ]
562 , name=self._build_operator_name( name, function, symbol )
563 , symbol=symbol
564 , function=self._build_operator_function( name, function )
565 , decl_type=self._impl_decl_types[ scopedef_t.member_operator ]
566 , return_type=return_type
567 , arg_types=arg_types
568 , header_dir=header_dir
569 , header_file=header_file
570 , recursive=recursive
571 , allow_empty=allow_empty)
572 mem_opers = member_operators
573
574 - def casting_operator( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None ):
585
586 - def casting_operators( self, name=None, function=None, return_type=None, arg_types=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
587 """returns a set of casting operator declarations, that are matched defined criterias"""
588 return self._find_multiple( self._impl_matchers[ scopedef_t.casting_operator ]
589 , name=name
590 , function=function
591 , decl_type=self._impl_decl_types[ scopedef_t.casting_operator ]
592 , return_type=return_type
593 , arg_types=arg_types
594 , header_dir=header_dir
595 , header_file=header_file
596 , recursive=recursive
597 , allow_empty=allow_empty)
598
599 - def enumeration( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ):
608
609 enum = enumeration
610 """adding small aliase to enumeration method"""
611
612 - def enumerations( self, name=None, function=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
622
623 enums = enumerations
624
625 - def typedef( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ):
634
635 - def typedefs( self, name=None, function=None, header_dir=None, header_file=None, recursive=None, allow_empty=None ):
645
647 """ Allow simple name based find of decls. Internally just calls decls() method.
648 @param name_or_function Name of decl to lookup or finder function.
649 """
650 return self.decls(name_or_function)
651