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