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

add initial autoListenable macro for fields #36

Merged
merged 3 commits into from Aug 9, 2021
Merged

add initial autoListenable macro for fields #36

merged 3 commits into from Aug 9, 2021

Conversation

jakemac53
Copy link
Owner

@jakemac53 jakemac53 commented Aug 5, 2021

Towards #23

cc @goderbauer can you do a review here? Much of this is actually checked in generated code - you can ignore all the main.*.dart files except main.gen.dart which is the hand written one.

I want to follow up with exploring use cases for listenable objects that come from the build context next.

This also has some extra cleanup in the fromParts apis - I realized it doesn't make sense for them to auto-concat nested lists of code with a ,. Instead you can supply a separator if you wish, otherwise pieces of code are just concatenated directly.

I also did remove the usage of autoDispose from the example - right now the prototype implementation doesn't support mixing these two macros together well, I filed a couple of related issues on that.

@goderbauer
Copy link
Collaborator

cc @goderbauer can you do a review here?

Will take a look today!

Copy link
Collaborator

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

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

LGTM

From a usability perspective I do find it a little strange that the annotation has to go on the state object, though (see comment in review)

flutter_example/lib/main.gen.dart Outdated Show resolved Hide resolved
widget.counter.value++;
}

void _handleCounter() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method is matched to widget.counter just by name? Wondering if that relationship can be made more explicit (i.e. less magic)?

Copy link
Owner Author

Choose a reason for hiding this comment

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

It could be made explicit via an annotation on the original field (a bit weird), or maybe an annotation on this method?

It is a bit magic for sure but the macro does try to keep you on the rails (it checks for the method, and that it matches the expected signature). I think this type of convention over configuration approach is actually highly desirable for a lot of people, but we could allow other more explicit options.


final String title;

@override
State<MyHomePage> createState() => _MyHomePageState();
}

@autoListenable
Copy link
Collaborator

Choose a reason for hiding this comment

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

The placement of the annotation on the state object feels a little disconnected from the pieces that are more relevant to this (the actual Listenable or the listenable handler).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess you could interpret this as "Hey, this state object listens to all Listenables it can find in the associated widget."

My guess is that most people (well, at least me) will be thinking the other way around: Either "here's a Listenable I want to listen to" or "here's a handler that I want to invoke when the listenable fires". Those two seem like more natural entry points / annotation points.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ya, given the widget/state separate this seemed the most intuitive to me (and least boilerplate). We can make other examples too that work a bit differently - and I do want to extend this one to also work for things from the state class (that are pulled off the context, etc). That will end up looking more like what you are talking about I think.

flutter_example/lib/main.dart Outdated Show resolved Hide resolved
} else {
// https://github.com/jakemac53/macro_prototype/issues/34
throw ArgumentError(
'@autoListenable isn\'t compatible with a custom `initState` '
Copy link
Collaborator

Choose a reason for hiding this comment

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

That's a bummer 😄

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ya, just something specific to this prototype though. If I have the time I will try and make it work better here haha but this is all just throwaway stuff so I don't think its critical I get all these cases worked out.

flutter_example/lib/macros/auto_listenable.dart Outdated Show resolved Hide resolved
@jakemac53 jakemac53 merged commit a27dcd6 into main Aug 9, 2021
@jakemac53 jakemac53 deleted the listenable branch August 9, 2021 19:54
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

3 participants