Merge pull request #75219 from venkatesh5789/result-builder-extraction

[Compile Time Constant Extraction] Extract Result Builder Expressions
This commit is contained in:
Venkatesh Sriram
2024-07-24 18:27:17 -07:00
committed by GitHub
3 changed files with 847 additions and 96 deletions

View File

@@ -96,17 +96,155 @@ private:
std::vector<FunctionParameter> Parameters;
};
/// A representation of a Builder pattern initialization expression
/// A representation of a Builder pattern initialization expression. For
/// example:
///
/// @FooBuilder
/// public static var foos: [Foo] {
/// Foo(name: "foos.1")
/// Foo(name: "foos.2")
/// }
///
/// In this example, the result builder type is FooBuilder
/// The members are Foo(name: "foos.1") and Foo(name: "foos.2")
///
class BuilderValue : public CompileTimeValue {
public:
BuilderValue() : CompileTimeValue(ValueKind::Builder) {}
enum MemberKind {
Expression,
Either,
Optional,
LimitedAvailability,
Array,
Unknown
};
/// A base class for individual members being declared inside the result
/// builder
class BuilderMember {
public:
MemberKind getKind() const { return Kind; }
protected:
BuilderMember(MemberKind MemberKind) : Kind(MemberKind) {}
private:
MemberKind Kind;
};
/// A basic expression that is defined inside the result builder. For example:
/// {
/// Foo(name: "1")
/// }
///
class SingleMember : public BuilderMember {
public:
SingleMember(std::shared_ptr<CompileTimeValue> Element)
: BuilderMember(MemberKind::Expression), Element(Element) {}
static bool classof(const BuilderMember *T) {
return T->getKind() == MemberKind::Expression;
}
std::shared_ptr<CompileTimeValue> getElement() const { return Element; }
private:
std::shared_ptr<CompileTimeValue> Element;
};
/// A member that represents when the individual values are defined by
/// iterating over an array. For example:
/// for i in 1...3 {
/// Foo(name: "MyFooProviderInferred.foos.Array.\(i)")
/// }
///
class ArrayMember : public BuilderMember {
public:
ArrayMember(std::vector<std::shared_ptr<BuilderMember>> Elements)
: BuilderMember(MemberKind::Array), Elements(Elements) {}
static bool classof(const BuilderMember *T) {
return T->getKind() == MemberKind::Array;
}
std::vector<std::shared_ptr<BuilderMember>> getElements() const {
return Elements;
}
private:
std::vector<std::shared_ptr<BuilderMember>> Elements;
};
/// A member that is defined conditionally. It can be of the following types:
///
/// 1. A regular if-else condition
/// if condition {
/// Foo(name: "1")
/// } else {
/// Foo(name: "2")
/// }
///
/// 2. An optional
/// if condition {
/// Foo(name: "1")
/// }
///
/// 3. Limited availability
/// if #available(macOS 99, *) {
/// Foo(name: "1")
/// Foo(name: "2")
/// }
///
class ConditionalMember : public BuilderMember {
public:
ConditionalMember(MemberKind MemberKind,
std::vector<std::shared_ptr<BuilderMember>> IfElements,
std::vector<std::shared_ptr<BuilderMember>> ElseElements)
: BuilderMember(MemberKind), IfElements(IfElements),
ElseElements(ElseElements) {}
static bool classof(const BuilderMember *T) {
auto Kind = T->getKind();
return (Kind == MemberKind::Either) ||
(Kind == MemberKind::LimitedAvailability) ||
(Kind == MemberKind::Optional);
}
std::vector<std::shared_ptr<BuilderMember>> getIfElements() const {
return IfElements;
}
std::vector<std::shared_ptr<BuilderMember>> getElseElements() const {
return ElseElements;
}
private:
std::vector<std::shared_ptr<BuilderMember>> IfElements;
std::vector<std::shared_ptr<BuilderMember>> ElseElements;
};
BuilderValue(std::vector<std::shared_ptr<BuilderMember>> Members)
: CompileTimeValue(ValueKind::Builder), ResultBuilderType(std::nullopt),
Members(Members) {}
BuilderValue(CustomAttr *ResultBuilderType,
std::vector<std::shared_ptr<BuilderMember>> Members)
: CompileTimeValue(ValueKind::Builder),
ResultBuilderType(ResultBuilderType), Members(Members) {}
std::optional<CustomAttr *> getResultBuilderType() const {
return ResultBuilderType;
}
std::vector<std::shared_ptr<BuilderMember>> getMembers() const {
return Members;
}
static bool classof(const CompileTimeValue *T) {
return T->getKind() == ValueKind::Builder;
}
private:
std::vector<CompileTimeValue> Members;
std::optional<CustomAttr *> ResultBuilderType;
std::vector<std::shared_ptr<BuilderMember>> Members;
};
struct TupleElement {

View File

@@ -166,6 +166,9 @@ parseProtocolListFromFile(StringRef protocolListFilePath,
return true;
}
std::vector<std::shared_ptr<BuilderValue::BuilderMember>>
getResultBuilderMembersFromBraceStmt(BraceStmt *braceStmt);
static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr);
static std::vector<FunctionParameter>
@@ -453,6 +456,16 @@ static std::shared_ptr<CompileTimeValue> extractCompileTimeValue(Expr *expr) {
return std::make_shared<InterpolatedStringLiteralValue>(segments);
}
case ExprKind::Closure: {
auto closureExpr = cast<ClosureExpr>(expr);
auto body = closureExpr->getBody();
auto resultBuilderMembers = getResultBuilderMembersFromBraceStmt(body);
if (!resultBuilderMembers.empty()) {
return std::make_shared<BuilderValue>(resultBuilderMembers);
}
break;
}
default: {
break;
}
@@ -662,6 +675,10 @@ void writeLocationInformation(llvm::json::OStream &JSON, SourceLoc Loc,
ctx.SourceMgr.getPresumedLineAndColumnForLoc(Loc).first);
}
// Take BuilderValue, which is a representation of a result builder
// and write the values
void writeBuilderValue(llvm::json::OStream &JSON, BuilderValue *Value);
void writeValue(llvm::json::OStream &JSON,
std::shared_ptr<CompileTimeValue> Value) {
auto value = Value.get();
@@ -711,7 +728,8 @@ void writeValue(llvm::json::OStream &JSON,
}
case CompileTimeValue::ValueKind::Builder: {
JSON.attribute("valueKind", "Builder");
auto builderValue = cast<BuilderValue>(value);
writeBuilderValue(JSON, builderValue);
break;
}
@@ -913,15 +931,230 @@ void writeEnumCases(
});
}
void writeResultBuilderInformation(llvm::json::OStream &JSON,
const swift::NominalTypeDecl *TypeDecl,
const swift::VarDecl *VarDecl) {
if (auto *attr = VarDecl->getAttachedResultBuilder()) {
JSON.attributeObject("resultBuilder", [&] {
JSON.attribute("type", toFullyQualifiedTypeNameString(attr->getType()));
std::optional<std::shared_ptr<CompileTimeValue>>
getResultBuilderElementFromASTNode(const ASTNode node) {
if (auto *D = node.dyn_cast<Decl *>()) {
if (auto *patternBinding = dyn_cast<PatternBindingDecl>(D)) {
if (auto originalInit = patternBinding->getOriginalInit(0)) {
return extractCompileTimeValue(originalInit);
}
}
}
return std::nullopt;
}
BuilderValue::ConditionalMember
getConditionalMemberFromIfStmt(const IfStmt *ifStmt) {
std::vector<std::shared_ptr<BuilderValue::BuilderMember>> IfElements;
std::vector<std::shared_ptr<BuilderValue::BuilderMember>> ElseElements;
if (auto thenBraceStmt = ifStmt->getThenStmt()) {
for (auto elem : thenBraceStmt->getElements()) {
if (auto memberElement = getResultBuilderElementFromASTNode(elem)) {
IfElements.push_back(std::make_shared<BuilderValue::SingleMember>(
memberElement.value()));
}
}
}
if (auto elseStmt = ifStmt->getElseStmt()) {
if (auto *elseIfStmt = dyn_cast<IfStmt>(elseStmt)) {
ElseElements.push_back(std::make_shared<BuilderValue::ConditionalMember>(
getConditionalMemberFromIfStmt(elseIfStmt)));
} else if (auto *elseBraceStmt = dyn_cast<BraceStmt>(elseStmt)) {
for (auto elem : elseBraceStmt->getElements()) {
if (auto memberElement = getResultBuilderElementFromASTNode(elem)) {
ElseElements.push_back(std::make_shared<BuilderValue::SingleMember>(
memberElement.value()));
}
}
}
}
BuilderValue::MemberKind memberKind = BuilderValue::Either;
if (ElseElements.size() == 0) {
memberKind = BuilderValue::Optional;
}
for (auto elt : ifStmt->getCond()) {
if (elt.getKind() == StmtConditionElement::CK_Availability) {
memberKind = BuilderValue::LimitedAvailability;
break;
}
}
return BuilderValue::ConditionalMember(memberKind, IfElements, ElseElements);
}
BuilderValue::ArrayMember
getBuildArrayMemberFromForEachStmt(const ForEachStmt *forEachStmt) {
std::vector<std::shared_ptr<BuilderValue::BuilderMember>> MemberElements;
if (auto braceStmt = forEachStmt->getBody()) {
for (auto elem : braceStmt->getElements()) {
if (auto memberElement = getResultBuilderElementFromASTNode(elem)) {
MemberElements.push_back(std::make_shared<BuilderValue::SingleMember>(
memberElement.value()));
}
}
}
return BuilderValue::ArrayMember(MemberElements);
}
std::vector<std::shared_ptr<BuilderValue::BuilderMember>>
getResultBuilderMembersFromBraceStmt(BraceStmt *braceStmt) {
std::vector<std::shared_ptr<BuilderValue::BuilderMember>>
ResultBuilderMembers;
for (auto elem : braceStmt->getElements()) {
if (auto resultBuilderElement = getResultBuilderElementFromASTNode(elem)) {
ResultBuilderMembers.push_back(
std::make_shared<BuilderValue::SingleMember>(
resultBuilderElement.value()));
} else if (auto *stmt = elem.dyn_cast<Stmt *>()) {
if (auto *ifStmt = dyn_cast<IfStmt>(stmt)) {
ResultBuilderMembers.push_back(
std::make_shared<BuilderValue::ConditionalMember>(
getConditionalMemberFromIfStmt(ifStmt)));
} else if (auto *doStmt = dyn_cast<DoStmt>(stmt)) {
if (auto body = doStmt->getBody()) {
for (auto elem : body->getElements()) {
if (auto *stmt = elem.dyn_cast<Stmt *>()) {
if (auto *forEachStmt = dyn_cast<ForEachStmt>(stmt)) {
ResultBuilderMembers.push_back(
std::make_shared<BuilderValue::ArrayMember>(
getBuildArrayMemberFromForEachStmt(forEachStmt)));
}
}
}
}
}
}
}
return ResultBuilderMembers;
}
std::shared_ptr<BuilderValue>
createBuilderCompileTimeValue(CustomAttr *AttachedResultBuilder,
const swift::VarDecl *VarDecl) {
std::vector<std::shared_ptr<BuilderValue::BuilderMember>>
ResultBuilderMembers;
if (!VarDecl->getAllAccessors().empty()) {
if (auto accessor = VarDecl->getAllAccessors()[0]) {
if (auto braceStmt = accessor->getTypecheckedBody()) {
ResultBuilderMembers = getResultBuilderMembersFromBraceStmt(braceStmt);
}
}
}
return std::make_shared<BuilderValue>(AttachedResultBuilder,
ResultBuilderMembers);
}
void writeSingleBuilderMemberElement(
llvm::json::OStream &JSON, std::shared_ptr<CompileTimeValue> Element) {
switch (Element.get()->getKind()) {
case CompileTimeValue::ValueKind::Enum: {
auto enumValue = cast<EnumValue>(Element.get());
if (enumValue->getIdentifier() == "buildExpression") {
if (enumValue->getParameters().has_value()) {
auto params = enumValue->getParameters().value();
for (auto FP : params) {
writeValue(JSON, FP.Value);
}
}
}
break;
}
default: {
writeValue(JSON, Element);
break;
}
}
}
void writeBuilderMember(
llvm::json::OStream &JSON,
std::shared_ptr<BuilderValue::BuilderMember> BuilderMember) {
auto Member = BuilderMember.get();
switch (Member->getKind()) {
case BuilderValue::Expression: {
auto member = cast<BuilderValue::SingleMember>(Member);
JSON.attributeObject("element", [&] {
writeSingleBuilderMemberElement(JSON, member->getElement());
});
return;
break;
}
case BuilderValue::Array: {
auto member = cast<BuilderValue::ArrayMember>(Member);
JSON.attributeArray("elements", [&] {
for (auto elem : member->getElements()) {
JSON.object([&] { writeBuilderMember(JSON, elem); });
}
});
break;
}
default: {
auto member = cast<BuilderValue::ConditionalMember>(Member);
JSON.attributeArray("ifElements", [&] {
for (auto elem : member->getIfElements()) {
JSON.object([&] { writeBuilderMember(JSON, elem); });
}
});
JSON.attributeArray("elseElements", [&] {
for (auto elem : member->getElseElements()) {
JSON.object([&] { writeBuilderMember(JSON, elem); });
}
});
break;
}
}
}
void writeBuilderValue(llvm::json::OStream &JSON, BuilderValue *Value) {
JSON.attribute("valueKind", "Builder");
JSON.attributeObject("value", [&] {
if (auto resultBuilderType = Value->getResultBuilderType()) {
JSON.attribute("type", toFullyQualifiedTypeNameString(
resultBuilderType.value()->getType()));
} else {
JSON.attribute("type", "");
}
JSON.attributeArray("members", [&] {
for (auto member : Value->getMembers()) {
JSON.object([&] {
switch (member->getKind()) {
case BuilderValue::Expression:
JSON.attribute("kind", "buildExpression");
break;
case BuilderValue::Either:
JSON.attribute("kind", "buildEither");
break;
case BuilderValue::Optional:
JSON.attribute("kind", "buildOptional");
break;
case BuilderValue::LimitedAvailability:
JSON.attribute("kind", "buildLimitedAvailability");
break;
case BuilderValue::Array:
JSON.attribute("kind", "buildArray");
break;
case BuilderValue::Unknown:
JSON.attribute("kind", "Unknown");
break;
}
writeBuilderMember(JSON, member);
});
}
});
});
}
std::optional<std::shared_ptr<BuilderValue>>
extractBuilderValueIfExists(const swift::NominalTypeDecl *TypeDecl,
const swift::VarDecl *VarDecl) {
if (auto *attr = VarDecl->getAttachedResultBuilder()) {
return createBuilderCompileTimeValue(attr, VarDecl);
}
for (ProtocolDecl *Decl :
@@ -936,16 +1169,13 @@ void writeResultBuilderInformation(llvm::json::OStream &JSON,
continue;
if (auto *attr = VD->getAttachedResultBuilder()) {
JSON.attributeObject("resultBuilder", [&] {
JSON.attribute("type",
toFullyQualifiedTypeNameString(attr->getType()));
});
return createBuilderCompileTimeValue(attr, VarDecl);
}
return;
}
}
}
return std::nullopt;
;
}
void writeAttrInformation(llvm::json::OStream &JSON,
@@ -1068,10 +1298,14 @@ void writeProperties(llvm::json::OStream &JSON,
JSON.attribute("isComputed", !decl->hasStorage() ? "true" : "false");
writeLocationInformation(JSON, decl->getLoc(),
decl->getDeclContext()->getASTContext());
writeValue(JSON, PropertyInfo.Value);
if (auto builderValue =
extractBuilderValueIfExists(&NomTypeDecl, decl)) {
writeValue(JSON, builderValue.value());
} else {
writeValue(JSON, PropertyInfo.Value);
}
writePropertyWrapperAttributes(JSON, PropertyInfo.PropertyWrappers,
decl->getASTContext());
writeResultBuilderInformation(JSON, &NomTypeDecl, decl);
writeAttrInformation(JSON, decl->getAttrs());
});
}

View File

@@ -7,16 +7,59 @@
public struct Foo {
let name: String
let baz: String = ""
public init(name: String) {
self.name = name
}
public init(name: String, @SimpleStringBuilder baz: () -> String) {
self.name = name
self.baz = baz()
}
}
@resultBuilder
struct SimpleStringBuilder {
static func buildBlock(_ parts: String...) -> String {
parts.joined(separator: "\n")
}
}
@resultBuilder
public enum FooBuilder {
public static func buildExpression(_ component: Foo) -> Foo {
component
public typealias Component = [Foo]
public typealias Expression = Foo
public static func buildExpression(_ element: Expression) -> Component {
return [element]
}
public static func buildBlock(_ components: Foo...) -> [Foo] {
components
public static func buildOptional(_ component: Component?) -> Component {
guard let component = component else {
return []
}
return component
}
public static func buildEither(first component: Component) -> Component {
return component
}
public static func buildEither(second component: Component) -> Component {
return component
}
public static func buildArray(_ components: [Component]) -> Component {
return Array(components.joined())
}
public static func buildBlock(_ components: Component...) -> Component {
return components.flatMap { $0 }
}
public static func buildLimitedAvailability(_ component: Component) -> Component {
return component
}
}
@@ -28,88 +71,424 @@ public protocol FooProvider {
public struct MyFooProvider: FooProvider {
@FooBuilder
public static var foos: [Foo] {
Foo(name: "AAA")
Foo(name: "BBB")
Foo(name: "MyFooProvider.foos.1")
Foo(name: "MyFooProvider.foos.2")
}
@FooBuilder
public static var fooTwo: [Foo] {
Foo(name: "111")
Foo(name: "222")
public static var bars: [Foo] {
Foo(name: "MyFooProvider.bars.1")
Foo(name: "MyFooProvider.bars.2")
}
}
let someNumber = Int.random(in: 0...10)
public struct MyFooProviderInferred: FooProvider {
public static var foos: [Foo] {
Foo(name: "CCC")
Foo(name: "DDD")
Foo(name: "MyFooProviderInferred.foos.1", baz: {
"Nested.Builder.1"
"Nested.Builder.2"
})
Foo(name: "MyFooProviderInferred.foos.2")
if someNumber < 3 {
Foo(name: "MyFooProviderInferred.foos.if.LessThan3")
} else if someNumber < 7 {
Foo(name: "MyFooProviderInferred.foos.elseif.Between3And6")
} else {
Foo(name: "MyFooProviderInferred.foos.else.Between7And10")
}
for i in 1...3 {
Foo(name: "MyFooProviderInferred.foos.Array.\(i)")
}
if (Bool.random()) {
Foo(name: "MyFooProviderInferred.foos.Optional")
}
if #available(macOS 99, *) {
Foo(name: "MyFooProviderInferred.foos.limitedAvailability.1")
Foo(name: "MyFooProviderInferred.foos.limitedAvailability.2")
} else {
Foo(name: "MyFooProviderInferred.foos.limitedAvailability.else")
}
}
}
// CHECK: [
// CHECK-NEXT: {
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProvider",
// CHECK-NEXT: "mangledTypeName": "21ExtractResultBuilders13MyFooProviderV",
// CHECK-NEXT: "kind": "struct",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 28,
// CHECK-NEXT: "conformances": [
// CHECK-NEXT: "ExtractResultBuilders.FooProvider"
// CHECK-NEXT: ],
// CHECK-NEXT: "associatedTypeAliases": [],
// CHECK-NEXT: "properties": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "foos",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 30,
// CHECK-NEXT: "valueKind": "Runtime",
// CHECK-NEXT: "resultBuilder": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "fooTwo",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 36,
// CHECK-NEXT: "valueKind": "Runtime",
// CHECK-NEXT: "resultBuilder": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProviderInferred",
// CHECK-NEXT: "mangledTypeName": "21ExtractResultBuilders21MyFooProviderInferredV",
// CHECK-NEXT: "kind": "struct",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 42,
// CHECK-NEXT: "conformances": [
// CHECK-NEXT: "ExtractResultBuilders.FooProvider"
// CHECK-NEXT: ],
// CHECK-NEXT: "associatedTypeAliases": [],
// CHECK-NEXT: "properties": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "foos",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 43,
// CHECK-NEXT: "valueKind": "Runtime",
// CHECK-NEXT: "resultBuilder": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: {
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProvider",
// CHECK-NEXT: "mangledTypeName": "21ExtractResultBuilders13MyFooProviderV",
// CHECK-NEXT: "kind": "struct",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 71,
// CHECK-NEXT: "conformances": [
// CHECK-NEXT: "ExtractResultBuilders.FooProvider"
// CHECK-NEXT: ],
// CHECK-NEXT: "associatedTypeAliases": [],
// CHECK-NEXT: "properties": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "foos",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 73,
// CHECK-NEXT: "valueKind": "Builder",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder",
// CHECK-NEXT: "members": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProvider.foos.1"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProvider.foos.2"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "bars",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 79,
// CHECK-NEXT: "valueKind": "Builder",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder",
// CHECK-NEXT: "members": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProvider.bars.1"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProvider.bars.2"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "typeName": "ExtractResultBuilders.MyFooProviderInferred",
// CHECK-NEXT: "mangledTypeName": "21ExtractResultBuilders21MyFooProviderInferredV",
// CHECK-NEXT: "kind": "struct",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 87,
// CHECK-NEXT: "conformances": [
// CHECK-NEXT: "ExtractResultBuilders.FooProvider"
// CHECK-NEXT: ],
// CHECK-NEXT: "associatedTypeAliases": [],
// CHECK-NEXT: "properties": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "foos",
// CHECK-NEXT: "type": "Swift.Array<ExtractResultBuilders.Foo>",
// CHECK-NEXT: "mangledTypeName": "n/a - deprecated",
// CHECK-NEXT: "isStatic": "true",
// CHECK-NEXT: "isComputed": "true",
// CHECK-NEXT: "file": "{{.*}}test{{/|\\\\}}ConstExtraction{{/|\\\\}}ExtractResultBuilders.swift",
// CHECK-NEXT: "line": 88,
// CHECK-NEXT: "valueKind": "Builder",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.FooBuilder",
// CHECK-NEXT: "members": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.1"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "label": "baz",
// CHECK-NEXT: "type": "() -> Swift.String",
// CHECK-NEXT: "valueKind": "Builder",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "",
// CHECK-NEXT: "members": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "Nested.Builder.1"
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "Nested.Builder.2"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildExpression",
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.2"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildEither",
// CHECK-NEXT: "ifElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.if.LessThan3"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "elseElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "ifElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.elseif.Between3And6"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "elseElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.else.Between7And10"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildArray",
// CHECK-NEXT: "elements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "InterpolatedStringLiteral",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "segments": [
// CHECK-NEXT: {
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.Array."
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "valueKind": "Runtime"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": ""
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildOptional",
// CHECK-NEXT: "ifElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.Optional"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "elseElements": []
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "buildLimitedAvailability",
// CHECK-NEXT: "ifElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.limitedAvailability.1"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.limitedAvailability.2"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "element": {}
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "elseElements": [
// CHECK-NEXT: {
// CHECK-NEXT: "element": {
// CHECK-NEXT: "valueKind": "InitCall",
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "ExtractResultBuilders.Foo",
// CHECK-NEXT: "arguments": [
// CHECK-NEXT: {
// CHECK-NEXT: "label": "name",
// CHECK-NEXT: "type": "Swift.String",
// CHECK-NEXT: "valueKind": "RawLiteral",
// CHECK-NEXT: "value": "MyFooProviderInferred.foos.limitedAvailability.else"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]