stevesaliman / gradle-properties-plugin

Gradle plugin to simplify loading project properties from external environment specific files
Apache License 2.0
192 stars 28 forks source link

Provide a Kotlin DSL for the task methods. #40

Open dtbullock opened 3 years ago

dtbullock commented 3 years ago

To invoke the groovy methods installed as extension properties of Task objects by applying gradle-properties-plugin from the Gradle Kotlin DSL using the 'check required properties as the first line of the task ' idiom, it is necessary to first install some Kotlin extension methods:

// These can be pasted into a build.gradle.kts ... though if provided *by the plugin* the getClosure() function could be private.

/* private */ fun getClosure(task: Task, closureName: String): groovy.lang.Closure<Any> {
    return (task.extensions["ext"] as ExtraPropertiesExtension).get(closureName) as (groovy.lang.Closure<Any>)
}

fun Task.requiredProperty(propertyName: String) {
    getClosure(this, "requiredProperty")(propertyName)
}

fun Task.requiredProperties(propertyNames: Array<String>) {
    getClosure(this, "requiredProperties")(propertyNames)
}

fun Task.recommendedProperty(propertyName: String, defaultFile: String) {
    getClosure(this, "recommendedProperty")(propertyName, defaultFile)
}

fun Task.recommendedProperties(propertyNames: Array<String>, defaultFile: String) {
    getClosure(this, "recommendedProperties")(mapOf(
        "names" to propertyNames,
        "defaultFile" to defaultFile
    ))
}

val Project.filterTokens : Map<String,String>
    get() = (ext["filterTokens"] as Map<String, String>)

It is then possible to use the suggested 'property check' idiom from scripted tasks:

val templateDir = File("${projectDir}/property-templates/")
val resourceDir = File("${projectDir}/src/main/resources/")

tasks.register<Copy>("prep") {

    requiredProperty("singleRequired")
    requiredProperties(arrayOf("foo", "bar"))
    recommendedProperty("singleRecomm", "fileA")
    recommendedProperties(arrayOf("applicationLogDir", "b"), "fileB")

    outputs.file(File(resourceDir, "log4j.properties"))

    from(templateDir)
    include("log4j.properties")
    into(resourceDir)
    filter(ReplaceTokens::class, "tokens" to project.filterTokens)

}

Notwithstanding the major design change (?) to be provoked by the configuration cache in future versions of Gradle, it'd be sweet if gradle-properties-plugin could distribute these extensions!

Vampire commented 2 years ago

Maybe better varargs than explicit Arrays

Vampire commented 2 years ago

It might even be better to not use ext properties at all which are in most cases just work-arounds instead of doing it properly. Instead it would probably be more appropriate to add an extension to the tasks. Unfortunately there will not be accessors generated for the Kotlin DSL, but as it will be available on all tasks, it would probably be ok to provide the accessors with the plugin. For Groovy DSL it would simply work. And it would then be for example


tasks.register("foo") {
    propertyRules {
        require("foo")
        recommend("bar", "baz")
    }
}