Skip to content

Commit

Permalink
Merge pull request #2242 from RomanPodymov/feature/result_builders
Browse files Browse the repository at this point in the history
  • Loading branch information
mlorenze committed Oct 4, 2023
2 parents 9ead011 + 299fe75 commit a77db05
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 14 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,22 @@ form +++ {
}
```

#### @FormBuilder
```swift
@FormBuilder
var form: Form {
Section("Section A") { section in
section.tag = "Section_A"
}
if true {
Section("Section B") { section in
section.tag = "Section_B"
}
}
NameRow("NameRow_f1") { $0.title = "Name" }
}
```

### Using the callbacks

Eureka includes callbacks to change the appearance and behavior of a row.
Expand Down
47 changes: 45 additions & 2 deletions Source/Core/ResultBuilders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ extension Array: RowsProvider where Element == BaseRow {
public var rows: [BaseRow] { self }
}

public protocol SectionsProvider {
var sections: [Section] { get }
}

extension Section: SectionsProvider {
public var sections: [Section] { [self] }
}

extension Array: SectionsProvider where Element == Section {
public var sections: [Section] { self }
}

extension BaseRow: SectionsProvider {
public var sections: [Section] { [.init([self])] }
}

@resultBuilder
public struct SectionBuilder {
public static func buildBlock(_ components: RowsProvider...) -> [BaseRow] {
Expand All @@ -57,8 +73,35 @@ public struct SectionBuilder {
components?.flatMap { $0.rows } ?? []
}

public static func buildExpression(_ expression: BaseRow?) -> [BaseRow] {
expression.flatMap { [$0] } ?? []
public static func buildExpression(_ expression: RowsProvider?) -> [BaseRow] {
expression.flatMap { $0.rows } ?? []
}
}

@resultBuilder
public struct FormBuilder {
public static func buildBlock(_ components: SectionsProvider...) -> [Section] {
components.flatMap { $0.sections }
}

public static func buildFinalResult(_ components: [Section]) -> Form {
.init(components)
}

public static func buildEither(first components: [SectionsProvider]) -> [Section] {
components.flatMap { $0.sections }
}

public static func buildEither(second components: [SectionsProvider]) -> [Section] {
components.flatMap { $0.sections }
}

public static func buildOptional(_ components: [SectionsProvider]?) -> [Section] {
components?.flatMap { $0.sections } ?? []
}

public static func buildExpression(_ expression: SectionsProvider?) -> [Section] {
expression.flatMap { $0.sections } ?? []
}
}
#endif
71 changes: 59 additions & 12 deletions Tests/ResultBuildersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,87 @@ class ResultBuildersTests: BaseEurekaTests {
}
DecimalRow("DecimalRow_f1") { $0.title = "Decimal" }
}

@FormBuilder
var form: Form {
Section("Section A") { section in
section.tag = "Section_A"
}
if true {
Section("Section B") { section in
section.tag = "Section_B"
}
}
NameRow("NameRow_f1") { $0.title = "Name" }
}
#endif

private var checkBuildEither = false
private var checkBuildExpressionBaseRowOptional = false

func testSectionBuilder() {
#if swift(>=5.4)
var checkBuildEither = false
setupManySectionsForm()
addMoreItemsToManySectionsForm()

XCTAssertNotNil(manySectionsForm.rowBy(tag: "NameRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "IntRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "DecimalRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "UrlRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "TwitterRow_f1"))
XCTAssertNil(manySectionsForm.rowBy(tag: "TwitterRow_f2"))
XCTAssertNil(manySectionsForm.rowBy(tag: "EmailRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "AccountRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PhoneRow_f1"))
XCTAssertNil(manySectionsForm.rowBy(tag: "PhoneRow_f2"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "ZipCodeRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PasswordRow_f1"))
#endif
}

private func setupManySectionsForm() {
checkBuildEither = false
checkBuildExpressionBaseRowOptional = true
manySectionsForm = (section1 +++ {
URLRow("UrlRow_f1") { $0.title = "Url" }
if checkBuildEither {
TwitterRow("TwitterRow_f2") { $0.title = "Twitter" }
} else {
TwitterRow("TwitterRow_f1") { $0.title = "Twitter" }
}
if checkBuildExpressionBaseRowOptional {
nil
} else {
EmailRow("EmailRow_f1") { $0.title = "Email" }
}
AccountRow("AccountRow_f1") { $0.title = "Account" }
})
checkBuildEither = true
}

private func addMoreItemsToManySectionsForm() {
checkBuildEither.toggle()
checkBuildExpressionBaseRowOptional.toggle()
manySectionsForm +++ {
if checkBuildEither {
PhoneRow("PhoneRow_f1") { $0.title = "Phone" }
} else {
PhoneRow("PhoneRow_f2") { $0.title = "Phone" }
}
if checkBuildExpressionBaseRowOptional {
nil
} else {
ZipCodeRow("ZipCodeRow_f1") { $0.title = "Zip Code" }
}
PasswordRow("PasswordRow_f1") { $0.title = "Password" }
}

}

func testFormBuilder() {
#if swift(>=5.4)
manySectionsForm = form
XCTAssertNotNil(manySectionsForm.sectionBy(tag: "Section_A"))
XCTAssertNotNil(manySectionsForm.sectionBy(tag: "Section_B"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "NameRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "IntRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "DecimalRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "UrlRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "TwitterRow_f1"))
XCTAssertNil(manySectionsForm.rowBy(tag: "TwitterRow_f2"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "AccountRow_f1"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PhoneRow_f1"))
XCTAssertNil(manySectionsForm.rowBy(tag: "PhoneRow_f2"))
XCTAssertNotNil(manySectionsForm.rowBy(tag: "PasswordRow_f1"))
#endif
}
}

0 comments on commit a77db05

Please sign in to comment.