Groovy编写的Gradle插件在Kotlin DSL中配置PluginExtension的方法
Gradle插件Kotlin DSL配置方案
问题场景
我有一个用Groovy编写的Gradle插件,通过PluginExtension接收配置输入,其Groovy实现代码如下:
class PluginExtension implements GroovyInterceptable { private final Project project private Map<String, ?> staticTokens private Map<String, DynamicToken> dynamicTokens private Map<String, Closure> derivedTokens private final Closure<Object> propertyGetter PluginExtension(Project project) { this.project = project propertyGetter = findDeploymentProperty.curry(project) } void setStaticTokens(Map<String, ?> staticTokens) { this.staticTokens = staticTokens } void setDynamicTokens(Map<String, ?> dynamicTokens) { this.dynamicTokens = dynamicTokens .collectEntries { k, v -> [(k): [refId: { v.refId }, defaultValue: { v.defaultValue }, transform: { v.transform ?: { it } }]] } .collectEntries { k, v -> [(k): v as DynamicToken] } as Map<String, DynamicToken> } }
在Groovy的build.gradle中,我是这样配置插件的:
deployPreparation { staticTokens = [ appName : project.name, version : project.version, gradleVersion: project.gradle.gradleVersion ] dynamicTokens = [ deployName : [refId: "deploy.name", defaultValue: project.name.toLowerCase().replaceAll("[-]", ""), transform: { it.length() > 20 ? it.substring(0, 20) : it }], jvmAllowedMemory : [refId: "jvm.allowed.memory", defaultValue: "1024m"], jvmActiveProcessors : [refId: "jvm.active.processors", defaultValue: "2"], ] derivedTokens = [ cloudServerGroup: { "${deployName}-${cloudEnvironment}".toString() }, ] }
尝试转成Kotlin DSL(build.gradle.kts)时,我写了以下代码:
configure<com.company.search.deploy.prepare.plugin.PluginExtension> { staticTokens=mapOf( "appName" to project.name, "version" to project.version, "gradleVersion" to project.gradle.gradleVersion ) as Map<String,Any> }
但遇到报错:
Cannot access 'staticTokens': it is private in 'PluginExtension'
解决方法
1. 调用Setter方法而非直接访问属性
Groovy允许通过staticTokens = xxx的语法自动调用setStaticTokens方法,但Kotlin DSL不会自动做这个映射,需要显式调用Setter方法:
configure<com.company.search.deploy.prepare.plugin.PluginExtension> { setStaticTokens(mapOf( "appName" to project.name, "version" to project.version, "gradleVersion" to project.gradle.gradleVersion )) }
2. 完整的Kotlin DSL配置示例
针对dynamicTokens和derivedTokens,需要注意Groovy闭包与Kotlin Lambda的转换,以及DynamicToken的构造适配:
import groovy.lang.Closure configure<com.company.search.deploy.prepare.plugin.PluginExtension> { // 配置staticTokens setStaticTokens(mapOf( "appName" to project.name, "version" to project.version, "gradleVersion" to project.gradle.gradleVersion )) // 配置dynamicTokens setDynamicTokens(mapOf( "deployName" to mapOf( "refId" to "deploy.name", "defaultValue" to project.name.lowercase().replace("-", ""), "transform" to Closure<Any>(null, null) { it: String -> if (it.length > 20) it.substring(0, 20) else it } ), "jvmAllowedMemory" to mapOf( "refId" to "jvm.allowed.memory", "defaultValue" to "1024m" ), "jvmActiveProcessors" to mapOf( "refId" to "jvm.active.processors", "defaultValue" to "2" ) )) // 配置derivedTokens(需要将Kotlin Lambda转为Groovy Closure) setDerivedTokens(mapOf( "cloudServerGroup" to Closure<String>(null, null) { "${getProperty("deployName")}-${getProperty("cloudEnvironment")}" } )) }
关键说明
- Kotlin DSL不会像Groovy那样自动将属性赋值映射到Setter方法,必须显式调用
setStaticTokens、setDynamicTokens这类方法 - 对于需要Groovy Closure的地方,要手动将Kotlin Lambda包装为
groovy.lang.Closure实例 derivedTokens中的闭包需要通过getProperty来访问Extension中的其他属性,因为Kotlin无法直接像Groovy那样隐式访问
内容的提问来源于stack exchange,提问作者codeYogico
相关产品推荐
相关产品推荐

