Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Multiplatform Annotation Processing

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?

like image 908
Cedric Hippmann Avatar asked Jan 17 '20 09:01

Cedric Hippmann


People also ask

What are compilations in Kotlin?

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.

How do I use annotations in Kotlin with Java?

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.

Can I inherit from the multiplatform-annotations in Kotlin?

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?

Why mockk for Kotlin/multiplatform?

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 :


1 Answers

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.

like image 85
Michał Klimczak Avatar answered Oct 17 '22 20:10

Michał Klimczak