-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Identify and promote first-class support for mapping between extension and task properties #726
Comments
I'm hoping you mean "won't promote it yet"? Just want to make sure software model is still the direction. |
Apologies, I'm 100% sure this isn't the appropriate place to ask this, but it's an open question for us too - was @ajoberstar's question answered anywhere? The radical differences between the JVM domain and the software model are a cause of near-constant complexity for someone using Gradle for native, so it would be good to know which way Gradle is going. |
I added a spec for this work. Feedback welcome! @ajoberstar This work won't touch the software model. Convention mapping has been treated almost like a public API by plugin developers in the past years. I have done it, I am sure you have done it. There's a good reason for it: there were simply no better options. With the software model you can effectively avoid the evaluation order issue (addressed by convention mapping) by defining model rules. |
@bmuschko That makes sense to me, and I like the focus on getting some issues to round out the public APIs. My original question was more of an aside, and I don't know that it's quite been answered. Since this came up recently on the forum too, maybe that's a better place to continue if you don't mind taking a look. |
@ajoberstar Thanks for raising the discussion. It's a valid concern for any plugin developer. Let's continue the discussion in the forum. |
I think there are a few options for making the 'provider' approach more convenient. We can make some progress towards a more managed model and remove a bunch of boilerplate by allowing Gradle to manage the state for a property and to provide getter and setter implementations. For example:
Gradle can provide implementations for these methods. The current decoration that mixes in convention mapping basically already does this. For backwards compatibility, the generated methods would still be convention mapping aware. So you can still do No task types are currently We might get rid of the need for an additional setter that accepts
The point here is to avoid mixing a bunch of different concerns into the model (the task type). For nested data structures, we should provide some kind of 'create a decorated instance of this type' feature. One option would be to add a public API for Another, not mutually exclusive option, would be for Gradle to automatically create instances of things that it knows how to create: collection types, |
Digging a little further into the cases where The first option might look something like this:
Gradle would override the getter and setter, as it does now, but would also manage the state of the property instead of delegating to the getter and setter. However, this would be broken:
The second option might look something like this:
There'd be some integration with the convention mapping infrastructure for backwards compatibility. We know which state object or field is associated with which property in both cases. |
Nested objects might work something like this:
A task might also want to hide the implementation type of a nested object:
|
Something to note is that these capabilities would not be specific to |
For unit testing these types, I think
|
Thanks for your feedback, @adammurdoch. Based on the feedback I got from other team members and you it seems like we feel comfortable with moving forward with the provider approach. Do you agree? Your comments above focus on the convenience aspect of the implementation. I am wondering if we could just release the provider implementation in multiple phases. Phase 1 would not provide the aspect of convenience. I am proposing the approach for two reasons:
In practice I do not see people mixing convention mapping and provider approach in their plugins. I'd expect external plugins to fully switch over to the new approach and release a new version. The interoperability aspect is probably more useful for internal plugins which will migrate to the provider approach over time. You also mentioned making the |
Yeah, I agree. We could (and should) certainly do this in stages. I'm not seeing generated getters and setters as magic. It's pretty explicit that someone else has to provide the implementation. In this regard it's quite a bit better than convention mapping. At this stage generated getters and setters are an important part of the performance strategy, as they allow us to cache state, reset state and make things immutable or parallel safe. Probably also part of the software model migration story as well. This pattern is intended to become pervasive in all domain object types.
This would instead be important for people that reuse tasks types from other plugins, or who add or override mappings for tasks created by other plugins. Interop with convention mapping means that the plugin author can switch styles without affecting downstream users. And downstream users can switch styles without being blocked on the plugin author releasing a new version. |
PR: #1452 |
This enables users to retrieve and add dependencies, configure inputs, and other user-supplied details at configuration time. We need the user supplied configuration to be applied lazily after they configure it, which means we cannot do it at plugin `apply` time. We can also use `Callable`/`Closure` in the `inputs.property` method, but that will only work for properties but not for methods. Another way of accomplishing lazy properties is by using `conventionMapping`, but that also has pitfalls (see https://github.com/gradle/gradle/blob/master/design-docs/internal-apis-made-public.md). This means we don't have an effective way of lazily configuring the `args` or the `systemProperty` of the task. The easiest way forward is to simply create the task at configuration time and then apply the rest of the configuration in the `afterEvaluate` method to avoid using internal `conventionMapping`. closes junit-team#708 See related Gradle issue for making lazy properties at gradle/gradle#726
* Update to latest Gradle build scan plugin and change Travis CI option to first class `--scan` option * Upgrade to Checkstyle 7.6 * Introduce Gradle functional tests for validating `'java'` and `'java-library'` plugins work - Generate classpath manifest for the testkit test compile classpath. This is useful so that the locally built versions of the other projects are used during functional testing. - Test against both the `'java'` and `'java-library'` plugins * Add functional test for validating `UP-TO-DATE` behavior when test is executed multiple times with no changes * Make Spock tests more standardized by using `given` * Switch task creation to use `TaskContainer` and repetitive configuration * Create `junitPlatformTest` task during configuration phase See related Gradle issue for making lazy properties at gradle/gradle#726 Closes #708
This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. If you're interested in how we try to keep the backlog in a healthy state, please read our blog post on how we refine our backlog. If you feel this is something you could contribute, please have a look at our Contributor Guide. Thank you for your contribution. |
This issue has been automatically closed due to inactivity. If you can reproduce this on a recent version of Gradle or if you have a good use case for this feature, please feel free to reopen the issue with steps to reproduce, a quick explanation of your use case or a high-quality pull request. |
Plugin developers are currently using the internal API for convention mapping to map extension values to task properties. Convention mapping is the only effective method to avoid evaluation order issues for this use case.
We need to identify a first-class, public API solution for the problem. The software model was supposed to solve the issue. As we won't promote the software model for the JVM domain, we'll need a different solution. Part of this ticket is to identify an appropriate solution. This could be convention mapping but doesn't have to.
If we go with convention mapping then we should make the API public. We should also tweak the contract to make the value immutable when the task starts executing.
The text was updated successfully, but these errors were encountered: