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

Support nested enum reducer (#2813) #2814

Merged
merged 8 commits into from Apr 29, 2024

Conversation

sk409
Copy link
Contributor

@sk409 sk409 commented Feb 16, 2024

This adds support for nested enum reducers.
#2813 for more information.

@stephencelis
Copy link
Member

@sk409 Thanks for the discussion and motivation. I think we're down to support this, but maybe in a way that doesn't introduce a new macro like @ReducerCaseStatic.

Instead, what if we used Feature.Body to denote a static reducer?

-@ReducerCaseStatic
-case sheet(Sheet)
+case sheet(Sheet.Body)

That would match explicit use in the reducer:

.ifLet(\.$sheet, action: \.sheet) {
  Sheet.body
}

What do you think?

@sk409
Copy link
Contributor Author

sk409 commented Feb 27, 2024

@stephencelis

Instead, what if we used Feature.Body to denote a static reducer?

I agree with the policy of not introducing new macros if possible.
I tried using Body in the example below, but Body was Never because the ReducerBuilder's _Sequence defines reduce.
This results in an error like the attached screenshot.

extension FeatureA {
    @Reducer(state: .equatable)
    enum Destination {
        case modal(Modal.Body)
    }
}

extension FeatureA {
    @Reducer(state: .equatable)
    enum Modal {
        case featureB(FeatureB)
        case featureC(FeatureC)
        case featureD(FeatureD)
    }
}

スクリーンショット 2024-02-27 15 35 16

@stephencelis
Copy link
Member

@sk409 Sorry if I wasn't clear, or maybe I'm misunderstanding you, but my suggestion was for the macro to see Modal.Body and then use that .Body to insert different code in the body, like:

 ComposableArchitecture.Scope(
   state: \Self.State.Cases.modal, action: \Self.Action.Cases.modal
 ) {
-  Modal()
+  Modal.body
 }

Are you interested in making those changes to this PR?

@sk409
Copy link
Contributor Author

sk409 commented Feb 29, 2024

@stephencelis

my suggestion was for the macro to see Modal.Body and then use that .Body to insert different code in the body, like:

Thank you for confirmation.
I think it's simple and clear because .Body and .body correspond.
I have implemented it, so please check if there are any discrepancies in recognition.
481bfc7
The body of the nested enum reducer has a detailed type and I needed to erase the type, so I implemented it as follows.

 ComposableArchitecture.Scope(
   state: \Self.State.Cases.modal, action: \Self.Action.Cases.modal
 ) {
  ComposableArchitecture.Reduce(Modal.body.reduce)
 }

@stephencelis
Copy link
Member

@sk409 Sorry for the extra back and forth, but it's taken us awhile to process the problem and potential solutions. We think we have an idea that minimizes magic and also enhances the reducer macro for even more general cases. Instead of detecting .Body and performing some magic, what if we used the optional "initializer" of the case as the scoped default? For example:

case sheet(Sheet.Body = Sheet.body)  // No magic, just use `Sheet.body` in the scope

This also would allow folks to customize struct reducers that take some static configuration, which is currently impossible:

case child(Child = Child(context: .sheet))

Thoughts? Are you up for making this final change? We promise no more back-and-forth 😄

If you don't have the time, though, we can also attempt to tackle soon.

@sk409
Copy link
Contributor Author

sk409 commented Mar 4, 2024

@stephencelis

what if we used the optional "initializer" of the case as the scoped default? For example:

I think it's good because it can be used in various cases.
I implemented it.
I added the following test after implementation, but a compilation error occurred because Sheet.Body was Never.

private enum TestEnumReducer_Nested {
  @Reducer
  struct Feature {}
  @Reducer
  enum Destination {
    // Compilation error occurs because Sheet.Body is Never.
    case sheet(Sheet.Body = Sheet.body)
  }
  
  @Reducer
  enum Sheet {
    case feature(Feature)
  }
}

It seems that there will be no compilation error if I change Sheet.Body to Sheet._Body, but why does Sheet.Body become Never?

private enum TestEnumReducer_Nested {
  ....
  @Reducer
  enum Destination {
    // No compilation error occurs because Sheet._Body is not Never.
    case sheet(Sheet._Body = Sheet.body)
  }
  ...
}

@stephencelis
Copy link
Member

@sk409 That's a bummer :( This looks like it might be a macro bug/issue. We'll chat about it and investigate a bit further.

Copy link
Member

@stephencelis stephencelis left a comment

Choose a reason for hiding this comment

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

This appears to be working with the changes from #3023, so will merge when #3023 is merged, thanks for making all the changes!

@stephencelis stephencelis merged commit 30334f9 into pointfreeco:main Apr 29, 2024
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request Apr 30, 2024
…ure to from: "1.10.1" (#1054)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
|
[pointfreeco/swift-composable-architecture](https://togithub.com/pointfreeco/swift-composable-architecture)
| patch | `from: "1.10.0"` -> `from: "1.10.1"` |

---

### Release Notes

<details>
<summary>pointfreeco/swift-composable-architecture
(pointfreeco/swift-composable-architecture)</summary>

###
[`v1.10.1`](https://togithub.com/pointfreeco/swift-composable-architecture/releases/tag/1.10.1)

[Compare
Source](https://togithub.com/pointfreeco/swift-composable-architecture/compare/1.10.0...1.10.1)

#### What's Changed

- Fixed: Support nested enum reducers (thanks
[@&#8203;sk409](https://togithub.com/sk409),
[pointfreeco/swift-composable-architecture#2814).
- Fixed: Add missing `NSPrivacyCollectedDataTypes` to
PrivacyInfo.xcprivacy (thanks
[@&#8203;DandyLyons](https://togithub.com/DandyLyons),
[pointfreeco/swift-composable-architecture#3027).
- Fixed: Emit test failure when warning in release
([pointfreeco/swift-composable-architecture#3024).
- Fixed: Bump Perception availability to support 1.1.6
([pointfreeco/swift-composable-architecture#3025).
- Infrastructure: Update README for TCA 1.10.0 (thanks
[@&#8203;kalupas226](https://togithub.com/kalupas226),
[pointfreeco/swift-composable-architecture#3019).
- Infrastructure: Fix DocC organization of shared state tools
([pointfreeco/swift-composable-architecture#3022).
- Infrastructure: Remove `Reducer._Body` workaround
([pointfreeco/swift-composable-architecture#3023).

#### New Contributors

- [@&#8203;sk409](https://togithub.com/sk409) made their first
contribution in
[pointfreeco/swift-composable-architecture#2814

**Full Changelog**:
pointfreeco/swift-composable-architecture@1.10.0...1.10.1

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDkuNCIsInVwZGF0ZWRJblZlciI6IjM2LjEwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants