How to access properties from a plugin in a Kotlin DSL gradle script?

Viewed 873

I have a kts gradle buildscript in which this plugin is used.

The plugin sets the project.version property to a string and adds some additional properties:

While the version property is a string, it does expose some additional properties. These are snapshot, major, minor, patch and preRelease.

Now, how can I access these properties from build.gradle.kts?

Trying things like val major = project.version.major as Integer always fail since Kotlin is statically typed:

Unresolved reference: major

Is there any way to access these properties or do I have to go back to a groovy based gradle.build buildscript?

1 Answers

Interesting question. The plugin is using Groovy metaprogramming to add these properties (major, minor, patch...) to the version property.
As far as I know, Kotlin cannot access the MetaClass properties of Groovy.
The plugin should rather use a normal class structure for the version property or (wanting to keep version a String object) add a dedicated property to the project that contains these values as properties of a new class. But the current implementation seems to be incompatible with Gradle Kotlin DSL.

This is the code section where they set project.version and add properties to its MetaClass (Source code):

project.version = semanticBuildVersion as String

// Attach snapshot boolean-property to version - says whether version is snapshot or not
project.version.metaClass.snapshot = semanticBuildVersion.snapshot

// Attach version components
def versionComponents = project.version.split(/[.-]/, 4)
project.version.metaClass.major = versionComponents[VersionComponent.MAJOR.index] as int
project.version.metaClass.minor = versionComponents[VersionComponent.MINOR.index] as int
project.version.metaClass.patch = versionComponents[VersionComponent.PATCH.index] as int

The official Groovy documentation actually documents that runtime metaprogramming is not visible for other JVM languages, whereas compile-time metaprogramming would be visible (link):

Compile-time metaprogramming in Groovy allows code generation at compile-time. Those transformations are altering the Abstract Syntax Tree (AST) of a program, which is why in Groovy we call it AST transformations. AST transformations allow you to hook into the compilation process, modify the AST and continue the compilation process to generate regular bytecode. Compared to runtime metaprogramming, this has the advantage of making the changes visible in the class file itself (that is to say, in the bytecode). Making it visible in the bytecode is important for example if you want the transformations to be part of the class contract (implementing interfaces, extending abstract classes, …​) or even if you need your class to be callable from Java (or other JVM languages). For example, an AST transformation can add methods to a class. If you do it with runtime metaprogramming, the new method would only be visible from Groovy. If you do the same using compile-time metaprogramming, the method would be visible from Java too. Last but not least, performance would likely be better with compile-time metaprogramming (because no initialization phase is required).

Related