ZacSweers/kotlin-compile-testing

How to use KSP?

Closed this issue · 2 comments

Been spending a lot of time trying to figure out how to make compilation use KSP.
Tried adding kspWithCompilation, calling different combinations of useKsp2 and configureKsp.
I think i'm just stumbling around in the dark.

A guide would be very helpful.

So this test works as expected with kotlin-compile-testing-ksp:1.6.0

import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.tschuchort.compiletesting.KotlinCompilation
import com.tschuchort.compiletesting.symbolProcessorProviders
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.Assert
import kotlin.test.Test

class Tests {
    @Test
    @OptIn(ExperimentalCompilerApi::class)
    fun isMySymbolProcessorProviderCalled() {
        val provider = MySymbolProcessorProvider()
        val compilation = KotlinCompilation().apply {
            symbolProcessorProviders = listOf(provider)
        }
        compilation.compile()
        Assert.assertTrue(provider.called)
    }
}

class MySymbolProcessorProvider : SymbolProcessorProvider {
    var called = false

    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        called = true
        return MySymbolProcessor()
    }
}

class MySymbolProcessor : SymbolProcessor {
    override fun process(resolver: Resolver): List<KSAnnotated> {
        return emptyList()
    }
}
plugins {
    kotlin("jvm") version "1.9.25"
    `maven-publish`
}

repositories {
    mavenCentral()
}

sourceSets.test {
    kotlin.srcDir("test")
}

dependencies {
    implementation("com.google.devtools.ksp:symbol-processing-api:1.9.25-1.0.20")
    implementation("com.github.tschuchortdev:kotlin-compile-testing-ksp:1.6.0")
    implementation("org.jetbrains.kotlin:kotlin-test:1.9.25")
}

Changing dependencies to the below and now it seems like no matter what i do the test will never pass.

plugins {
    kotlin("jvm") version "2.0.21"
    `maven-publish`
}

repositories {
    mavenCentral()
}

sourceSets.test {
    kotlin.srcDir("test")
}

dependencies {
    implementation("com.google.devtools.ksp:symbol-processing-api:2.0.21-1.0.25")
    implementation("dev.zacsweers.kctfork:ksp:0.5.1")
    implementation("org.jetbrains.kotlin:kotlin-test:2.0.21")
}

Looking at their tests: the issue is that you have done none of the following:

  1. set the language version to <2.0
    class Tests {
        @Test
        @OptIn(ExperimentalCompilerApi::class)
        fun isMySymbolProcessorProviderCalled() {
            val compilation = KotlinCompilation().apply {
                languageVersion = "1.9" // this can really just be anything that is less than 2.0
                configureKsp {
                    symbolProcessorProviders += MySymbolProcessorProvider()
                }
            }
            compilation.compile()
            Assert.assertTrue(provider.called)
        }
    }
  2. enabled ksp2:
    class Tests {
        @Test
        @OptIn(ExperimentalCompilerApi::class)
        fun isMySymbolProcessorProviderCalled() {
            val compilation = KotlinCompilation().apply {
                configureKsp(useKsp2 = true) {
                    symbolProcessorProviders += MySymbolProcessorProvider()
                }
            }
            compilation.compile()
            Assert.assertTrue(provider.called)
        }
    }

Yeah, second part works with Kotlin 2.0.21 from what i can see, the code passes now.

You forgot to make the provider variable in your sample so i fixed it and here is the new code:

@Test
@OptIn(ExperimentalCompilerApi::class)
fun isMySymbolProcessorProviderCalled() {
    val provider = MySymbolProcessorProvider()
    val compilation = KotlinCompilation().apply {
        configureKsp(useKsp2 = true) {
            symbolProcessorProviders += provider
        }
    }
    compilation.compile()
    Assert.assertTrue(provider.called)
}

So the important change here is the line symbolProcessorProviders += provider inside configureKsp(useKsp2 = true) {
because that is different from referencing symbolProcessorProviders directly inside KotlinCompilation().apply

I will close this as it has been solved, but do consider adding something like this to the readme.