Annotation Processing in Kotlin Multiplatform can be done with kapt
when one has a jvm target.
But how does one process annotations if there is no jvm target?
Specifically I want to generate code when processing annotations from commonMain
. But I can't figure out how to process those.
My annotation processor just logs at the moment:
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("ch.hippmann.annotation.Register")
@SupportedOptions(RegisterAnnotationProcessor.KAPT_KOTLIN_GENERATED_OPTION_NAME)
class RegisterAnnotationProcessor : AbstractProcessor(){
companion object {
const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
}
override fun process(annotations: MutableSet<out TypeElement>?, roundEnv: RoundEnvironment?): Boolean {
processingEnv.messager.printMessage(Diagnostic.Kind.WARNING, "Processing")
return true
}
}
The annotation is in a separate multiplatform module and resides in commonMain
:
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Register
And is used in a project in commonMain
:
part of build.gradle
:
kotlin {
jvm()
// For ARM, should be changed to iosArm32 or iosArm64
// For Linux, should be changed to e.g. linuxX64
// For MacOS, should be changed to e.g. macosX64
// For Windows, should be changed to e.g. mingwX64
linuxX64("linux")
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation project(":annotations")
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
jvmMain {
dependencies {
implementation kotlin('stdlib-jdk8')
}
}
jvmTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
linuxMain {
}
linuxTest {
}
}
}
dependencies {
kapt project(":annotationProcessor")
}
This works as log as there is the jvm()
target present. But if i remove it, i can't use kapt
.
So how to process the annotations when there is no jvm
target?
Kotlin multiplatform projects use compilations for producing artifacts. Each target can have one or more compilations, for example, for production and test purposes. main and test compilations for JVM, JS, and Native targets.
If you need to specify a class as an argument of an annotation, use a Kotlin class ( KClass ). The Kotlin compiler will automatically convert it to a Java class, so that the Java code can access the annotations and arguments normally. Copied! Annotations can also be used on lambdas.
let the multiplatform-annotations inherit from the multiplatform-annotations isn't possible since kotlin doesn't yet support annotation inheritance. Should I refrain from using the data-class feature and use inheritance or is there a more elegant way?
When investing why that choice was made, the answer became evident : there is no mocking system on Kotlin/Multiplatform, and Mockk only supports JVM & Android. The JVM reflection is an amazing powerful API, allowing libraries to instrument existing classes and create new implementations at run time. When you write :
You seem to have solved your issue, but if anyone ends up here...
I could use kapt on common code without any issues, like this:
val commonMain by getting {
dependencies {
...
configurations.get("kapt").dependencies.add(project(": annotationProcessor"))
}
}
It processes annotation on commonMain
code without a problem. I do have an android target, though, so if the issue only surfaced when there was no jvm target at all, then ymmv. There are also annotation processors working for Kotlin Native e.g. https://github.com/Foso/MpApt.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With