On 9 April 2014 at 5:23:35 am, Peter Niederwieser (pnied...@gmail.com) wrote: All,
as we are improving component metadata rules, we need a way for a rule to declare which metadata it is interested in. The current proposal is to do this via typed callback parameters. For example: dependencies { components { eachComponent { ComponentMetaDataDetails details, IvyModuleDescriptor descriptor -> ... } } } The rule above declares that it is interested in the generic metadata (`ComponentMetaDataDetails`) and Ivy specific metadata (`IvyModuleDescriptor`). Because it is interested in Ivy specific metadata, the rule will only fire for Ivy components. The set of potentially supported parameter types is open-ended. For example, future Gradle versions may support a `ArtifactoryProperties` parameter type. This raises some questions: * The above looks very much like a model rule. (`details` is the object to be mutated, `descriptor` is an input.) Should `eachComponent()` indeed accept a `ModelRule`, now or in the future? * If not, what should the Java API look like? * Do we want to generate the closure-based Groovy API from the Java API, now or in the future? For the time being, I've hand-coded the Groovy API, but obviously we also need a Java API. Thanks for any insights. Not sure it’s insightful, but here goes… This is slightly different to the model rules we’ve implemented to date, but not different to the types of rules we’ve discussed or conceptualised. Disclaimer: I don’t have a good understand of the component model, so I could be well off with what I’m about to say. My understand is that conceptually we are transforming things (modules?) into components, and this hook allows you to augment how that should be done. So internally, there is a model rule that knows how to create components from module descriptors (roughly). We want to supply extra configuration to the created components, based on how they were created (i.e. what type of module descriptor they were created from). So, this is a model rule where the bindings are relative to the rule the created the thing to mutate. We currently don’t have any implementation for partially (potential other names: speculatively, relatively) bound rules. Currently, the rule itself dictates how it is bound to the model. In this case, The same rule can be reused and be bound to different elements each time because the bindings are not absolute. So, this is some context specific sugar that would somehow create many absolutely bound rules (in some form) from the partially bound rule. In terms of API, the complication here is that there are constraints on the rule. It can only mutate a ComponentMetaDataDetails. Arbitrary targets don’t make sense. I can’t see an easy way to express “first argument must be <T>, but the rest are any <? extends X>”. Java’s type system isn’t up for this. We are going to have this problem generally for the model rules of course. One possibility for a general pattern would be something like… interface Components { void eachComponent(MutationRules<ComponentMetaDataDetails> rules) {} } abstract class MutationRules<T> { public final T getTarget() { // retrieve the target from some thread scoped global that we manage } } components.eachComponent(new MutationRules<ComponentMetaDataDetails>>() { // arbitrary methods in here that act as rules, with arbitrary signatures }) We could then as a common pattern, transform this kind of method to… void eachComponent(@DelegatesTo(ComponentMetaDataDetails) Closure<?> closure) So the closure delegate is the target, and all of the closure params are inputs. I’ll keep thinking on it.