I’m creating a plugin (using the new rule-based syntax) which adds a new ModelMap container. I can get it to work, but there’s one thing I don’t understand. I’d like to declare a custom extension of ModelMap to streamline my code, but it doesn’t seem to work when used as an input to a Mutate rule.
Here is a simple example that demonstrates the problem:
This code gives the confusing error “Foo is not a subtype of Foo”. If I explicitly use ModelMap<Foo> instead of FooContainer throughout my code, it works fine. Am I missing something, or is this a bug? I’m using Gradle 2.10.
This may very well be an issue with Gradle 2.10 (or perhaps not yet implemented). Your example however does work when in the master branch so you might try using the latest nightly.
BTW, you’ll want to use ModelMap<Task> instead of TaskContainer. I believe targeting TaskContainer as an input/subject to a rule is likely to be deprecated/removed.
Thanks Mark, it does work with the latest nightly! But if you’re doing away with TaskContainer, I may be going the wrong direction; was mainly doing this to parallel the Container interfaces in the existing Gradle code.
To take it a step further though, it looks like I cannot add additional managed properties to FooContainer. I was hoping to have some top-level config that applies to all items in the map, so I tried:
This now gives the error “Method FooContainer_Impl.setBar(Z)V is abstract”. I’m guessing this one may be by design, and ModelMap may be exclusively designed to contain children (with no properties of its own).
TaskContainer is treated a bit special. You’ll notice it is a “legacy” collection and doesn’t implement ModelMap. We have special bridging logic to handle it.
The managed collection types cannot be extended in that way. The “Container” types are really mostly there for additional type safety and documentation purposes. For this you could either create a new top-level model element with these properties or just use the model DSL to configure all items in the collection.
Yep, this is pretty much what I ended up doing (creating a top-level element with base config and a “contents” sub-element containing the map). Thanks for all the details!