@@ -28,7 +28,7 @@ private predicate shouldPrint(Locatable e) { any(PrintAstConfiguration config).s
28
28
/**
29
29
* An AST node that should be printed.
30
30
*/
31
- private newtype TPrintAstNode = TLocatable ( Locatable ast )
31
+ private newtype TPrintAstNode = TPrintLocatable ( Locatable ast )
32
32
33
33
/**
34
34
* A node in the output tree.
@@ -60,6 +60,11 @@ class PrintAstNode extends TPrintAstNode {
60
60
* the property is `key`.
61
61
*/
62
62
string getProperty ( string key ) { none ( ) }
63
+
64
+ /**
65
+ * Gets the underlying AST node, if any.
66
+ */
67
+ abstract Locatable getAstNode ( ) ;
63
68
}
64
69
65
70
private string prettyPrint ( Locatable e ) {
@@ -73,10 +78,10 @@ private class Unresolved extends Locatable {
73
78
/**
74
79
* A graph node representing a real Locatable node.
75
80
*/
76
- class PrintLocatable extends PrintAstNode , TLocatable {
81
+ class PrintLocatable extends PrintAstNode , TPrintLocatable {
77
82
Locatable ast ;
78
83
79
- PrintLocatable ( ) { this = TLocatable ( ast ) }
84
+ PrintLocatable ( ) { this = TPrintLocatable ( ast ) }
80
85
81
86
override string toString ( ) { result = prettyPrint ( ast ) }
82
87
@@ -87,9 +92,9 @@ class PrintLocatable extends PrintAstNode, TLocatable {
87
92
c = getChildAndAccessor ( ast , i , accessor ) and
88
93
(
89
94
// use even indexes for normal children, leaving odd slots for conversions if any
90
- child = TLocatable ( c ) and index = 2 * i and label = accessor
95
+ child = TPrintLocatable ( c ) and index = 2 * i and label = accessor
91
96
or
92
- child = TLocatable ( c .getFullyUnresolved ( ) .( Unresolved ) ) and
97
+ child = TPrintLocatable ( c .getFullyUnresolved ( ) .( Unresolved ) ) and
93
98
index = 2 * i + 1 and
94
99
(
95
100
if c instanceof Expr
@@ -100,6 +105,8 @@ class PrintLocatable extends PrintAstNode, TLocatable {
100
105
)
101
106
}
102
107
108
+ final override Locatable getAstNode ( ) { result = ast }
109
+
103
110
final override Location getLocation ( ) { result = ast .getLocation ( ) }
104
111
}
105
112
@@ -112,17 +119,38 @@ class PrintUnresolved extends PrintLocatable {
112
119
113
120
override predicate hasChild ( PrintAstNode child , int index , string label ) {
114
121
// only print immediate unresolved children from the "parallel" AST
115
- child = TLocatable ( getImmediateChildAndAccessor ( ast , index , label ) .( Unresolved ) )
122
+ child = TPrintLocatable ( getImmediateChildAndAccessor ( ast , index , label ) .( Unresolved ) )
116
123
}
117
124
}
118
125
126
+ private predicate hasPropertyWrapperElement ( VarDecl d , Locatable a ) {
127
+ a = [ d .getPropertyWrapperBackingVar ( ) , d .getPropertyWrapperProjectionVar ( ) ] or
128
+ a = [ d .getPropertyWrapperBackingVarBinding ( ) , d .getPropertyWrapperProjectionVarBinding ( ) ]
129
+ }
130
+
119
131
/**
120
- * A specialization of graph node for `VarDecl`, to add typing information.
132
+ * A specialization of graph node for `VarDecl`, to add typing information and deal with ambiguity
133
+ * over property wrapper children.
121
134
*/
122
135
class PrintVarDecl extends PrintLocatable {
123
136
override VarDecl ast ;
124
137
125
138
override string getProperty ( string key ) { key = "Type" and result = ast .getType ( ) .toString ( ) }
139
+
140
+ override predicate hasChild ( PrintAstNode child , int index , string label ) {
141
+ PrintLocatable .super .hasChild ( child , index , label ) and
142
+ // exclude property wrapper related children when they are already listed in the enclosing
143
+ // nominal type declaration or for a wrapped parameter for which this is a virtual local variable copy
144
+ not exists ( Locatable childAst |
145
+ childAst = child .getAstNode ( ) and
146
+ hasPropertyWrapperElement ( ast , childAst ) and
147
+ (
148
+ childAst = ast .getDeclaringDecl ( ) .getAMember ( )
149
+ or
150
+ ast instanceof ConcreteVarDecl and hasPropertyWrapperElement ( any ( ParamDecl p ) , childAst )
151
+ )
152
+ )
153
+ }
126
154
}
127
155
128
156
/**
@@ -135,3 +163,23 @@ class PrintFunction extends PrintLocatable {
135
163
key = "InterfaceType" and result = ast .getInterfaceType ( ) .toString ( )
136
164
}
137
165
}
166
+
167
+ /**
168
+ * A specialization of graph node for `PatternBindingDecl`, to solve ambiguity on `getInit`.
169
+ * When a property wrapper is involved, `getInit` may become shared between the explicit binding and
170
+ * the implicit compiler synthesized one.
171
+ */
172
+ class PrintPatternBindingDecl extends PrintLocatable {
173
+ override PatternBindingDecl ast ;
174
+
175
+ override predicate hasChild ( PrintAstNode child , int index , string label ) {
176
+ PrintLocatable .super .hasChild ( child , index , label ) and
177
+ // exclude `getInit` that are already the initializer of a variable that has this as a property wrapper backer
178
+ not exists ( Expr init , VarDecl var |
179
+ init = child .getAstNode ( ) and
180
+ init = ast .getAnInit ( ) and
181
+ var .getPropertyWrapperBackingVarBinding ( ) = ast and
182
+ var .getParentInitializer ( ) = init
183
+ )
184
+ }
185
+ }
0 commit comments