Skip to content

Commit cb7be4f

Browse files
authored
Merge pull request github#9398 from github/redsun82/swift-getparent
Swift: simplify `GetImmediateParent.qll`
2 parents ecce7f1 + 3414028 commit cb7be4f

File tree

5 files changed

+244
-261
lines changed

5 files changed

+244
-261
lines changed

swift/codegen/generators/qlgen.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ def generate(opts, renderer):
119119
all_imports = ql.ImportList(list(sorted(imports.values())))
120120
renderer.render(all_imports, include_file)
121121

122-
renderer.render(ql.GetParentImplementation(classes=classes, imports=[get_import(include_file, opts.swift_dir)]),
123-
out / 'GetImmediateParent.qll')
122+
renderer.render(ql.GetParentImplementation(classes), out / 'GetImmediateParent.qll')
124123

125124
renderer.cleanup(existing)
126125
if opts.ql_format:

swift/codegen/lib/ql.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,3 @@ class GetParentImplementation:
9999
template: ClassVar = 'ql_parent'
100100

101101
classes: List[Class] = field(default_factory=list)
102-
imports: List[str] = field(default_factory=list)

swift/codegen/templates/ql_parent.mustache

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
11
// generated by {{generator}}
22

3-
{{#imports}}
4-
import {{.}}
5-
{{/imports}}
6-
7-
// we are defining this class mainly to leverage existing generation machinery
8-
// when we generate getters in classes we use the db predicate with `this`. In order to reuse that we need a class here
9-
// as well
10-
private class ElementWithChildAccessor extends Element {
11-
// why does this look more complicated than it should?
12-
// * the none() simplifies generation, as we can append `or ...` without a special case for the first item
13-
// * the `exists` and the `x` variables are there to reuse the same generation done in classes (where the variables
14-
// are used to hide nodes via resolution)
15-
Element getAnImmediateChild() {
16-
none()
17-
{{#classes}}
18-
{{#properties}}
19-
{{#is_child}}
20-
or
21-
exists({{type}} {{local_var}}{{#is_repeated}}, int index{{/is_repeated}} | {{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}}) and result = {{local_var}})
22-
{{/is_child}}
23-
{{/properties}}
24-
{{/classes}}
25-
}
26-
}
3+
import codeql.swift.elements.Element
274

285
/**
296
* Gets any of the "immediate" children of `e`. "Immediate" means not taking into account node resolution: for example
307
* if the AST child is the first of a series of conversions that would normally be hidden away, this will select the
318
* next conversion down the hidden AST tree instead of the corresponding fully uncoverted node at the bottom.
32-
* This predicate is mainly intended to be used to test uniqueness of parents.
9+
* Outside this module this file is mainly intended to be used to test uniqueness of parents.
3310
*/
3411
cached
3512
Element getAnImmediateChild(Element e) {
36-
result = e.(ElementWithChildAccessor).getAnImmediateChild()
13+
// why does this look more complicated than it should?
14+
// * `exists` and the `x` variable are there to reuse the same generation done in classes (where `x` is used to hide
15+
// nodes via resolution)
16+
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
17+
exists(Element x | result = x and (
18+
none()
19+
{{#classes}}
20+
{{#properties}}
21+
{{#is_child}}
22+
or
23+
{{#is_repeated}}
24+
{{tablename}}(e, _, x)
25+
{{/is_repeated}}
26+
{{^is_repeated}}
27+
{{tablename}}(e{{#tableparams}}{{^first}}, {{param}}{{/first}}{{/tableparams}})
28+
{{/is_repeated}}
29+
{{/is_child}}
30+
{{/properties}}
31+
{{/classes}}
32+
))
3733
}
3834

3935
/**

swift/codegen/test/test_qlgen.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ def run_mock():
1818
ql_output_path = lambda: paths.swift_dir / "ql/lib/other/path"
1919
import_file = lambda: stub_path().with_suffix(".qll")
2020
children_file = lambda: ql_output_path() / "GetImmediateParent.qll"
21-
stub_import = "stub.path"
22-
stub_import_prefix = f"{stub_import}."
21+
stub_import_prefix = "stub.path."
22+
root_import = stub_import_prefix + "Element"
2323
gen_import_prefix = "other.path."
2424

2525

@@ -69,7 +69,7 @@ def generate_classes(opts, renderer):
6969
def test_empty(opts, input, renderer):
7070
assert generate(opts, renderer) == {
7171
import_file(): ql.ImportList(),
72-
children_file(): ql.GetParentImplementation(imports=[stub_import]),
72+
children_file(): ql.GetParentImplementation(),
7373
}
7474

7575

@@ -127,7 +127,6 @@ def test_hierarchy_children(opts, input, renderer):
127127
ql.Class(name="D", final=True, bases=["B", "C"],
128128
imports=[stub_import_prefix + cls for cls in "BC"]),
129129
],
130-
imports=[stub_import],
131130
)
132131

133132

0 commit comments

Comments
 (0)