@@ -589,6 +589,9 @@ class CppClass(dict):
589
589
* ``nested_classes`` - Classes and structs defined within this class
590
590
* ``final`` - True if final
591
591
* ``abstract`` - True if abstract
592
+ * ``using`` - Using directives in this class scope: key is name for lookup,
593
+ value is :class:`.CppVariable`
594
+ * ``parent`` - If not None, the class that this class is nested in
592
595
593
596
An example of how this could look is as follows::
594
597
@@ -653,6 +656,7 @@ def __init__(self, nameStack, curTemplate, doxygen, location):
653
656
self ._public_typedefs = {}
654
657
self ._public_forward_declares = []
655
658
self ["namespace" ] = ""
659
+ self ["using" ] = {}
656
660
657
661
debug_print ("Class: %s" , nameStack )
658
662
debug_print ("Template: %s" , curTemplate )
@@ -713,7 +717,7 @@ def show(self):
713
717
if "doxygen" in list (self .keys ()):
714
718
rtn += self ["doxygen" ] + "\n "
715
719
if "parent" in list (self .keys ()) and self ["parent" ]:
716
- rtn += "parent class: " + self ["parent" ] + "\n "
720
+ rtn += "parent class: " + self ["parent" ][ "name" ] + "\n "
717
721
718
722
if "inherits" in list (self .keys ()):
719
723
rtn += " Inherits: "
@@ -759,7 +763,7 @@ def __str__(self):
759
763
if "doxygen" in list (self .keys ()):
760
764
rtn += self ["doxygen" ] + "\n "
761
765
if "parent" in list (self .keys ()) and self ["parent" ]:
762
- rtn += "parent class: " + self ["parent" ] + "\n "
766
+ rtn += "parent class: " + self ["parent" ][ "name" ] + "\n "
763
767
764
768
if "inherits" in list (self .keys ()) and len (self ["inherits" ]):
765
769
rtn += "Inherits: "
@@ -834,7 +838,7 @@ def __str__(self):
834
838
if "doxygen" in list (self .keys ()):
835
839
rtn += self ["doxygen" ] + "\n "
836
840
if "parent" in list (self .keys ()) and self ["parent" ]:
837
- rtn += "parent class: " + self ["parent" ] + "\n "
841
+ rtn += "parent class: " + self ["parent" ][ "name" ] + "\n "
838
842
839
843
rtn += "{\n "
840
844
for member in self ["members" ]:
@@ -898,6 +902,7 @@ def _params_helper1(self, stack):
898
902
def _params_helper2 (self , params ):
899
903
for p in params :
900
904
p ["method" ] = self # save reference in variable to parent method
905
+ p ["parent" ] = self
901
906
if "::" in p ["type" ]:
902
907
ns = p ["type" ].split ("::" )[0 ]
903
908
if ns not in Resolver .NAMESPACES and ns in Resolver .CLASSES :
@@ -914,6 +919,7 @@ class CppMethod(_CppMethod):
914
919
* ``name`` - Name of the method
915
920
* ``doxygen`` - Doxygen comments associated with the method if they exist
916
921
* ``parameters`` - List of :class:`.CppVariable`
922
+ * ``parent`` - If not None, the class this method belongs to
917
923
"""
918
924
919
925
def show (self ):
@@ -1121,12 +1127,14 @@ class CppVariable(_CppVariable):
1121
1127
* ``default`` - Default value of the variable, this key will only
1122
1128
exist if there is a default value
1123
1129
* ``extern`` - True if its an extern, False if not
1130
+ * ``parent`` - If not None, either the class this is a property of, or the
1131
+ method this variable is a parameter in
1124
1132
"""
1125
1133
1126
1134
Vars = []
1127
1135
1128
1136
def __init__ (self , nameStack , doxygen , location , ** kwargs ):
1129
- debug_print ("trace %s" , nameStack )
1137
+ debug_print ("var trace %s" , nameStack )
1130
1138
if len (nameStack ) and nameStack [0 ] == "extern" :
1131
1139
self ["extern" ] = True
1132
1140
del nameStack [0 ]
@@ -1494,21 +1502,33 @@ def resolve_type(self, string, result): # recursive
1494
1502
result ["fundamental" ] = False
1495
1503
result ["class" ] = klass
1496
1504
result ["unresolved" ] = False
1497
- elif self .using :
1498
- # search for type in all enclosing namespaces
1499
- for ns in _iter_ns_str_reversed (result .get ("namespace" , "" )):
1500
- nsalias = ns + alias
1501
- used = self .using .get (nsalias )
1502
- if used :
1503
- for i in ("type" , "namespace" , "ctypes_type" , "raw_type" ):
1504
- if i in used :
1505
- result [i ] = used [i ]
1506
- result ["unresolved" ] = False
1507
- break
1508
- else :
1509
- result ["unresolved" ] = True
1510
1505
else :
1511
- result ["unresolved" ] = True
1506
+ used = None
1507
+
1508
+ # Search for using directives in parents
1509
+ parent = result ["parent" ]
1510
+ while parent :
1511
+ p_using = parent .get ("using" )
1512
+ if p_using :
1513
+ used = p_using .get (alias )
1514
+ if used :
1515
+ break
1516
+ parent = parent ["parent" ]
1517
+
1518
+ if not used and self .using :
1519
+ # search for type in all enclosing namespaces
1520
+ # TODO: would be nice if namespaces were an object?
1521
+ for ns in _iter_ns_str_reversed (result .get ("namespace" , "" )):
1522
+ nsalias = ns + alias
1523
+ used = self .using .get (nsalias )
1524
+ if used :
1525
+ break
1526
+
1527
+ if used :
1528
+ for i in ("type" , "namespace" , "ctypes_type" , "raw_type" ):
1529
+ if i in used :
1530
+ result [i ] = used [i ]
1531
+ result ["unresolved" ] = False
1512
1532
else :
1513
1533
result ["fundamental" ] = True
1514
1534
result ["unresolved" ] = False
@@ -1538,14 +1558,16 @@ def finalize_vars(self):
1538
1558
nestedEnum = None
1539
1559
nestedStruct = None
1540
1560
nestedTypedef = None
1541
- if "method" in var and "parent" in list (var ["method" ].keys ()):
1542
- klass = var ["method" ]["parent" ]
1543
- if tag in var ["method" ]["parent" ]._public_enums :
1544
- nestedEnum = var ["method" ]["parent" ]._public_enums [tag ]
1545
- elif tag in var ["method" ]["parent" ]._public_typedefs :
1546
- nestedTypedef = var ["method" ]["parent" ]._public_typedefs [
1547
- tag
1548
- ]
1561
+
1562
+ parent = var ["parent" ]
1563
+ while parent :
1564
+ nestedEnum = getattr (parent , "_public_enums" , {}).get (tag )
1565
+ if nestedEnum :
1566
+ break
1567
+ nestedTypedef = getattr (parent , "_public_typedefs" , {}).get (tag )
1568
+ if nestedTypedef :
1569
+ break
1570
+ parent = parent ["parent" ]
1549
1571
1550
1572
if "<" in tag : # should also contain '>'
1551
1573
var ["template" ] = tag # do not resolve templates
@@ -1604,7 +1626,7 @@ def finalize_vars(self):
1604
1626
var ["enum" ] = enum ["namespace" ] + enum ["name" ]
1605
1627
var ["fundamental" ] = True
1606
1628
1607
- elif var ["parent" ]:
1629
+ elif var ["parent" ] and var [ "unresolved" ] :
1608
1630
warning_print ("WARN unresolved %s" , _tag )
1609
1631
var ["ctypes_type" ] = "ctypes.c_void_p"
1610
1632
var ["unresolved" ] = True
@@ -1750,17 +1772,15 @@ def finalize_vars(self):
1750
1772
var ["raw_type" ] = (
1751
1773
var ["class" ]["namespace" ] + "::" + var ["raw_type" ]
1752
1774
)
1753
- elif var [ "class" ][ "parent" ] in self . classes :
1754
- parent = self . classes [ var ["class" ]["parent" ] ]
1775
+ else :
1776
+ parent = var ["class" ]["parent" ]
1755
1777
var ["raw_type" ] = (
1756
1778
parent ["namespace" ]
1757
1779
+ "::"
1758
1780
+ var ["class" ]["name" ]
1759
1781
+ "::"
1760
1782
+ var ["raw_type" ]
1761
1783
)
1762
- else :
1763
- var ["unresolved" ] = True
1764
1784
1765
1785
elif (
1766
1786
"::" in var ["raw_type" ]
@@ -2166,6 +2186,7 @@ def _evaluate_method_stack(self):
2166
2186
self ._get_stmt_doxygen (),
2167
2187
self ._get_location (self .nameStack ),
2168
2188
)
2189
+ newMethod ["parent" ] = None
2169
2190
self .functions .append (newMethod )
2170
2191
global parseHistory
2171
2192
parseHistory .append (
@@ -2299,6 +2320,7 @@ def _evaluate_property_stack(self, clearStack=True, addToVar=None):
2299
2320
klass = self .classes [self .curClass ]
2300
2321
klass ["properties" ][self .curAccessSpecifier ].append (newVar )
2301
2322
newVar ["property_of_class" ] = klass ["name" ]
2323
+ newVar ["parent" ] = klass
2302
2324
parseHistory .append (
2303
2325
{"braceDepth" : self .braceDepth , "item_type" : "variable" , "item" : newVar }
2304
2326
)
@@ -2373,16 +2395,17 @@ def _evaluate_class_stack(self):
2373
2395
2374
2396
if parent :
2375
2397
newClass ["namespace" ] = self .classes [parent ]["namespace" ] + "::" + parent
2376
- newClass ["parent" ] = parent
2398
+ newClass ["parent" ] = self . classes [ parent ]
2377
2399
self .classes [parent ]["nested_classes" ].append (newClass )
2378
2400
## supports nested classes with the same name ##
2379
2401
self .curClass = key = parent + "::" + classKey
2380
2402
self ._classes_brace_level [key ] = self .braceDepth
2381
2403
2382
2404
elif newClass ["parent" ]: # nested class defined outside of parent. A::B {...}
2383
- parent = newClass ["parent" ]
2384
- newClass ["namespace" ] = self .classes [parent ]["namespace" ] + "::" + parent
2385
- self .classes [parent ]["nested_classes" ].append (newClass )
2405
+ pcls = newClass ["parent" ]
2406
+ parent = pcls ["name" ]
2407
+ newClass ["namespace" ] = pcls ["namespace" ] + "::" + parent
2408
+ pcls ["nested_classes" ].append (newClass )
2386
2409
## supports nested classes with the same name ##
2387
2410
self .curClass = key = parent + "::" + classKey
2388
2411
self ._classes_brace_level [key ] = self .braceDepth
@@ -2538,8 +2561,8 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):
2538
2561
self .anon_struct_counter = 0
2539
2562
self .anon_union_counter = [- 1 , 0 ]
2540
2563
2541
- #: Using directives in this header: key is full name for lookup, value
2542
- #: is :class:`.CppVariable`
2564
+ #: Using directives in this header outside of class scope: key is
2565
+ #: full name for lookup, value is :class:`.CppVariable`
2543
2566
self .using = {}
2544
2567
2545
2568
if len (self .headerFileName ):
@@ -2767,7 +2790,9 @@ def __init__(self, headerFileName, argType="file", encoding=None, **kwargs):
2767
2790
self .curAccessSpecifier = self .accessSpecifierStack [- 1 ]
2768
2791
self .accessSpecifierStack = self .accessSpecifierStack [:- 1 ]
2769
2792
if self .curClass and self .classes [self .curClass ]["parent" ]:
2770
- self .curClass = self .classes [self .curClass ]["parent" ]
2793
+ self .curClass = self .classes [self .curClass ]["parent" ][
2794
+ "name"
2795
+ ]
2771
2796
else :
2772
2797
self .curClass = ""
2773
2798
self .stack = []
@@ -3108,23 +3133,40 @@ def _evaluate_stack(self, token=None):
3108
3133
else :
3109
3134
if len (self .nameStack ) > 3 and self .nameStack [2 ] == "=" :
3110
3135
# using foo = ns::bar
3136
+ # -> type alias: same behavior in all scopes
3111
3137
alias = self .nameStack [1 ]
3112
3138
ns , stack = _split_namespace (self .nameStack [3 :])
3113
3139
atype = CppVariable (
3114
3140
stack , self ._get_stmt_doxygen (), self ._get_location (stack )
3115
3141
)
3142
+
3143
+ # namespace refers to the embedded type
3144
+ atype ["namespace" ] = ns
3116
3145
else :
3117
3146
# using foo::bar
3147
+ # -> in global scope this is bringing in something
3148
+ # from a different namespace
3149
+ # -> in class scope this is bringing in a member
3150
+ # from a base class
3118
3151
ns , stack = _split_namespace (self .nameStack [1 :])
3119
3152
atype = CppVariable (
3120
3153
stack , self ._get_stmt_doxygen (), self ._get_location (stack )
3121
3154
)
3122
3155
alias = atype ["type" ]
3156
+ if self .curClass :
3157
+ atype ["baseclass" ] = ns
3158
+ else :
3159
+ atype ["namespace" ] = ns
3123
3160
3124
- atype ["namespace" ] = ns
3125
3161
atype ["raw_type" ] = ns + atype ["type" ]
3126
- alias = self .current_namespace () + alias
3127
- self .using [alias ] = atype
3162
+
3163
+ if self .curClass :
3164
+ klass = self .classes [self .curClass ]
3165
+ klass ["using" ][alias ] = atype
3166
+ else :
3167
+ # lookup is done
3168
+ alias = self .current_namespace () + alias
3169
+ self .using [alias ] = atype
3128
3170
elif is_method_namestack (self .stack ) and "(" in self .nameStack :
3129
3171
debug_print ("trace" )
3130
3172
self ._evaluate_method_stack ()
0 commit comments