Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Files generated through KSP not showing #129

Open
gfreivasc opened this issue Mar 17, 2021 · 6 comments
Open

Files generated through KSP not showing #129

gfreivasc opened this issue Mar 17, 2021 · 6 comments

Comments

@gfreivasc
Copy link

gfreivasc commented Mar 17, 2021

I'm having a problem with compiler testing. For some reason, it does not detect KSP generated files. They have been successfully generated and it's possible to browse to them through the file system, but they're not reported on the compilation result. It looks like it's looking for kapt generated stuff instead.

Here's how I'm running it:

compile(folder: File, vararg sourceFiles: SourceFile): KotlinCompilation.Result {
  val processors = provider.provide()
  val kspProcessors = processors.filterIsInstance<SymbolProcessor>()
  val kaptProcessors = processors.filterIsInstance<BasicAnnotationProcessor>()
  return KotlinCompilation()
    .apply {
      workingDir = folder
      inheritClassPath = true
      if (kspProcessors.isNotEmpty()) {
        symbolProcessors = kspProcessors
      } else if (kaptProcessors.isNotEmpty()) {
        annotationProcessors = kaptProcessors.asProcessorList
      }
      sources = sourceFiles.asList()
      verbose = false
      kspIncremental = true
    }.compile()
}
// ... during test
val result = compile(
  temporaryFolder.root,  // The jUnit rule for temporary folders
  SourceFile.kotlin(
    "source.kt",
    """
        package test
   
        import com.gabrielfv.crane.annotations.RoutedBy
        
        class R
        
  	@RoutedBy(R::class)
  	class A
    """
  )
)

The variable result won't contain no generated sources, all the properties generatedFiles, generatedStubFiles, sourcesGeneratedByAnnotationProcessor and compiledClassAndResourceFiles return empty for my KSP round. Everything works just fine for my KAPT rounds.

@tschuchortdev
Copy link
Owner

I am able to reproduce your issue. Strictly speaking it's "working as intended". Unfortunately, the current implementation of KotlinCompilation is quite limited in its extensibility and KSP, being implemented as a third-party extension instead of being integrated like KAPT, can not add its generated files to the Result class. Let me think of a way to gather all the new files in the working directory and I will add it as a new method to the Result class.

@gfreivasc
Copy link
Author

I see, so not a bug but rather that it's not designed to fully support KSP at least just yet. Other than this kind of behavior, what else do you think would be necessary to extend KSP support, and do you intend to do it in the sorter term?

gfreivasc added a commit to gfreivasc/crane that referenced this issue Mar 22, 2021
Creates extensions that run the necessary lookup for KSP generated
sources in order to enable tests to match outputs.

Currently this is not a functionality supported by kotlin compile
testing, but should eventually be.

See: tschuchortdev/kotlin-compile-testing#129
@gfreivasc
Copy link
Author

gfreivasc commented Mar 22, 2021

I've been able to apply the following workaround:

internal val KotlinCompilation.Result.workingDir: File get() =
  outputDirectory.parentFile!!

val KotlinCompilation.Result.kspGeneratedSources: List<File> get() {
  val kspWorkingDir = workingDir.resolve("ksp")
  val kspGeneratedDir = kspWorkingDir.resolve("sources")
  val kotlinGeneratedDir = kspGeneratedDir.resolve("kotlin")
  val javaGeneratedDir = kspGeneratedDir.resolve("java")
  return kotlinGeneratedDir.listFilesRecursively() +
    javaGeneratedDir.listFilesRecursively()
}

This allows me to test for what I want without problems. Perhaps a similar strategy could be adopted for the KSP extensions? I could open a PR if you'd believe it to be applicable.

Here's how I'm testing this:

assertThat(result.exitCode)
  .isEqualTo(KotlinCompilation.ExitCode.OK)
val generated = if (backend == "ksp") {
  assertThat(result.kspGeneratedSources)
    .isNotEmpty
  result.kspGeneratedSources
} else {
  assertThat(result.sourcesGeneratedByAnnotationProcessor)
    .isNotEmpty
  result.sourcesGeneratedByAnnotationProcessor
}

@ghost
Copy link

ghost commented Nov 2, 2021

@gfreivasc Can you explain, where the listFilesRecursively comes from?

I could not elaborate this, so I use walkTopDown extension method method from kotlin.io instead:

val KotlinCompilation.Result.kspGeneratedSources: List<File> get() {
  val kspWorkingDir = workingDir.resolve("ksp")
  val kspGeneratedDir = kspWorkingDir.resolve("sources")
  val kotlinGeneratedDir = kspGeneratedDir.resolve("kotlin")
  val javaGeneratedDir = kspGeneratedDir.resolve("java")
  return kotlinGeneratedDir.walkTopDown().toList() +
    javaGeneratedDir.walkTopDown()
}

@gfreivasc
Copy link
Author

@chausknecht I created this method, or got it from somewhere Idk it's been a while. I didn't include it in this excerpt for shortness sake but you can see it in this PR

@ghost
Copy link

ghost commented Jan 7, 2022

@gfreivasc Thx for answering :-) After looking at the handcrafted method, I tend to prefer the walkTopDown approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants