Skip to content

Commit f4a7e4c

Browse files
authored
[Compile Time Constant Extraction] Extract result builder-type information (#63091)
1 parent 9618083 commit f4a7e4c

File tree

2 files changed

+136
-1
lines changed

2 files changed

+136
-1
lines changed

Diff for: lib/ConstExtract/ConstExtract.cpp

+34-1
Original file line numberDiff line numberDiff line change
@@ -646,14 +646,46 @@ void writeEnumCases(
646646
});
647647
}
648648

649+
void writeResultBuilderInformation(llvm::json::OStream &JSON,
650+
const swift::NominalTypeDecl *TypeDecl,
651+
const swift::VarDecl *VarDecl) {
652+
if (auto *attr = VarDecl->getAttachedResultBuilder()) {
653+
JSON.attributeObject("resultBuilder", [&] {
654+
JSON.attribute("type", toFullyQualifiedTypeNameString(attr->getType()));
655+
});
656+
657+
return;
658+
}
659+
660+
for (ProtocolDecl *Decl :
661+
TypeDecl->getLocalProtocols(ConformanceLookupKind::All)) {
662+
for (auto Member : Decl->getMembers()) {
663+
if (auto *VD = dyn_cast<swift::VarDecl>(Member)) {
664+
if (VD->getName() != VarDecl->getName())
665+
continue;
666+
667+
if (auto *attr = VD->getAttachedResultBuilder()) {
668+
JSON.attributeObject("resultBuilder", [&] {
669+
JSON.attribute("type",
670+
toFullyQualifiedTypeNameString(attr->getType()));
671+
});
672+
}
673+
674+
return;
675+
}
676+
}
677+
}
678+
}
679+
649680
bool writeAsJSONToFile(const std::vector<ConstValueTypeInfo> &ConstValueInfos,
650681
llvm::raw_fd_ostream &OS) {
651682
llvm::json::OStream JSON(OS, 2);
652683
JSON.array([&] {
653684
for (const auto &TypeInfo : ConstValueInfos) {
654685
JSON.object([&] {
655686
const auto *TypeDecl = TypeInfo.TypeDecl;
656-
JSON.attribute("typeName", toFullyQualifiedTypeNameString(TypeDecl->getDeclaredInterfaceType()));
687+
JSON.attribute("typeName", toFullyQualifiedTypeNameString(
688+
TypeDecl->getDeclaredInterfaceType()));
657689
JSON.attribute(
658690
"kind",
659691
TypeDecl->getDescriptiveKindName(TypeDecl->getDescriptiveKind())
@@ -672,6 +704,7 @@ bool writeAsJSONToFile(const std::vector<ConstValueTypeInfo> &ConstValueInfos,
672704
writeFileInformation(JSON, decl);
673705
writeValue(JSON, PropertyInfo.Value);
674706
writeAttributes(JSON, PropertyInfo.PropertyWrappers);
707+
writeResultBuilderInformation(JSON, TypeDecl, decl);
675708
});
676709
}
677710
});

Diff for: test/ConstExtraction/ExtractResultBuilders.swift

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/inputs)
3+
// RUN: echo "[FooProvider]" > %t/inputs/protocols.json
4+
5+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractResultBuilders.swiftconstvalues -const-gather-protocols-file %t/inputs/protocols.json -primary-file %s
6+
// RUN: cat %t/ExtractResultBuilders.swiftconstvalues 2>&1 | %FileCheck %s
7+
8+
public struct Foo {
9+
let name: String
10+
}
11+
12+
@resultBuilder
13+
public enum FooBuilder {
14+
public static func buildExpression(_ component: Foo) -> Foo {
15+
component
16+
}
17+
18+
public static func buildBlock(_ components: Foo...) -> [Foo] {
19+
components
20+
}
21+
}
22+
23+
public protocol FooProvider {
24+
@FooBuilder
25+
static var foos: [Foo] { get }
26+
}
27+
28+
public struct MyFooProvider: FooProvider {
29+
@FooBuilder
30+
public static var foos: [Foo] {
31+
Foo(name: "AAA")
32+
Foo(name: "BBB")
33+
}
34+
35+
@FooBuilder
36+
public static var fooTwo: [Foo] {
37+
Foo(name: "111")
38+
Foo(name: "222")
39+
}
40+
}
41+
42+
public struct MyFooProviderInferred: FooProvider {
43+
public static var foos: [Foo] {
44+
Foo(name: "CCC")
45+
Foo(name: "DDD")
46+
}
47+
}
48+
49+
// CHECK: [
50+
// CHECK-NEXT: {
51+
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProvider",
52+
// CHECK-NEXT: "kind": "struct",
53+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
54+
// CHECK-NEXT: "line": 28,
55+
// CHECK-NEXT: "properties": [
56+
// CHECK-NEXT: {
57+
// CHECK-NEXT: "label": "foos",
58+
// CHECK-NEXT: "type": "[ExtractResultBuilders.Foo]",
59+
// CHECK-NEXT: "isStatic": "true",
60+
// CHECK-NEXT: "isComputed": "true",
61+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
62+
// CHECK-NEXT: "line": 30,
63+
// CHECK-NEXT: "valueKind": "Runtime",
64+
// CHECK-NEXT: "resultBuilder": {
65+
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
66+
// CHECK-NEXT: }
67+
// CHECK-NEXT: },
68+
// CHECK-NEXT: {
69+
// CHECK-NEXT: "label": "fooTwo",
70+
// CHECK-NEXT: "type": "[ExtractResultBuilders.Foo]",
71+
// CHECK-NEXT: "isStatic": "true",
72+
// CHECK-NEXT: "isComputed": "true",
73+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
74+
// CHECK-NEXT: "line": 36,
75+
// CHECK-NEXT: "valueKind": "Runtime",
76+
// CHECK-NEXT: "resultBuilder": {
77+
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
78+
// CHECK-NEXT: }
79+
// CHECK-NEXT: }
80+
// CHECK-NEXT: ]
81+
// CHECK-NEXT: },
82+
// CHECK-NEXT: {
83+
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProviderInferred",
84+
// CHECK-NEXT: "kind": "struct",
85+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
86+
// CHECK-NEXT: "line": 42,
87+
// CHECK-NEXT: "properties": [
88+
// CHECK-NEXT: {
89+
// CHECK-NEXT: "label": "foos",
90+
// CHECK-NEXT: "type": "[ExtractResultBuilders.Foo]",
91+
// CHECK-NEXT: "isStatic": "true",
92+
// CHECK-NEXT: "isComputed": "true",
93+
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
94+
// CHECK-NEXT: "line": 43,
95+
// CHECK-NEXT: "valueKind": "Runtime",
96+
// CHECK-NEXT: "resultBuilder": {
97+
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
98+
// CHECK-NEXT: }
99+
// CHECK-NEXT: }
100+
// CHECK-NEXT: ]
101+
// CHECK-NEXT: }
102+
// CHECK-NEXT: ]

0 commit comments

Comments
 (0)