Skip to content

Commit 7f8bff5

Browse files
authored
Merge pull request #9729 from github/redsun82/swift-extraction
Swift: extract `ProtocolCompositionType` and all `BuiltinType`s
2 parents 780f5ab + 131524d commit 7f8bff5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+351
-102
lines changed

swift/codegen/generators/qlgen.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class ModifiedStubMarkedAsGeneratedError(Error):
3030
def get_ql_property(cls: schema.Class, prop: schema.Property):
3131
common_args = dict(
3232
type=prop.type if not prop.is_predicate else "predicate",
33-
skip_qltest="skip_qltest" in prop.pragmas,
33+
qltest_skip="qltest_skip" in prop.pragmas,
3434
is_child=prop.is_child,
3535
is_optional=prop.is_optional,
3636
is_predicate=prop.is_predicate,
@@ -69,13 +69,14 @@ def get_ql_property(cls: schema.Class, prop: schema.Property):
6969

7070

7171
def get_ql_class(cls: schema.Class):
72+
pragmas = {k: True for k in cls.pragmas if k.startswith("ql")}
7273
return ql.Class(
7374
name=cls.name,
7475
bases=cls.bases,
7576
final=not cls.derived,
7677
properties=[get_ql_property(cls, p) for p in cls.properties],
7778
dir=cls.dir,
78-
skip_qltest="skip_qltest" in cls.pragmas,
79+
**pragmas,
7980
)
8081

8182

@@ -143,7 +144,7 @@ def _get_all_properties_to_be_tested(cls: ql.Class, lookup: typing.Dict[str, ql.
143144
# deduplicate using id
144145
already_seen = set()
145146
for c, p in _get_all_properties(cls, lookup):
146-
if not (c.skip_qltest or p.skip_qltest or id(p) in already_seen):
147+
if not (c.qltest_skip or p.qltest_skip or id(p) in already_seen):
147148
already_seen.add(id(p))
148149
yield ql.PropertyForTest(p.getter, p.type, p.is_single, p.is_predicate, p.is_repeated)
149150

@@ -156,6 +157,20 @@ def _partition(l, pred):
156157
return res
157158

158159

160+
def _is_in_qltest_collapsed_hierachy(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
161+
return cls.qltest_collapse_hierarchy or _is_under_qltest_collapsed_hierachy(cls, lookup)
162+
163+
164+
def _is_under_qltest_collapsed_hierachy(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
165+
return not cls.qltest_uncollapse_hierarchy and any(
166+
_is_in_qltest_collapsed_hierachy(lookup[b], lookup) for b in cls.bases)
167+
168+
169+
def _should_skip_qltest(cls: ql.Class, lookup: typing.Dict[str, ql.Class]):
170+
return cls.qltest_skip or not (cls.final or cls.qltest_collapse_hierarchy) or _is_under_qltest_collapsed_hierachy(
171+
cls, lookup)
172+
173+
159174
def generate(opts, renderer):
160175
input = opts.schema
161176
out = opts.ql_output
@@ -196,7 +211,7 @@ def generate(opts, renderer):
196211
classes), out / 'GetImmediateParent.qll')
197212

198213
for c in classes:
199-
if not c.final or c.skip_qltest:
214+
if _should_skip_qltest(c, lookup):
200215
continue
201216
test_dir = test_out / c.path
202217
test_dir.mkdir(parents=True, exist_ok=True)

swift/codegen/lib/ql.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Property:
3737
is_optional: bool = False
3838
is_predicate: bool = False
3939
is_child: bool = False
40-
skip_qltest: bool = False
40+
qltest_skip: bool = False
4141

4242
def __post_init__(self):
4343
if self.tableparams:
@@ -79,7 +79,9 @@ class Class:
7979
properties: List[Property] = field(default_factory=list)
8080
dir: pathlib.Path = pathlib.Path()
8181
imports: List[str] = field(default_factory=list)
82-
skip_qltest: bool = False
82+
qltest_skip: bool = False
83+
qltest_collapse_hierarchy: bool = False
84+
qltest_uncollapse_hierarchy: bool = False
8385

8486
def __post_init__(self):
8587
self.bases = sorted(self.bases)

swift/codegen/schema.yml

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,22 @@ _directories:
1414

1515
Element:
1616
is_unknown: predicate
17-
_pragma: skip_qltest
17+
_pragma: qltest_skip
1818

1919
File:
2020
name: string
2121

2222
Locatable:
2323
location: Location?
24-
_pragma: skip_qltest
24+
_pragma: qltest_skip
2525

2626
Location:
2727
file: File
2828
start_line: int
2929
start_column: int
3030
end_line: int
3131
end_column: int
32-
_pragma: skip_qltest
32+
_pragma: qltest_skip
3333

3434
Type:
3535
diagnostics_name: string
@@ -85,6 +85,7 @@ AnyMetatypeType:
8585

8686
BuiltinType:
8787
_extends: Type
88+
_pragma: qltest_collapse_hierarchy
8889

8990
DependentMemberType:
9091
_extends: Type
@@ -114,6 +115,7 @@ PlaceholderType:
114115

115116
ProtocolCompositionType:
116117
_extends: Type
118+
members: Type*
117119

118120
ExistentialType:
119121
_extends: Type
@@ -393,7 +395,7 @@ EnumIsCaseExpr:
393395

394396
ErrorExpr:
395397
_extends: Expr
396-
_pragma: skip_qltest # unexpected emission
398+
_pragma: qltest_skip # unexpected emission
397399

398400
ExplicitCastExpr:
399401
_extends: Expr
@@ -468,7 +470,7 @@ ObjCSelectorExpr:
468470
_children:
469471
sub_expr: Expr
470472
method: AbstractFunctionDecl
471-
_pragma: skip_qltest # to be tested in integration tests
473+
_pragma: qltest_skip # to be tested in integration tests
472474

473475
OneWayExpr:
474476
_extends: Expr
@@ -510,7 +512,7 @@ SequenceExpr:
510512
_extends: Expr
511513
_children:
512514
elements: Expr*
513-
_pragma: skip_qltest # we should really never extract these, as these should be resolved to trees of operations
515+
_pragma: qltest_skip # we should really never extract these, as these should be resolved to trees of operations
514516

515517
SuperRefExpr:
516518
_extends: Expr
@@ -542,7 +544,7 @@ TypeExpr:
542544
UnresolvedDeclRefExpr:
543545
_extends: Expr
544546
name: string?
545-
_pragma: skip_qltest # we should really never extract these
547+
_pragma: qltest_skip # we should really never extract these
546548

547549
UnresolvedDotExpr:
548550
_extends: Expr
@@ -553,15 +555,15 @@ UnresolvedDotExpr:
553555
UnresolvedMemberExpr:
554556
_extends: Expr
555557
name: string
556-
_pragma: skip_qltest # we should really never extract these
558+
_pragma: qltest_skip # we should really never extract these
557559

558560
UnresolvedPatternExpr:
559561
_extends: Expr
560-
_pragma: skip_qltest # we should really never extract these
562+
_pragma: qltest_skip # we should really never extract these
561563

562564
UnresolvedSpecializeExpr:
563565
_extends: Expr
564-
_pragma: skip_qltest # we should really never extract these
566+
_pragma: qltest_skip # we should really never extract these
565567

566568
VarargExpansionExpr:
567569
_extends: Expr
@@ -698,6 +700,7 @@ BuiltinIntegerLiteralType:
698700

699701
BuiltinIntegerType:
700702
_extends: AnyBuiltinIntegerType
703+
_pragma: qltest_uncollapse_hierarchy
701704
width: int?
702705

703706
NestedArchetypeType:
@@ -830,11 +833,11 @@ ArrayToPointerExpr:
830833

831834
BridgeFromObjCExpr:
832835
_extends: ImplicitConversionExpr
833-
_pragma: skip_qltest # to be tested in integration tests
836+
_pragma: qltest_skip # to be tested in integration tests
834837

835838
BridgeToObjCExpr:
836839
_extends: ImplicitConversionExpr
837-
_pragma: skip_qltest # to be tested in integration tests
840+
_pragma: qltest_skip # to be tested in integration tests
838841

839842
ClassMetatypeToObjectExpr:
840843
_extends: ImplicitConversionExpr
@@ -844,7 +847,7 @@ CollectionUpcastConversionExpr:
844847

845848
ConditionalBridgeFromObjCExpr:
846849
_extends: ImplicitConversionExpr
847-
_pragma: skip_qltest # to be tested in integration tests
850+
_pragma: qltest_skip # to be tested in integration tests
848851

849852
CovariantFunctionConversionExpr:
850853
_extends: ImplicitConversionExpr

swift/codegen/test/test_qlgen.py

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,13 @@ def test_test_properties_skipped(opts, generate_tests):
480480
write(opts.ql_test_output / "Derived" / "test.swift")
481481
assert generate_tests([
482482
schema.Class("Base", derived={"Derived"}, properties=[
483-
schema.SingleProperty("x", "string", pragmas=["skip_qltest", "foo"]),
484-
schema.RepeatedProperty("y", "int", pragmas=["bar", "skip_qltest"]),
483+
schema.SingleProperty("x", "string", pragmas=["qltest_skip", "foo"]),
484+
schema.RepeatedProperty("y", "int", pragmas=["bar", "qltest_skip"]),
485485
]),
486486
schema.Class("Derived", bases={"Base"}, properties=[
487-
schema.PredicateProperty("a", pragmas=["skip_qltest"]),
487+
schema.PredicateProperty("a", pragmas=["qltest_skip"]),
488488
schema.OptionalProperty(
489-
"b", "int", pragmas=["bar", "skip_qltest", "baz"]),
489+
"b", "int", pragmas=["bar", "qltest_skip", "baz"]),
490490
]),
491491
]) == {
492492
"Derived/Derived.ql": ql.ClassTester(class_name="Derived"),
@@ -496,7 +496,7 @@ def test_test_properties_skipped(opts, generate_tests):
496496
def test_test_base_class_skipped(opts, generate_tests):
497497
write(opts.ql_test_output / "Derived" / "test.swift")
498498
assert generate_tests([
499-
schema.Class("Base", derived={"Derived"}, pragmas=["skip_qltest", "foo"], properties=[
499+
schema.Class("Base", derived={"Derived"}, pragmas=["qltest_skip", "foo"], properties=[
500500
schema.SingleProperty("x", "string"),
501501
schema.RepeatedProperty("y", "int"),
502502
]),
@@ -510,12 +510,54 @@ def test_test_final_class_skipped(opts, generate_tests):
510510
write(opts.ql_test_output / "Derived" / "test.swift")
511511
assert generate_tests([
512512
schema.Class("Base", derived={"Derived"}),
513-
schema.Class("Derived", bases={"Base"}, pragmas=["skip_qltest", "foo"], properties=[
513+
schema.Class("Derived", bases={"Base"}, pragmas=["qltest_skip", "foo"], properties=[
514514
schema.SingleProperty("x", "string"),
515515
schema.RepeatedProperty("y", "int"),
516516
]),
517517
]) == {}
518518

519519

520+
def test_test_class_hierarchy_collapse(opts, generate_tests):
521+
write(opts.ql_test_output / "Base" / "test.swift")
522+
assert generate_tests([
523+
schema.Class("Base", derived={"D1", "D2"}, pragmas=["foo", "qltest_collapse_hierarchy"]),
524+
schema.Class("D1", bases={"Base"}, properties=[schema.SingleProperty("x", "string")]),
525+
schema.Class("D2", bases={"Base"}, derived={"D3"}, properties=[schema.SingleProperty("y", "string")]),
526+
schema.Class("D3", bases={"D2"}, properties=[schema.SingleProperty("z", "string")]),
527+
]) == {
528+
"Base/Base.ql": ql.ClassTester(class_name="Base"),
529+
}
530+
531+
532+
def test_test_class_hierarchy_uncollapse(opts, generate_tests):
533+
for d in ("Base", "D3", "D4"):
534+
write(opts.ql_test_output / d / "test.swift")
535+
assert generate_tests([
536+
schema.Class("Base", derived={"D1", "D2"}, pragmas=["foo", "qltest_collapse_hierarchy"]),
537+
schema.Class("D1", bases={"Base"}, properties=[schema.SingleProperty("x", "string")]),
538+
schema.Class("D2", bases={"Base"}, derived={"D3", "D4"}, pragmas=["qltest_uncollapse_hierarchy", "bar"]),
539+
schema.Class("D3", bases={"D2"}),
540+
schema.Class("D4", bases={"D2"}),
541+
]) == {
542+
"Base/Base.ql": ql.ClassTester(class_name="Base"),
543+
"D3/D3.ql": ql.ClassTester(class_name="D3"),
544+
"D4/D4.ql": ql.ClassTester(class_name="D4"),
545+
}
546+
547+
548+
def test_test_class_hierarchy_uncollapse_at_final(opts, generate_tests):
549+
for d in ("Base", "D3"):
550+
write(opts.ql_test_output / d / "test.swift")
551+
assert generate_tests([
552+
schema.Class("Base", derived={"D1", "D2"}, pragmas=["foo", "qltest_collapse_hierarchy"]),
553+
schema.Class("D1", bases={"Base"}, properties=[schema.SingleProperty("x", "string")]),
554+
schema.Class("D2", bases={"Base"}, derived={"D3"}),
555+
schema.Class("D3", bases={"D2"}, pragmas=["qltest_uncollapse_hierarchy", "bar"]),
556+
]) == {
557+
"Base/Base.ql": ql.ClassTester(class_name="Base"),
558+
"D3/D3.ql": ql.ClassTester(class_name="D3"),
559+
}
560+
561+
520562
if __name__ == '__main__':
521563
sys.exit(pytest.main([__file__] + sys.argv[1:]))

0 commit comments

Comments
 (0)