/Companionate

Kotlin Compiler Plugin for library authors

Primary LanguageKotlin

Companionate

Companionate is a compiler plugin that allows you to add a companion object to classes and interfaces that are annotated with an arbitrary annotation that you can specify in the build configuration. This way you can also use existing third-party annotations that you don't own.

It ignores annotated singletons since they cannot contain a companion object.

Tests

To tell the Companionate plugin which annotations to look for in your tests, you can declare them using the COMPANIONATE_ANNOTATIONS directive in your test file.

package com.example

// COMPANIONATE_ANNOTATIONS: com.example.Companionate
annotation class Companionate

@Companionate
interface Sample

If you're getting ClassNotFoundException for com/intellij/openapi/util/SystemInfo you likely use the compiler embeddable as dependency org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.20. Use the org.jetbrains.kotlin:kotlin-compiler:1.9.20 instead or include the intellij OpenAPI dependency which contains the missing class.

// https://mvnrepository.com/artifact/com.intellij/openapi
testImplementation("com.intellij:openapi:7.0.3")

IntelliJ Environments

Since the Kotlin Compiler still is coupled with IntelliJ dependencies, you need to make sure to set some important environment variables. One of them is idea.home. If this variable is not set, you will encounter errors like: java.lang.RuntimeException: Could not find installation home path. Please make sure bin/idea.properties is present in the installation directory.

The kotlin test framework (not the internal compiler test framework) already includes a setup function in TestSetupUtils.kt.

package org.jetbrains.kotlin.test

/**
 * For proper initialization of idea services those two properties should
 *   be set in environment of test. You can setup them manually via build
 *   system of run configurations or just `initIdeaConfiguration` before
 *   running tests using abilities of core test framework you use
 */
fun initIdeaConfiguration() {
    System.setProperty("idea.home", computeHomeDirectory())
    System.setProperty("idea.ignore.disabled.plugins", "true")
}

private fun computeHomeDirectory(): String {
    val userDir = System.getProperty("user.dir")
    return File(userDir ?: ".").canonicalPath
}

You need to build your own test runner and call the setup before executes the tests.

A great starting point for plugin development is the Compiler Plugin Template.