Home | Trees | Indices | Help |
|
---|
|
1 # Copyright 2004-2008 Roman Yakovenko. 2 # Distributed under the Boost Software License, Version 1.0. (See 3 # accompanying file LICENSE_1_0.txt or copy at 4 # http://www.boost.org/LICENSE_1_0.txt) 5 6 """ 7 defines classes, that describes C++ classes 8 9 This modules contains definition for next C++ declarations: 10 - class definition 11 - class declaration 12 - small helper class for describing C++ class hierarchy 13 """ 14 15 import scopedef 16 import itertools 17 import compilers 18 import algorithm 19 import declaration 20 import dependencies 21 from pygccxml import utils24 """class that defines "access" constants""" 25 PUBLIC = "public" 26 PRIVATE = "private" 27 PROTECTED = "protected" 28 ALL = [ PUBLIC, PRIVATE, PROTECTED ]2931 """class that defines "class" type constants""" 32 CLASS = "class" 33 STRUCT = "struct" 34 UNION = "union" 35 ALL = [ CLASS, STRUCT, UNION ]3638 import templates 39 import container_traits #prevent cyclic dependencies 40 ct = container_traits.find_container_traits( name ) 41 if ct: 42 return ct.remove_defaults( name ) 43 elif templates.is_instantiation( name ): 44 tmpl_name, args = templates.split( name ) 45 for i, arg_name in enumerate( args ): 46 args[i] = get_partial_name( arg_name.strip() ) 47 return templates.join( tmpl_name, args ) 48 else: 49 return name5053 """describes class relationship"""10555 """creates class that contains partial information about class relationship""" 56 if related_class: 57 assert( isinstance( related_class, class_t ) ) 58 self._related_class = related_class 59 if access: 60 assert( access in ACCESS_TYPES.ALL) 61 self._access=access 62 self._is_virtual = is_virtual6365 if not isinstance( other, hierarchy_info_t ): 66 return False 67 return algorithm.declaration_path( self.related_class ) == algorithm.declaration_path( other.related_class ) \ 68 and self.access == other.access \ 69 and self.is_virtual == other.is_virtual7072 return not self.__eq__( other )7375 if not isinstance( other, self.__class__ ): 76 return self.__class__.__name__ < other.__class__.__name__ 77 return ( algorithm.declaration_path( self.related_class ), self.access, self.is_virtual ) \ 78 < ( algorithm.declaration_path( other.related_class ), other.access, self.is_virtual )79 86 related_class = property( _get_related_class, _set_related_class 87 , doc="reference to base or derived L{class<class_t>}") 88 94 access = property( _get_access, _set_access ) 95 access_type = property( _get_access, _set_access 96 , doc="describes L{hierarchy type<ACCESS_TYPES>}") 97 98 #TODO: check whether GCC XML support this and if so parser this information 103 is_virtual = property( _get_is_virtual, _set_is_virtual 104 , doc="indicates whether the inheritance is virtual or not")108 """describes class declaration"""141110 """creates class that describes C++ class declaration( and not definition )""" 111 declaration.declaration_t.__init__( self, name ) 112 self._aliases = [] 113 self._container_traits = None 114 self._container_traits_set = False115 119 122 127 aliases = property( _get_aliases, _set_aliases 128 , doc="List of L{aliases<typedef_t>} to this instance") 129 130 @property132 """reference to L{container traits<container_traits.py>} or None""" 133 if self._container_traits_set == False: 134 import container_traits #prevent cyclic dependencies 135 self._container_traits_set = True 136 self._container_traits = container_traits.find_container_traits( self ) 137 return self._container_traits138143 """describes class definition""" 144 145 USE_DEMANGLED_AS_NAME = True530 531 532 class_types = ( class_t, class_declaration_t ) 533147 """creates class that describes C++ class definition""" 148 scopedef.scopedef_t.__init__( self, name ) 149 if class_type: 150 assert( class_type in CLASS_TYPES.ALL ) 151 self._class_type = class_type 152 self._bases = [] 153 self._derived = [] 154 self._is_abstract = is_abstract 155 self._public_members = [] 156 self._private_members = [] 157 self._protected_members = [] 158 self._aliases = [] 159 self._byte_size = 0 160 self._byte_align = 0 161 self._container_traits = None 162 self._container_traits_set = False 163 self._recursive_bases = None 164 self._recursive_derived = None165167 if not self._name: #class with empty name 168 return self._name 169 elif class_t.USE_DEMANGLED_AS_NAME and self.demangled and 'GCC' in self.compiler: 170 if not self.cache.demangled_name: 171 fname = algorithm.full_name( self.parent ) 172 if fname.startswith( '::' ) and not self.demangled.startswith( '::' ): 173 fname = fname[2:] 174 if self.demangled.startswith( fname ): 175 tmp = self.demangled[ len( fname ): ] #demangled::name 176 if tmp.startswith( '::' ): 177 tmp = tmp[2:] 178 if '<' not in tmp and '<' in self._name: 179 #we have template class, but for some reason demangled 180 #name doesn't contain any template 181 #This happens for std::string class, but this breaks 182 #other cases, because this behaviour is not consistent 183 self.cache.demangled_name = self._name 184 return self.cache.demangled_name 185 else: 186 self.cache.demangled_name = tmp 187 return tmp 188 else: 189 self.cache.demangled_name = self._name 190 return self._name 191 else: 192 return self.cache.demangled_name 193 else: 194 return self._name195197 name = algorithm.full_name(self) 198 if name[:2]=="::": 199 name = name[2:] 200 return "%s [%s]"%(name, self.class_type)201203 """implementation details""" 204 return [ self.class_type 205 , self._sorted_list( [ algorithm.declaration_path( base.related_class ) for base in self.bases ] ) 206 , self._sorted_list( [ algorithm.declaration_path( derive.related_class ) for derive in self.derived ] ) 207 , self.is_abstract 208 , self._sorted_list( self.public_members ) 209 , self._sorted_list( self.private_members ) 210 , self._sorted_list( self.protected_members ) ]211213 if not scopedef.scopedef_t.__eq__( self, other ): 214 return False 215 return self.class_type == other.class_type \ 216 and self._sorted_list( [ algorithm.declaration_path( base.related_class ) for base in self.bases ] ) \ 217 == other._sorted_list( [ algorithm.declaration_path( base.related_class ) for base in other.bases ] ) \ 218 and self._sorted_list( [ algorithm.declaration_path( derive.related_class ) for derive in self.derived ] ) \ 219 == other._sorted_list( [ algorithm.declaration_path( derive.related_class ) for derive in other.derived ] ) \ 220 and self.is_abstract == other.is_abstract \ 221 and self._sorted_list( self.public_members ) \ 222 == other._sorted_list( other.public_members ) \ 223 and self._sorted_list( self.private_members ) \ 224 == other._sorted_list( other.private_members ) \ 225 and self._sorted_list( self.protected_members ) \ 226 == self._sorted_list( other.protected_members )227231 if new_class_type: 232 assert( new_class_type in CLASS_TYPES.ALL ) 233 self._class_type = new_class_type234 class_type = property( _get_class_type, _set_class_type 235 , doc="describes class L{type<CLASS_TYPES>}") 236 241 bases = property( _get_bases, _set_bases 242 , doc="list of L{base classes<hierarchy_info_t>}") 243 244 @property246 """list of all L{base classes<hierarchy_info_t>}""" 247 if self._recursive_bases is None: 248 to_go = self.bases[:] 249 all_bases = [] 250 while to_go: 251 base = to_go.pop() 252 if base not in all_bases: 253 all_bases.append( base ) 254 to_go.extend( base.related_class.bases ) 255 self._recursive_bases = all_bases 256 return self._recursive_bases257 262 derived = property( _get_derived, _set_derived 263 , doc="list of L{derived classes<hierarchy_info_t>}") 264 265 @property267 """list of all L{derive classes<hierarchy_info_t>}""" 268 if self._recursive_derived is None: 269 to_go = self.derived[:] 270 all_derived = [] 271 while to_go: 272 derive = to_go.pop() 273 if derive not in all_derived: 274 all_derived.append( derive ) 275 to_go.extend( derive.related_class.derived ) 276 self._recursive_derived = all_derived 277 return self._recursive_derived278280 if self.compiler == compilers.MSVC_PDB_9: 281 #prevent cyclic dependencies 282 import calldef 283 import function_traits 284 from matchers import virtuality_type_matcher_t as vtmatcher_t 285 filter_pv = vtmatcher_t( calldef.VIRTUALITY_TYPES.PURE_VIRTUAL ) 286 if self.calldefs( filter_pv, recursive=False, allow_empty=True ): 287 return True 288 filter_npv = vtmatcher_t( calldef.VIRTUALITY_TYPES.VIRTUAL ) \ 289 | vtmatcher_t( calldef.VIRTUALITY_TYPES.NOT_VIRTUAL ) 290 pv_calldefs = [] 291 npv_calldefs = [] 292 293 npv_calldefs.extend( self.calldefs( filter_npv, recursive=False, allow_empty=True ) ) 294 for base in self.recursive_bases: 295 cls = base.related_class 296 pv_calldefs.extend( cls.calldefs( filter_pv, recursive=False, allow_empty=True ) ) 297 npv_calldefs.extend( cls.calldefs( filter_npv, recursive=False, allow_empty=True ) ) 298 299 for pure_virtual in pv_calldefs: 300 impl_found = filter( lambda f: function_traits.is_same_function( pure_virtual, f ) 301 , npv_calldefs ) 302 if not impl_found: 303 return True 304 return False 305 else: 306 return self._is_abstract308 self._is_abstract = is_abstract309 is_abstract = property( _get_is_abstract, _set_is_abstract 310 ,doc="describes whether class abstract or not" ) 311 316 public_members = property( _get_public_members, _set_public_members 317 , doc="list of all public L{members<declaration_t>}") 318 323 private_members = property( _get_private_members, _set_private_members 324 , doc="list of all private L{members<declaration_t>}") 325 330 protected_members = property( _get_protected_members, _set_protected_members 331 , doc="list of all protected L{members<declaration_t>}" ) 332 337 aliases = property( _get_aliases, _set_aliases 338 , doc="List of L{aliases<typedef_t>} to this instance") 339 344 byte_size = property( _get_byte_size, _set_byte_size 345 , doc="Size of this class in bytes @type: int") 346348 if self.compiler == compilers.MSVC_PDB_9: 349 compilers.on_missing_functionality( self.compiler, "byte align" ) 350 return self._byte_align353 byte_align = property( _get_byte_align, _set_byte_align 354 , doc="Alignment of this class in bytes @type: int") 355357 return self.get_members()358360 """ 361 returns list of members according to access type 362 363 If access equals to None, then returned list will contain all members. 364 You should not modify the list content, otherwise different optimization 365 data will stop work and may to give you wrong results. 366 367 @param access: describes desired members 368 @type access: L{ACCESS_TYPES} 369 370 @return: [ members ] 371 """ 372 if access == ACCESS_TYPES.PUBLIC: 373 return self.public_members 374 elif access == ACCESS_TYPES.PROTECTED: 375 return self.protected_members 376 elif access == ACCESS_TYPES.PRIVATE: 377 return self.private_members 378 else: 379 all_members = [] 380 all_members.extend( self.public_members ) 381 all_members.extend( self.protected_members ) 382 all_members.extend( self.private_members ) 383 return all_members384386 """adds new declaration to the class 387 388 @param decl: reference to a L{declaration<declaration_t>} 389 390 @param access: member access type 391 @type access: L{ACCESS_TYPES} 392 """ 393 if access == ACCESS_TYPES.PUBLIC: 394 self.public_members.append( decl ) 395 elif access == ACCESS_TYPES.PROTECTED: 396 self.protected_members.append( decl ) 397 elif access == ACCESS_TYPES.PRIVATE: 398 self.private_members.append( decl ) 399 else: 400 raise RuntimeError( "Invalid access type: %s." % access ) 401 decl.parent = self 402 decl.cache.reset() 403 decl.cache.access_type = access404406 """ 407 removes decl from members list 408 409 @param decl: declaration to be removed 410 @type decl: L{declaration_t} 411 """ 412 container = None 413 access_type = self.find_out_member_access_type( decl ) 414 if access_type == ACCESS_TYPES.PUBLIC: 415 container = self.public_members 416 elif access_type == ACCESS_TYPES.PROTECTED: 417 container = self.protected_members 418 else: #decl.cache.access_type == ACCESS_TYPES.PRVATE 419 container = self.private_members 420 del container[ container.index( decl ) ] 421 decl.cache.reset()422424 """ 425 returns member access type 426 427 @param member: member of the class 428 @type member: L{declaration_t} 429 430 @return: L{ACCESS_TYPES} 431 """ 432 assert member.parent is self 433 if not member.cache.access_type: 434 access_type = None 435 if member in self.public_members: 436 access_type = ACCESS_TYPES.PUBLIC 437 elif member in self.protected_members: 438 access_type = ACCESS_TYPES.PROTECTED 439 elif member in self.private_members: 440 access_type = ACCESS_TYPES.PRIVATE 441 else: 442 raise RuntimeError( "Unable to find member within internal members list." ) 443 member.cache.access_type = access_type 444 return access_type 445 else: 446 return member.cache.access_type447449 members = self.get_members( access_type ) 450 answer = [] 451 map( lambda mem: answer.extend( mem.i_depend_on_them(recursive=True) ), members ) 452 member_ids = set( map( lambda m: id( m ), members ) ) 453 for dependency in answer: 454 if id( dependency.declaration ) in member_ids: 455 dependency.access_type = access_type 456 return answer457459 report_dependency = lambda *args: dependencies.dependency_info_t( self, *args ) 460 461 answer = [] 462 463 map( lambda base: answer.append( report_dependency( base.related_class, base.access_type, "base class" ) ) 464 , self.bases ) 465 466 if recursive: 467 map( lambda access_type: answer.extend( self.__find_out_member_dependencies( access_type ) ) 468 , ACCESS_TYPES.ALL ) 469 470 return answer471 472 @property474 """reference to L{container traits<container_traits.py>} or None""" 475 if self._container_traits_set == False: 476 import container_traits #prevent cyclic dependencies 477 self._container_traits_set = True 478 self._container_traits = container_traits.find_container_traits( self ) 479 return self._container_traits480482 copy_ = self.constructors( lambda x: x.is_copy_constructor, recursive=False, allow_empty=True ) 483 if copy_: 484 return copy_[0] 485 else: 486 return None487489 trivial = self.constructors( lambda x: x.is_trivial_constructor, recursive=False, allow_empty=True ) 490 if trivial: 491 return trivial[0] 492 else: 493 return None494496 import type_traits #prevent cyclic dependencies 497 if type_traits.is_std_string( self ): 498 return 'string' 499 elif type_traits.is_std_wstring( self ): 500 return 'wstring' 501 else: 502 return get_partial_name( self.name )503 505 """returns list of all noncopyable variables""" 506 import type_traits as tt#prevent cyclic dependencies 507 logger = utils.loggers.cxx_parser 508 mvars = self.vars( lambda v: not v.type_qualifiers.has_static, recursive=False, allow_empty=True ) 509 noncopyable_vars = [] 510 for mvar in mvars: 511 type_ = tt.remove_reference( mvar.type ) 512 if tt.is_const( type_ ): 513 no_const = tt.remove_const( type_ ) 514 if tt.is_fundamental( no_const ) or tt.is_enum( no_const): 515 logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - fundamental or enum" % self.decl_string ) 516 noncopyable_vars.append( mvar ) 517 if tt.is_class( no_const ): 518 logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - class" % self.decl_string ) 519 noncopyable_vars.append( mvar ) 520 if tt.is_array( no_const ): 521 logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - array" % self.decl_string ) 522 noncopyable_vars.append( mvar ) 523 if tt.class_traits.is_my_case( type_ ): 524 cls = tt.class_traits.get_declaration( type_ ) 525 if tt.is_noncopyable( cls ): 526 logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes member variable - class that is not copyable" % self.decl_string ) 527 noncopyable_vars.append( mvar ) 528 logger.debug( "__contains_noncopyable_mem_var - %s - false - doesn't contains noncopyable members" % self.decl_string ) 529 return noncopyable_vars
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Oct 20 09:00:22 2008 | http://epydoc.sourceforge.net |