A documentação da API Gradle Project
afirma que é possível adicionar um método dinâmico a um projeto
Uma propriedade do projeto cujo valor é um encerramento. O encerramento é tratado como um método e chamado com os parâmetros fornecidos. A propriedade está localizada conforme descrito acima.
Acho que "descrito acima" significa que é possível usar propriedades dinâmicas do projeto. Eles são descritos na documentação da API como
Um projeto possui 5 'escopos' de propriedades, nos quais ele procura propriedades. Você pode acessar essas propriedades pelo nome em seu arquivo de construção ou chamando o método property(String) do projeto. Os escopos são:
...
- As propriedades extras do projeto. Cada projeto mantém um mapa de propriedades extras, que pode conter qualquer par arbitrário de nome -> valor. Uma vez definidas, as propriedades deste escopo são legíveis e graváveis. Veja propriedades extras para mais detalhes.
Então pensei que poderia escrever um plugin de convenção, por exemplo, "sayHello.gradle.kts"
// sayhello.gradle.kts
val sayHello : (String) -> Unit = { who ->
println("Hello $who")
}
ext.set("sayHello", sayHello)
e então use a função (ou lambda) que adicionei ao projeto em outrobuild.gradle.kts
// Some projects build.gradle.kts
plugins {
id("sayHello")
}
sayHello("René")
Mas estou conseguindo
Script compilation errors:
Line 7: sayHello("")
^ Expression 'sayHello' cannot be invoked as a function. The function 'invoke()' is not found
Line 7: sayHello("")
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public val TaskContainer.sayHello: TaskProvider<DefaultTask> defined in org.gradle.kotlin.dsl
Achei que estava errado com o DSL Kotlin e li a seção Propriedades Extras , mas isso mostra apenas como os valores são registrados e não os fechamentos.
Porém tentei registrar um fechamento semelhante aos valores do exemplo. Então eu fiz:
val sayHelloFun : (String) -> Unit = { who ->
println("Hello $who")
}
val sayHello by extra(sayHelloFun)
Eu recebi a mesma mensagem de erro.
Alguém sabe como adicionar uma função personalizada a um Project
plugin de convenção usando Kotlin DSL?
O acesso dinâmico à propriedade não está disponível no Kotlin DSL
Infelizmente, não é possível adicionar funções ao
Project
objeto dessa forma a partir de um plug-in de script pré-compilado no Kotlin DSL. A seção da documentação que fala sobre os "cinco escopos do projeto" antecipa que o usuário está escrevendo um script de construção Groovy e não é estritamente preciso para Kotlin: tal acesso depende de recursos dinâmicos da linguagem Groovy.Para provar isso, veja a documentação sobre como usar propriedades extras . Se você comparar os exemplos Kotlin e Groovy, verá que todas as propriedades extras do Kotlin devem ser acessadas usando o nome da string da propriedade como chave, por exemplo, escrevendo
extra["myProperty"]
, enquanto o Groovy pode acessá-las diretamente.Alternativas
Como o Kotlin é digitado estaticamente, precisamos de um método real que o compilador Kotlin possa ver. Sugiro duas alternativas para fazer isso: extensões Gradle e funções de extensão Kotlin.
Extensões Gradle
Quando você cria uma extensão , o Gradle cria um acessador para essa extensão. Você pode usar isso para criar uma função em projetos que aplicam seu plugin, exceto que você precisa chamá-lo na extensão em vez de
Project
diretamente:Funções de extensão Kotlin
Essa abordagem apenas explora um recurso regular da linguagem Kotlin . Tais funções devem ser definidas no código que está no classpath do buildscript, portanto, isso não funcionaria em um plugin de script pré-compilado (conforme sua pergunta).
No entanto, esse código poderia ser escrito, por exemplo, em um arquivo Kotlin normal na
buildSrc
pasta 1 . Então você poderia simplesmente fazer:1 Esse código também poderia ser escrito dentro da compilação de um plugin definido por classe.