-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Macro bonanza #2553
Macro bonanza #2553
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi there! 👋
I've just taken a look at the macro implementation and have left a few inline comments. While I hope these observations will be helpful, please feel free to disregard any that you don't find useful. I understand that different perspectives can lead to varying approaches!
Great use case of Swift Macro! I love it!
Sending much love,
Mateusz 🫶
let method = $0.decl.as(FunctionDeclSyntax.self), | ||
method.name.text == "reduce", | ||
method.signature.parameterClause.parameters.count == 2, | ||
let state = method.signature.parameterClause.parameters.first, | ||
state.firstName.text == "into", | ||
state.type.as(AttributedTypeSyntax.self)?.specifier?.text == "inout", | ||
method.signature.parameterClause.parameters.last?.firstName.text == "action", | ||
method.signature.effectSpecifiers == nil, | ||
method.signature.returnClause?.type.as(IdentifierTypeSyntax.self) != nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using a large conditional, why not simply compare the FunctionDeclSyntax.description
string with the expected description of the reduce method? I suppose one could add additional trivia to the function, like this:
func reduce(into state: inout State, action: Action) -> Effect<Action>
However, I believe we would still be able to handle that. We are comparing only the argument names, not their types, but am I right in thinking it's safe to assume they will be State
and Action
, respectively?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question remains how to handle access modifiers. The best solution would be to ensure that it is the same as the type declaration, but I'm not sure if this will be possible. Maybe it can be implemented based on the body
property access modifier? If the two are the same then emit a warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I'm thinking about an edge case where someone might have code like this:
var body: some Reducer<State, Action> {
// somewhere here private reduce is called
}
private func reduce(into state: inout State, action: Action) -> Action {
// ...
}
In this scenario, wouldn't the private reduce
method, be detected instead of the one intended from the protocol?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the current might be more complex, I'm comfortable with the checks, and I think it's checking just what needs to be checked and nothing more. Folks can technically define a reduce
that matches the protocol conformance but uses a custom type for State
or Action
(since those are just associated types), and one could also define custom secondary names. An extreme example:
func reduce(
into myState: MyState,
action myAction: MyAction<Something>
) -> EffectOf<MyFeature>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this scenario, wouldn't the private
reduce
method, be detected instead of the one intended from the protocol?
That's not valid Swift, so the compiler would complain at the conformance level:
🛑 Method 'reduce(into:action:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'Reducer'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this scenario, wouldn't the private
reduce
method, be detected instead of the one intended from the protocol?That's not valid Swift, so the compiler would complain at the conformance level:
🛑 Method 'reduce(into:action:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'Reducer'
OK, I think I understand what happened here. In theory, the following code should indeed result in an error, but... it seems that, thanks to the implementation of the Reduce
protocol being handled by a macro, the code works just fine 🤯
@Reducer
struct MyTest {
struct State {}
enum Action {
case none
}
var body: some Reducer<State, Action> { Reduce { _, _ in .none } }
private func reduce(into state: inout State, action: Action) -> Effect<Action> {
.none
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the current might be more complex, I'm comfortable with the checks, and I think it's checking just what needs to be checked and nothing more. Folks can technically define a
reduce
that matches the protocol conformance but uses a custom type forState
orAction
(since those are just associated types), and one could also define custom secondary names. An extreme example:func reduce( into myState: MyState, action myAction: MyAction<Something> ) -> EffectOf<MyFeature>
Sorry, I'm a bit confused now. So, is your intention that every method like this should produce an error, right? Even ones with different types, like this example:
@Reducer
struct MyTest {
struct State {}
enum Action {
case none
}
enum LocalAction {
case some
}
var body: some Reducer<State, Action> { Reduce { _, _ in .none } }
private func reduce(into state: inout State, action: LocalAction) -> Effect<Action> {
.none
}
}
Is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Matejkob I think there's only so much we can do from the macro to detect that a method matches the conformance. Someone could type alias the Effect
return type so we can't do any checking there, and while we could traverse the reducer to see if there are State
or Action
types/aliases and use that to silence the warning for your above example, I'm not sure it's worth the extra work when at the end of the day, defining a method named reduce
is confusing enough that we think a rename is warranted for folks to silence the warning. In fact, I did just add a syntax visitor that tries to fix-it a rename.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephencelis Thanks for your explanation. I understand the challenges with the macro approach and agree that a rename is a more straightforward solution. Appreciate your work on this and the helpful response!
Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com>
…ure to from: "1.4.2" (#737) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [pointfreeco/swift-composable-architecture](https://togithub.com/pointfreeco/swift-composable-architecture) | minor | `from: "1.3.0"` -> `from: "1.4.2"` | --- ### Release Notes <details> <summary>pointfreeco/swift-composable-architecture (pointfreeco/swift-composable-architecture)</summary> ### [`v1.4.2`](https://togithub.com/pointfreeco/swift-composable-architecture/releases/tag/1.4.2) [Compare Source](https://togithub.com/pointfreeco/swift-composable-architecture/compare/1.4.1...1.4.2) #### What's Changed - Fixed: `swift-case-paths` is now correctly pinned from 1.1.0, which should avoid some SPM resolution issues (thanks [@​bdolewski-intellias](https://togithub.com/bdolewski-intellias), [https://github.com/pointfreeco/swift-composable-architecture/pull/2577](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2577)). #### New Contributors - [@​bdolewski-intellias](https://togithub.com/bdolewski-intellias) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2577](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2577) **Full Changelog**: pointfreeco/swift-composable-architecture@1.4.1...1.4.2 ### [`v1.4.1`](https://togithub.com/pointfreeco/swift-composable-architecture/releases/tag/1.4.1) [Compare Source](https://togithub.com/pointfreeco/swift-composable-architecture/compare/1.4.0...1.4.1) #### What's Changed - Fixed: A regression in `Reducer.forEach` was introduced in 1.4 that broke compilation in some cases, notably in the TCACoordinators library. This regression has been corrected (thanks [@​rhysm94](https://togithub.com/rhysm94), [https://github.com/pointfreeco/swift-composable-architecture/pull/2570](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2570)). - Infrastructure: Updated Japanese and Korean README translations (thanks [@​Achoo-kr](https://togithub.com/Achoo-kr), [https://github.com/pointfreeco/swift-composable-architecture/pull/2563](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2563), [https://github.com/pointfreeco/swift-composable-architecture/pull/2562](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2562)). - Infrastructure: Fixed documentation links (thanks [@​johankool](https://togithub.com/johankool), [https://github.com/pointfreeco/swift-composable-architecture/pull/2566](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2566), [https://github.com/pointfreeco/swift-composable-architecture/pull/2576](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2576)); fixed migration guide typos (thanks [@​kalupas226](https://togithub.com/kalupas226), [https://github.com/pointfreeco/swift-composable-architecture/pull/2569](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2569); [@​woxtu](https://togithub.com/woxtu), [https://github.com/pointfreeco/swift-composable-architecture/pull/2575](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2575); [@​Ryu0118](https://togithub.com/Ryu0118), [https://github.com/pointfreeco/swift-composable-architecture/pull/2574](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2574)). - Infrastructure: Clean up case study (thanks [@​mike123789-dev](https://togithub.com/mike123789-dev), [https://github.com/pointfreeco/swift-composable-architecture/pull/2567](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2567)). #### New Contributors - [@​Achoo-kr](https://togithub.com/Achoo-kr) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2563](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2563) - [@​mike123789-dev](https://togithub.com/mike123789-dev) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2567](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2567) - [@​woxtu](https://togithub.com/woxtu) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2575](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2575) - [@​rhysm94](https://togithub.com/rhysm94) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2570](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2570) **Full Changelog**: pointfreeco/swift-composable-architecture@1.4.0...1.4.1 ### [`v1.4.0`](https://togithub.com/pointfreeco/swift-composable-architecture/releases/tag/1.4.0) [Compare Source](https://togithub.com/pointfreeco/swift-composable-architecture/compare/1.3.0...1.4.0) #### What's Changed - Added: The `@Reducer` macro ([https://github.com/pointfreeco/swift-composable-architecture/pull/2553](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2553)). See the [migration guide](https://pointfreeco.github.io/swift-composable-architecture/main/documentation/composablearchitecture/migratingto1.4/) for more details. - Added: Reducer builder support for `any Reducer<State, Action>` ([https://github.com/pointfreeco/swift-composable-architecture/pull/2533](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2533)). - Fixed: Silenced a SwiftUI sendability warning ([https://github.com/pointfreeco/swift-composable-architecture/pull/2540](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2540)). - Fixed: Alert and confirmation dialog helpers now use `Text(verbatim: "")` to avoid localization warnings ([https://github.com/pointfreeco/swift-composable-architecture/pull/2541](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2541)). - Fixed: `Reducer.onChange` no longer requires an `Equatable` conformance (thanks [@​lukaskubanek](https://togithub.com/lukaskubanek), [https://github.com/pointfreeco/swift-composable-architecture/pull/2545](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2545)). - Infrastructure: Updated Swift compiler version to 5.7.1 to follow Apple's policy (thanks [@​jaesung-0o0](https://togithub.com/jaesung-0o0), [https://github.com/pointfreeco/swift-composable-architecture/pull/2549](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2549)). - Fixed: Short circuit equatability of ordered sets when counts don't match ([https://github.com/pointfreeco/swift-composable-architecture/pull/2556](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2556)). - Infrastructure: Added previews to integration test cases by ([https://github.com/pointfreeco/swift-composable-architecture/pull/2551](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2551)) #### New Contributors - [@​lukaskubanek](https://togithub.com/lukaskubanek) made their first contribution in [https://github.com/pointfreeco/swift-composable-architecture/pull/2545](https://togithub.com/pointfreeco/swift-composable-architecture/pull/2545) **Full Changelog**: pointfreeco/swift-composable-architecture@1.3.0...1.4.0 </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:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDAuMCIsInVwZGF0ZWRJblZlciI6IjM2LjEwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9--> Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
This branch introduces a few new tools and changes made possible by Swift 5.9 macros.
Discussion
forthcominghere: #2555