kotlin-compile-testing icon indicating copy to clipboard operation
kotlin-compile-testing copied to clipboard

Unable to load classes generated by a KSP symbol processor

Open ansman opened this issue 3 years ago • 11 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.

ansman avatar Sep 08 '22 19:09 ansman

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

ansman avatar Sep 09 '22 19:09 ansman

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?

Tiagoperes avatar Oct 28 '22 18:10 Tiagoperes

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

bishiboosh avatar Oct 28 '22 18:10 bishiboosh

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

Tiagoperes avatar Oct 28 '22 19:10 Tiagoperes

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

Tiagoperes avatar Oct 31 '22 18:10 Tiagoperes

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

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

bennyhuo avatar Nov 03 '22 23:11 bennyhuo

@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

bishiboosh avatar Nov 04 '22 08:11 bishiboosh

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

ansman avatar Nov 04 '22 14:11 ansman

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?

ansman avatar Nov 04 '22 14:11 ansman

/** 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

bennyhuo avatar Nov 05 '22 00:11 bennyhuo

kspWithCompilation

This also worked for me! Thanks!

Tiagoperes avatar Nov 08 '22 20:11 Tiagoperes