Skip to content

Commit a77db05

Browse files
authored
Merge pull request #2242 from RomanPodymov/feature/result_builders
@formbuilder
2 parents 9ead011 + 299fe75 commit a77db05

File tree

3 files changed

+120
-14
lines changed

3 files changed

+120
-14
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,22 @@ form +++ {
228228
}
229229
```
230230

231+
#### @FormBuilder
232+
```swift
233+
@FormBuilder
234+
var form: Form {
235+
Section("Section A") { section in
236+
section.tag = "Section_A"
237+
}
238+
if true {
239+
Section("Section B") { section in
240+
section.tag = "Section_B"
241+
}
242+
}
243+
NameRow("NameRow_f1") { $0.title = "Name" }
244+
}
245+
```
246+
231247
### Using the callbacks
232248

233249
Eureka includes callbacks to change the appearance and behavior of a row.

Source/Core/ResultBuilders.swift

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ extension Array: RowsProvider where Element == BaseRow {
3535
public var rows: [BaseRow] { self }
3636
}
3737

38+
public protocol SectionsProvider {
39+
var sections: [Section] { get }
40+
}
41+
42+
extension Section: SectionsProvider {
43+
public var sections: [Section] { [self] }
44+
}
45+
46+
extension Array: SectionsProvider where Element == Section {
47+
public var sections: [Section] { self }
48+
}
49+
50+
extension BaseRow: SectionsProvider {
51+
public var sections: [Section] { [.init([self])] }
52+
}
53+
3854
@resultBuilder
3955
public struct SectionBuilder {
4056
public static func buildBlock(_ components: RowsProvider...) -> [BaseRow] {
@@ -57,8 +73,35 @@ public struct SectionBuilder {
5773
components?.flatMap { $0.rows } ?? []
5874
}
5975

60-
public static func buildExpression(_ expression: BaseRow?) -> [BaseRow] {
61-
expression.flatMap { [$0] } ?? []
76+
public static func buildExpression(_ expression: RowsProvider?) -> [BaseRow] {
77+
expression.flatMap { $0.rows } ?? []
78+
}
79+
}
80+
81+
@resultBuilder
82+
public struct FormBuilder {
83+
public static func buildBlock(_ components: SectionsProvider...) -> [Section] {
84+
components.flatMap { $0.sections }
85+
}
86+
87+
public static func buildFinalResult(_ components: [Section]) -> Form {
88+
.init(components)
89+
}
90+
91+
public static func buildEither(first components: [SectionsProvider]) -> [Section] {
92+
components.flatMap { $0.sections }
93+
}
94+
95+
public static func buildEither(second components: [SectionsProvider]) -> [Section] {
96+
components.flatMap { $0.sections }
97+
}
98+
99+
public static func buildOptional(_ components: [SectionsProvider]?) -> [Section] {
100+
components?.flatMap { $0.sections } ?? []
101+
}
102+
103+
public static func buildExpression(_ expression: SectionsProvider?) -> [Section] {
104+
expression.flatMap { $0.sections } ?? []
62105
}
63106
}
64107
#endif

Tests/ResultBuildersTests.swift

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,87 @@ class ResultBuildersTests: BaseEurekaTests {
3535
}
3636
DecimalRow("DecimalRow_f1") { $0.title = "Decimal" }
3737
}
38+
39+
@FormBuilder
40+
var form: Form {
41+
Section("Section A") { section in
42+
section.tag = "Section_A"
43+
}
44+
if true {
45+
Section("Section B") { section in
46+
section.tag = "Section_B"
47+
}
48+
}
49+
NameRow("NameRow_f1") { $0.title = "Name" }
50+
}
3851
#endif
3952

53+
private var checkBuildEither = false
54+
private var checkBuildExpressionBaseRowOptional = false
55+
4056
func testSectionBuilder() {
4157
#if swift(>=5.4)
42-
var checkBuildEither = false
58+
setupManySectionsForm()
59+
addMoreItemsToManySectionsForm()
60+
61+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "NameRow_f1"))
62+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "IntRow_f1"))
63+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "DecimalRow_f1"))
64+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "UrlRow_f1"))
65+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "TwitterRow_f1"))
66+
XCTAssertNil(manySectionsForm.rowBy(tag: "TwitterRow_f2"))
67+
XCTAssertNil(manySectionsForm.rowBy(tag: "EmailRow_f1"))
68+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "AccountRow_f1"))
69+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PhoneRow_f1"))
70+
XCTAssertNil(manySectionsForm.rowBy(tag: "PhoneRow_f2"))
71+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "ZipCodeRow_f1"))
72+
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PasswordRow_f1"))
73+
#endif
74+
}
75+
76+
private func setupManySectionsForm() {
77+
checkBuildEither = false
78+
checkBuildExpressionBaseRowOptional = true
4379
manySectionsForm = (section1 +++ {
4480
URLRow("UrlRow_f1") { $0.title = "Url" }
4581
if checkBuildEither {
4682
TwitterRow("TwitterRow_f2") { $0.title = "Twitter" }
4783
} else {
4884
TwitterRow("TwitterRow_f1") { $0.title = "Twitter" }
4985
}
86+
if checkBuildExpressionBaseRowOptional {
87+
nil
88+
} else {
89+
EmailRow("EmailRow_f1") { $0.title = "Email" }
90+
}
5091
AccountRow("AccountRow_f1") { $0.title = "Account" }
5192
})
52-
checkBuildEither = true
93+
}
94+
95+
private func addMoreItemsToManySectionsForm() {
96+
checkBuildEither.toggle()
97+
checkBuildExpressionBaseRowOptional.toggle()
5398
manySectionsForm +++ {
5499
if checkBuildEither {
55100
PhoneRow("PhoneRow_f1") { $0.title = "Phone" }
56101
} else {
57102
PhoneRow("PhoneRow_f2") { $0.title = "Phone" }
58103
}
104+
if checkBuildExpressionBaseRowOptional {
105+
nil
106+
} else {
107+
ZipCodeRow("ZipCodeRow_f1") { $0.title = "Zip Code" }
108+
}
59109
PasswordRow("PasswordRow_f1") { $0.title = "Password" }
60110
}
61-
111+
}
112+
113+
func testFormBuilder() {
114+
#if swift(>=5.4)
115+
manySectionsForm = form
116+
XCTAssertNotNil(manySectionsForm.sectionBy(tag: "Section_A"))
117+
XCTAssertNotNil(manySectionsForm.sectionBy(tag: "Section_B"))
62118
XCTAssertNotNil(manySectionsForm.rowBy(tag: "NameRow_f1"))
63-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "IntRow_f1"))
64-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "DecimalRow_f1"))
65-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "UrlRow_f1"))
66-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "TwitterRow_f1"))
67-
XCTAssertNil(manySectionsForm.rowBy(tag: "TwitterRow_f2"))
68-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "AccountRow_f1"))
69-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PhoneRow_f1"))
70-
XCTAssertNil(manySectionsForm.rowBy(tag: "PhoneRow_f2"))
71-
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PasswordRow_f1"))
72119
#endif
73120
}
74121
}

0 commit comments

Comments
 (0)