Skip to content

Commit 7878bc3

Browse files
committed
Swift: remove property wrapper AST inconsistencies
1 parent 5de8934 commit 7878bc3

File tree

6 files changed

+55
-64
lines changed

6 files changed

+55
-64
lines changed

swift/ql/lib/codeql/swift/printast/PrintAstNode.qll

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ private predicate shouldPrint(Locatable e) { any(PrintAstConfiguration config).s
2828
/**
2929
* An AST node that should be printed.
3030
*/
31-
private newtype TPrintAstNode = TLocatable(Locatable ast)
31+
private newtype TPrintAstNode = TPrintLocatable(Locatable ast)
3232

3333
/**
3434
* A node in the output tree.
@@ -60,6 +60,11 @@ class PrintAstNode extends TPrintAstNode {
6060
* the property is `key`.
6161
*/
6262
string getProperty(string key) { none() }
63+
64+
/**
65+
* Gets the underlying AST node, if any.
66+
*/
67+
abstract Locatable getAstNode();
6368
}
6469

6570
private string prettyPrint(Locatable e) {
@@ -73,10 +78,10 @@ private class Unresolved extends Locatable {
7378
/**
7479
* A graph node representing a real Locatable node.
7580
*/
76-
class PrintLocatable extends PrintAstNode, TLocatable {
81+
class PrintLocatable extends PrintAstNode, TPrintLocatable {
7782
Locatable ast;
7883

79-
PrintLocatable() { this = TLocatable(ast) }
84+
PrintLocatable() { this = TPrintLocatable(ast) }
8085

8186
override string toString() { result = prettyPrint(ast) }
8287

@@ -87,9 +92,9 @@ class PrintLocatable extends PrintAstNode, TLocatable {
8792
c = getChildAndAccessor(ast, i, accessor) and
8893
(
8994
// 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
9196
or
92-
child = TLocatable(c.getFullyUnresolved().(Unresolved)) and
97+
child = TPrintLocatable(c.getFullyUnresolved().(Unresolved)) and
9398
index = 2 * i + 1 and
9499
(
95100
if c instanceof Expr
@@ -100,6 +105,8 @@ class PrintLocatable extends PrintAstNode, TLocatable {
100105
)
101106
}
102107

108+
final override Locatable getAstNode() { result = ast }
109+
103110
final override Location getLocation() { result = ast.getLocation() }
104111
}
105112

@@ -112,17 +119,38 @@ class PrintUnresolved extends PrintLocatable {
112119

113120
override predicate hasChild(PrintAstNode child, int index, string label) {
114121
// 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))
116123
}
117124
}
118125

126+
private predicate hasPropertyWrapperElement(VarDecl d, Locatable a) {
127+
a = [d.getPropertyWrapperBackingVar(), d.getPropertyWrapperProjectionVar()] or
128+
a = [d.getPropertyWrapperBackingVarBinding(), d.getPropertyWrapperProjectionVarBinding()]
129+
}
130+
119131
/**
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.
121134
*/
122135
class PrintVarDecl extends PrintLocatable {
123136
override VarDecl ast;
124137

125138
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+
}
126154
}
127155

128156
/**
@@ -135,3 +163,23 @@ class PrintFunction extends PrintLocatable {
135163
key = "InterfaceType" and result = ast.getInterfaceType().toString()
136164
}
137165
}
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+
}

swift/ql/test/extractor-tests/generated/decl/ConcreteVarDecl/CONSISTENCY/PrintAstConsistency.expected

Lines changed: 0 additions & 13 deletions
This file was deleted.

swift/ql/test/extractor-tests/generated/decl/ParamDecl/CONSISTENCY/PrintAstConsistency.expected

Lines changed: 0 additions & 21 deletions
This file was deleted.

swift/ql/test/extractor-tests/generated/expr/AppliedPropertyWrapperExpr/CONSISTENCY/PrintAstConsistency.expected

Lines changed: 0 additions & 13 deletions
This file was deleted.

swift/ql/test/extractor-tests/generated/expr/PropertyWrapperValuePlaceholderExpr/CONSISTENCY/PrintAstConsistency.expected

Lines changed: 0 additions & 7 deletions
This file was deleted.

swift/ql/test/library-tests/dataflow/dataflow/CONSISTENCY/PrintAstConsistency.expected

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)