Skip to content

Commit cd1800e

Browse files
authored
Merge pull request github#9371 from MathiasVP/extract-key-path-application
Swift: Extract KeyPath applications
2 parents b6cc438 + 9175354 commit cd1800e

File tree

7 files changed

+71
-2
lines changed

7 files changed

+71
-2
lines changed

swift/codegen/schema.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ InOutExpr:
390390

391391
KeyPathApplicationExpr:
392392
_extends: Expr
393+
base: Expr
394+
key_path: Expr
393395

394396
KeyPathDotExpr:
395397
_extends: Expr

swift/extractor/visitors/ExprVisitor.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
468468
auto pathLabel = dispatcher_.fetchLabel(path);
469469
dispatcher_.emit(KeyPathExprParsedPathsTrap{label, pathLabel});
470470
}
471-
if (auto root = expr->getParsedPath()) {
471+
if (auto root = expr->getParsedRoot()) {
472472
auto rootLabel = dispatcher_.fetchLabel(root);
473473
dispatcher_.emit(KeyPathExprParsedRootsTrap{label, rootLabel});
474474
}
@@ -509,6 +509,22 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
509509
dispatcher_.emit(IfExprsTrap{label, condLabel, thenLabel, elseLabel});
510510
}
511511

512+
void visitKeyPathDotExpr(swift::KeyPathDotExpr* expr) {
513+
auto label = dispatcher_.assignNewLabel(expr);
514+
dispatcher_.emit(KeyPathDotExprsTrap{label});
515+
}
516+
517+
void visitKeyPathApplicationExpr(swift::KeyPathApplicationExpr* expr) {
518+
auto label = dispatcher_.assignNewLabel(expr);
519+
assert(expr->getBase() && "KeyPathApplicationExpr has getBase()");
520+
assert(expr->getKeyPath() && "KeyPathApplicationExpr has getKeyPath()");
521+
522+
auto baseLabel = dispatcher_.fetchLabel(expr->getBase());
523+
auto keyPathLabel = dispatcher_.fetchLabel(expr->getKeyPath());
524+
525+
dispatcher_.emit(KeyPathApplicationExprsTrap{label, baseLabel, keyPathLabel});
526+
}
527+
512528
private:
513529
TrapLabel<ArgumentTag> emitArgument(const swift::Argument& arg) {
514530
auto argLabel = dispatcher_.createLabel<ArgumentTag>();

swift/ql/lib/codeql/swift/generated/expr/KeyPathApplicationExpr.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,18 @@ import codeql.swift.elements.expr.Expr
33

44
class KeyPathApplicationExprBase extends @key_path_application_expr, Expr {
55
override string getAPrimaryQlClass() { result = "KeyPathApplicationExpr" }
6+
7+
Expr getBase() {
8+
exists(Expr x |
9+
key_path_application_exprs(this, x, _) and
10+
result = x.resolve()
11+
)
12+
}
13+
14+
Expr getKeyPath() {
15+
exists(Expr x |
16+
key_path_application_exprs(this, _, x) and
17+
result = x.resolve()
18+
)
19+
}
620
}

swift/ql/lib/swift.dbscheme

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,9 @@ in_out_exprs(
888888
);
889889

890890
key_path_application_exprs(
891-
unique int id: @key_path_application_expr
891+
unique int id: @key_path_application_expr,
892+
int base: @expr ref,
893+
int key_path: @expr ref
892894
);
893895

894896
key_path_dot_exprs(

swift/ql/test/extractor-tests/expressions/all.expected

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
| expressions.swift:54:1:54:1 | _ |
126126
| expressions.swift:54:1:54:8 | ... = ... |
127127
| expressions.swift:54:5:54:8 | #keyPath(...) |
128+
| expressions.swift:54:6:54:8 | TBD (UnresolvedDotExpr) |
128129
| expressions.swift:58:16:58:16 | 1234 |
129130
| expressions.swift:59:1:59:1 | unsafeFunction |
130131
| expressions.swift:59:1:59:34 | call to unsafeFunction |
@@ -232,3 +233,15 @@
232233
| expressions.swift:138:10:138:17 | ...[...] |
233234
| expressions.swift:138:13:138:13 | 3 |
234235
| expressions.swift:138:16:138:16 | 4 |
236+
| expressions.swift:152:26:152:26 | a |
237+
| expressions.swift:152:26:152:47 | \\...[...] |
238+
| expressions.swift:152:37:152:37 | keyPathInt |
239+
| expressions.swift:153:24:153:24 | a |
240+
| expressions.swift:153:24:153:43 | \\...[...] |
241+
| expressions.swift:153:35:153:35 | keyPathB |
242+
| expressions.swift:154:22:154:22 | a |
243+
| expressions.swift:154:22:154:41 | \\...[...] |
244+
| expressions.swift:154:22:154:56 | \\...[...] |
245+
| expressions.swift:154:33:154:33 | keyPathB |
246+
| expressions.swift:154:52:154:55 | #keyPath(...) |
247+
| expressions.swift:154:53:154:55 | TBD (UnresolvedDotExpr) |

swift/ql/test/extractor-tests/expressions/expressions.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,20 @@ func testProperties(hp : inout HasProperty) -> Int {
136136
var w = hp.normalField
137137
hp[1] = 2
138138
return hp[3, 4]
139+
}
140+
141+
struct B {
142+
var x : Int
143+
}
144+
145+
struct A {
146+
var b : B
147+
var bs : [B]
148+
var mayB : B?
149+
}
150+
151+
func test(a : A, keyPathInt : WritableKeyPath<A, Int>, keyPathB : WritableKeyPath<A, B>) {
152+
var apply_keyPathInt = a[keyPath: keyPathInt]
153+
var apply_keyPathB = a[keyPath: keyPathB]
154+
var nested_apply = a[keyPath: keyPathB][keyPath: \B.x]
139155
}

swift/ql/test/extractor-tests/expressions/semantics.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,9 @@
6868
| expressions.swift:137:3:137:7 | ...[...] | OrdinarySemantics |
6969
| expressions.swift:138:10:138:10 | hp | OrdinarySemantics |
7070
| expressions.swift:138:10:138:17 | ...[...] | OrdinarySemantics |
71+
| expressions.swift:152:26:152:26 | a | OrdinarySemantics |
72+
| expressions.swift:152:37:152:37 | keyPathInt | OrdinarySemantics |
73+
| expressions.swift:153:24:153:24 | a | OrdinarySemantics |
74+
| expressions.swift:153:35:153:35 | keyPathB | OrdinarySemantics |
75+
| expressions.swift:154:22:154:22 | a | OrdinarySemantics |
76+
| expressions.swift:154:33:154:33 | keyPathB | OrdinarySemantics |

0 commit comments

Comments
 (0)