-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[AssistedInject] Validate that parameters names match between factory method and the constructor #2281
Comments
Thanks! that's a good point. Originally, we decided not to rely on parameter names because the .class files don't include parameter names by default. However, I think you're right that we should validate the parameter names to avoid subtle issues like you describe above. This change may require adding I'll start working on a fix for this. |
square AssistedInject actually reverted the requirement on parameter name matching, and Jake Wharton posted this comment regarding it: cashapp/InflationInject#157 (comment) |
Good catch, I wasn't aware of that one as it seems like it never went live 😕 Although the behavior since the last public square/AssistedInject release changes, so it still might be a surprising migration for some. Do you know why incap means parameter names sometimes aren't present? Would that be the case for when factory and the injected types are in separate files, or there's some more common scenario? edit: Gradle docs suggest the
|
I am strongly opposed to parameter name matching, as was said. Once you start using base interfaces for factories and incremental compilation it will break. Our (square's) AssistedInject is simply broken in current form and that change needs released. Using qualifiers, like regular Dagger matching, is a logical and conceptually easy concept. You'll hear the typical calls of "boilerplate" at least once, but correctness trumps the slight added verbosity in this case which isn't even all that common. |
This all makes sense. I'm not familiar with the technical limitations, but if qualifiers are really the only way, then validation should be adjusted to fail if there are unqualified parameters of the same type. My primary motivation for this issue was to require more effort to create wrong bindings, if qualifiers are the only technically appropriate way to fix this then 🤷 |
Hm, I'm currently still leaning towards just keeping the current behavior of relying on the parameter order for disambiguation. The issue with using qualifiers is that I think it can cause confusion because from someone using the factory, the qualifier does nothing. Someone might look at a factory that has a method While relying on parameter order isn't my favorite thing either, since adding a new parameter to the |
Qualifier annotations may be present on component builder and factory methods which are exposed to user values in the same way, right? I mean assisted injection itself is basically just a scope-less component factory that directly returns an instance rather than a component. Additionally, when there isn't a conflict for graph types you are still able to use a qualifier. The need to use qualifiers to disambiguate assisted types should be rare. We are designing an edge case here, but doing things like parameter matching and placing significance on order have implications to every assisted inject usage rather than just the disambiguation situation. Nowhere else in Dagger do parameter names matter. Nowhere else in Dagger does position matter. Everywhere else in Dagger the qualifier concept used for disambiguation. There's a high cognitive load to learning Dagger and to using Dagger day-to-day. My argument is for self-consistency so that the mechanisms you use for other parts of Dagger apply the same way here rather than having to learn and remember a different set of rules. |
I think those cases are okay though because they actually create bindings. Assisted injection is different from a scope-less component factory because the assisted values aren't bindings. You can't, for example, move an I think we disagree because before assisted injection, the statements "qualifiers are used for all disambiguation" and "qualifiers are only used for bindings" could be consistent and so it is easy to come up with different mental models of what a qualifier should be. I'm probably influenced by Guice where How about this? If we created an (We can fiddle with how this looks exactly. One option is to put the string on |
|
For the record, Guice attaches the disambiguation name to the |
Thanks for the all of the input, it sounds like we have a plan =) |
So you are going to support qualifiers in assisted injection, right? |
@IlyaGulya, we plan to support adding a |
Aren't qualifiers more natural for Dagger than some custom parameter for |
@IlyaGulya I have some thoughts on why we don't want to support qualifiers in my comments above. |
And if it wasn't clear, I am supportive of this solution. Since we'll likely do another Square AssistedInject release I am considering dropping the qualifier annotation support which was re-added and instead switching to this approach. |
With the following code:
Dagger will ignore the fact that
foo
andbar
parameters order is different in thecreate
method and the constructor. The generated factory will then pass arguments fromcreate
to the constructor in unexpected (or expected, but clearly not intentional) order. So:will print
This is error prone and difficult to prevent using automated tools. It would be great if Dagger verified the parameters names as well, requiring them to match between the factory method and the constructor.
Also as far as I understand,
square/AssistedInject
doesn't verify the parameters order, but forces matching names (if there were more than one parameter with the same type). This can lead to some confusing migration errors, as now the behavior is the opposite.The text was updated successfully, but these errors were encountered: