Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@FormBuilder #2242

Merged
merged 11 commits into from
Oct 4, 2023
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,24 @@ form +++ {
}
```

#### @FormBuilder
```swift
@FormBuilder
var form: Form {
nil as Section?
mlorenze marked this conversation as resolved.
Show resolved Hide resolved
Section("Section A") { section in
section.tag = "Section_A"
}
if true {
Section("Section B") { section in
section.tag = "Section_B"
}
}
nil as TextRow?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mats-claassen
Fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, so my question is why do we need to put a nil there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about if something { nil } ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why would you want to add a nil row or section? It is not clear to me what this would produce nor why would you use it like that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mats-claassen
Exactly. So, should we remove it from the examples?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or you can add your suggestions to my branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mats-claassen
Can you please tell me what else should I fix in this pull request?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @RomanPodymov I think if you remove the if something { nil} from the examples then this is fine to be merged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mats-claassen
Done.

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
73 changes: 61 additions & 12 deletions Tests/ResultBuildersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,89 @@ class ResultBuildersTests: BaseEurekaTests {
}
DecimalRow("DecimalRow_f1") { $0.title = "Decimal" }
}

@FormBuilder
var form: Form {
nil as Section?
Section("Section A") { section in
section.tag = "Section_A"
}
if true {
Section("Section B") { section in
section.tag = "Section_B"
}
}
nil as TextRow?
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
}
}