I would like to improve my current ReplaceVersionPlugin (buildSrc/src/main/kotlin/versioning.gradle.kts
)
By default the plugin should replace all occurrences of @VERSION@
with project.version
in my Java code.
It works, but has 1 big problem:
It injects itself as source (setSource
) for every JavaCompile
task, even if the task has already another input set. I’ve verified this behaviour by copying the ReplaceVersionPlugin
to ReplaceVersionPlugin2
and applying it. The id(...)
order becomes important and one of them will be ignored.
My questions are:
- How would this be implemented correctly.
- Is there an easier way to replace tokens in java code.
open class ReplaceVersionExtension @Inject constructor(
project: Project
) {
val tokens: MapProperty<String, String> = project.objects.mapProperty(String::class.java, String::class.java)
.convention(project.provider { mutableMapOf("VERSION" to "${project.version}") })
}
val replaceVersion = extensions.create<ReplaceVersionExtension>("replaceVersion")
val replaceVersionInSource by tasks.registering(Sync::class) {
from(project.the<SourceSetContainer>()[SourceSet.MAIN_SOURCE_SET_NAME].java)
inputs.property("tokens", replaceVersion.tokens)
// DeferredReplaceTokens has been added as separate code block below
filter<DeferredReplaceTokens>("tokens" to replaceVersion.tokens)
into(layout.buildDirectory.dir("src"))
}
// ======= THIS SHOULD PROBABLY BE MODIFIED =======
tasks.withType<JavaCompile>().configureEach {
setSource(replaceVersionInSource.get().outputs)
}
My code is based on
and
which led to:
class DeferredReplaceTokens(`in`: Reader) : FilterReader(`in`) {
private var actualReader: FilterReader? = null
var tokens: MapProperty<String, String>? = null
private fun reader(): FilterReader {
actualReader = actualReader ?: ReplaceTokens(this.`in`).also { replaceTokens ->
val tokens = this.tokens
if (tokens == null) {
println("No tokens set. tokens is null")
} else {
tokens.keySet().get()
.map { key -> key to tokens.getting(key).get() }
.onEach { println("Token: ${it.first} : ${it.second}") }
.map { (key, value) -> ReplaceTokens.Token().also { it.key = key; it.value = value } }
.forEach(replaceTokens::addConfiguredToken)
}
}
return actualReader!!
}
override fun read(cbuf: CharArray, off: Int, len: Int): Int = reader().read(cbuf, off, len)
override fun read(): Int = reader().read()
override fun close() = reader().close()
}