Hi :slightly_smiling_face: I'm fairly new to creat...
# gradle
r
Hi 🙂 I'm fairly new to creating gradle plugins and i having some issues with the extension I want to create for my plugin. The extension should be used like this:
Copy code
versionControl {
    group {
        groupName = "com.example.something"
        exclude {
            moduleName = "ui"
            moduleVersion = "1.0.0"
        }
        exclude {
            moduleName = "domain"
            moduleVersion = "1.0.0"
        }
    }
    group {
        groupName = "com.example.somethingElse"
        exclude {
            moduleName = "foundation"
            moduleVersion = "1.0.0"
        }
    }
}
If I do
moduleName = "something"
I get this error:
Caused by: groovy.lang.MissingPropertyException: Could not set unknown property 'moduleName' for object of type com.example.versioncontrolplugin.DependencyGroup.
But If I instead do this
it.moduleName = "something"
it seems to work. How can I avoid the need for using
it.
? Code added in the comment :)
VersionControlExtension code:
Copy code
open class VersionControlExtension(
    private val objectFactory: ObjectFactory
) {

    var groups: ListProperty<DependencyGroup> = objectFactory.listProperty(DependencyGroup::class.java).convention(emptyList())

    fun group(action: Action<in DependencyGroup>) {
        val group = DependencyGroup(objectFactory)
        action.execute(group)
        groups.add(group)
    }
}
DependencyGroup:
Copy code
open class DependencyGroup(
    private val objectFactory: ObjectFactory
) {
    var groupName: Property<String> = objectFactory.property(String::class.java)

    var moduleExclusions: ListProperty<ModuleExclusion> = objectFactory.listProperty(ModuleExclusion::class.java).convention(emptyList())

    fun exclude(action: Action<in ModuleExclusion>): ModuleExclusion {
        val moduleExclusion = ModuleExclusion(objectFactory)
        action.execute(moduleExclusion)
        moduleExclusions.add(moduleExclusion)
        return moduleExclusion
    }

    fun setGroupName(groupName: String) {
        this.groupName.set(groupName)
    }
}
ModuleExclusion:
Copy code
open class ModuleExclusion(
    objects: ObjectFactory
) {
    var moduleName: Property<String> = objects.property(String::class.java)
    var moduleVersion: Property<String> = objects.property(String::class.java)
    var isVersionIncluded: Property<Boolean> = objects.property(Boolean::class.java).convention(true)

    fun setModuleName(value: String) { moduleName.set(value) }
    fun setModuleVersion(value: String) { moduleVersion.set(value) }
    fun setIsVersionIncluded(value: Boolean) { isVersionIncluded.set(value) }
}
e
is the user a
.gradle.kts
or a
.kt
file? if it's a
.kt
file, is it in a project that applies `plugins {
kotlin-dsl
}`?
☝️ 1
r
The user is a regular
.gradle
in an Android project and no usage of
kotlin-dsl
.
v
Not sure if it changes things, generally, you should remove the setters, they should not be necessary, and make the classes and properties abstract (or use an interface right away) and make the properties val not var. The latter is anyway important as those must not be changed and what the assign plugin for Kotlin DSL would not work otherwise.
r
Let's say I make
ModuleExclusion
an interface, how should I then do the
fun exclude(action: Action<in ModuleExclusion>)
that should add the ModuleExclusion to the ListProperty?
v
Ah yeah, either Just make
ModuleExclusion
an interface and keep
DependencyGroup
as class, but abstract with abstract
val
properties, then you at least save some of the boilerplate. Alternatively, I think it should also work to add
ModuleExclusion
as extension to
DependencyGroup
. Each thing you instantiate through Gradle is automatically decorated to be
ExtensionAware
, so you can just cast it. Or you can also - that's what I do with all my Gradle-constructed types - explicitly declare them to implement
ExtensionAware
, Gradle will care for the implementation anyway.
r
Alternatively, I think it should also work to add ModuleExclusion as extension to DependencyGroup
how do I do this?
v
Ah, wait no, in your situation, that will probably not work as it is a property of a domain object as part of a list property. So you can probably just make the
ModuleExclusion
an interface, but all the rest holds.
r
I found this guide that helped me get what I wanted 🙂 Thanks for helping! https://dev.to/autonomousapps/gradle-plugins-and-extensions-a-primer-for-the-bemused-51lp
e
that article has some inaccuracies
yes gradle uses asm but it doesn't rewrite your Action<*> receivers. that's a standard Kotlin compiler plugin https://kotlinlang.org/docs/sam-with-receiver-plugin.html changing how a client can use them, no ABI or bytecode changed.
👍 1