Skip to content

Commit fe7a336

Browse files
committed
[SwiftSyntaxBuilder] Add support for control flow statements in result builders
Add the `buildOptional` etc. result builder constructs to add support for control-flow constructs inside the result builders.
1 parent 185114c commit fe7a336

File tree

3 files changed

+2504
-87
lines changed

3 files changed

+2504
-87
lines changed

Sources/SwiftSyntaxBuilder/ResultBuilders.swift.gyb

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,65 @@ import SwiftSyntax
2626
@resultBuilder
2727
public struct ${node.syntax_kind}Builder {
2828
% element_type = syntax_buildable_child_type(node.collection_element_type, node.collection_element, node.is_token())
29-
public static func buildBlock(_ elements: ${element_type}...) -> ${node.syntax_kind} {
30-
${node.syntax_kind}(elements)
29+
30+
/// The type of individual statement expressions in the transformed function,
31+
/// which defaults to Component if buildExpression() is not provided.
32+
public typealias Expression = ${element_type}
33+
34+
/// The type of a partial result, which will be carried through all of the
35+
/// build methods.
36+
public typealias Component = [${element_type}]
37+
38+
/// The type of the final returned result, which defaults to Component if
39+
/// buildFinalResult() is not provided.
40+
public typealias FinalResult = ${node.syntax_kind}
41+
42+
/// Required by every result builder to build combined results from
43+
/// statement blocks.
44+
public static func buildBlock(_ components: Component...) -> Component {
45+
components.flatMap { $0 }
46+
}
47+
48+
/// If declared, provides contextual type information for statement
49+
/// expressions to translate them into partial results.
50+
public static func buildExpression(_ expression: Expression) -> Component {
51+
[expression]
52+
}
53+
54+
/// Enables support for `if` statements that do not have an `else`.
55+
public static func buildOptional(_ component: Component?) -> Component {
56+
component ?? []
57+
}
58+
59+
/// With buildEither(second:), enables support for 'if-else' and 'switch'
60+
/// statements by folding conditional results into a single result.
61+
public static func buildEither(first component: Component) -> Component {
62+
component
63+
}
64+
65+
/// With buildEither(first:), enables support for 'if-else' and 'switch'
66+
/// statements by folding conditional results into a single result.
67+
public static func buildEither(second component: Component) -> Component {
68+
component
69+
}
70+
71+
/// Enables support for 'for..in' loops by combining the
72+
/// results of all iterations into a single result.
73+
public static func buildArray(_ components: [Component]) -> Component {
74+
components.flatMap { $0 }
75+
}
76+
77+
/// If declared, this will be called on the partial result of an 'if
78+
/// #available' block to allow the result builder to erase type
79+
/// information.
80+
public static func buildLimitedAvailability(_ component: Component) -> Component {
81+
component
82+
}
83+
84+
/// If declared, this will be called on the partial result from the outermost
85+
/// block statement to produce the final returned result.
86+
public static func buildFinalResult(_ component: Component) -> FinalResult {
87+
.init(component)
3188
}
3289
}
3390

@@ -36,4 +93,4 @@ extension ${node.syntax_kind} {
3693
}
3794

3895
% end
39-
% end
96+
% end

0 commit comments

Comments
 (0)