tschuchortdev / kotlin-compile-testing

A library for testing Kotlin and Java annotation processors, compiler plugins and code generation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unable to load classes generated by a KSP symbol processor

ansman opened this issue · comments

Here is an example that I use:

val source = kotlin("source.kt", """
    @se.ansman.kotshi.KotshiJsonAdapterFactory
    object Factory : com.squareup.moshi.JsonAdapter.Factory by KotshiFactory
""".trimIndent()
)
val compilation = KotlinCompilation().apply {
  workingDir = temporaryFolder.root
  sources = listOf(source)
  inheritClassPath = true
  messageOutputStream = System.out // see diagnostics in real time
  kspIncremental = true
  symbolProcessorProviders = listOf(KotshiSymbolProcessorProvider())
}
assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK)
val factory = result.classLoader.loadClass("KotshiFactory")
assertThat(factory).isAssignableTo(JsonAdapter.Factory::class.java)

This works fine when using the KAPT version of the processor and I have manually confirmed that the source is indeed generated.

This is likely related to all KSP generated files being missing from Result.generatedFiles

This is also happening to me, the file is correctly generated, but the class itself doesn't get loaded into the classpath. Have you find any solution for this @ansman?

What I'm doing right now is doing a second compilation run without processors but including the generated files, but that's only a workaround

This is what I just thought of doing. I'll try this and see if it works. Thanks!

Compiling the code twice works. Hope we can remove this workaround soon. Thanks for the help!

val compilation = KotlinCompilation().apply {
  ...
  // add this 
  kspWithCompilation = true
}

Ksp won't generate byte code by default. Try enable the compilation with kspWithCompilation option.

@bennyhuo kspWithCompilation does the trick for me, I was able to remove the second round of compilation. Maybe add to the documentation regarding this point ? Otherwise is @ansman is ok I think this issue could be closed

I can still not load classes after using kspWithCompilation = true.

Even with this flag set the class loader till only contains the classes dir.
image

Ah, it turns it it's likely because I'm generating java sources and not kotlin sources. Perhaps this isn't something that KSP/Compile Testing supports?

/** Performs the 4th compilation step to compile Java source files */
private fun compileJava(sourceFiles: List<File>): ExitCode {
  val javaSources = (sourceFiles + kaptSourceDir.listFilesRecursively())
			  .filterNot<File>(File::hasKotlinFileExtension)

  if(javaSources.isEmpty())
    return ExitCode.OK
  ...
}

Yes, only java sources from sources property and kapt are compiled by Javac.

It is still the best choice to compile again after KSP compilation. And I also did this in my extensions library with module support here kotlin-compile-testing-extensions/KotlinModule

kspWithCompilation

This also worked for me! Thanks!