All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tschuchort.compiletesting.Ksp2.kt Maven / Gradle / Ivy

There is a newer version: 0.7.0
Show newest version
/* Adds support for KSP (https://goo.gle/ksp). */
package com.tschuchort.compiletesting

import com.google.devtools.ksp.impl.KotlinSymbolProcessing
import com.google.devtools.ksp.processing.KSPJvmConfig
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import java.io.File
import java.io.PrintStream
import java.util.EnumSet
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi

@ExperimentalCompilerApi
class Ksp2PrecursorTool : PrecursorTool, KspTool {
  override var withCompilation: Boolean
    get() = false
    set(value) {
      // Irrelevant/unavailable on KSP 2
    }

  override val symbolProcessorProviders: MutableList = mutableListOf()
  override val processorOptions: MutableMap = mutableMapOf()
  override var incremental: Boolean = false
  override var incrementalLog: Boolean = false
  override var allWarningsAsErrors: Boolean = false
  override var loggingLevels: Set =
    EnumSet.allOf(CompilerMessageSeverity::class.java)

  // Extra hook for direct configuration of KspJvmConfig.Builder, for advanced use cases
  var onBuilder: (KSPJvmConfig.Builder.() -> Unit)? = null

  override fun execute(
    compilation: KotlinCompilation,
    output: PrintStream,
    sources: List,
  ): KotlinCompilation.ExitCode {
    if (symbolProcessorProviders.isEmpty()) {
      return KotlinCompilation.ExitCode.OK
    }

    val config =
      KSPJvmConfig.Builder()
        .apply {
          projectBaseDir = compilation.kspWorkingDir.absoluteFile

          incremental = [email protected]
          incrementalLog = [email protected]
          allWarningsAsErrors = [email protected]
          processorOptions = [email protected]()

          jvmTarget = compilation.jvmTarget
          jdkHome = compilation.jdkHome
          languageVersion = compilation.languageVersion ?: "2.0"
          apiVersion = compilation.apiVersion ?: "2.0"

          // TODO adopt new roots model
          moduleName = compilation.moduleName ?: "main"
          sourceRoots = sources.filter { it.extension == "kt" }.mapNotNull { it.parentFile.absoluteFile }.distinct()
          javaSourceRoots = sources.filter { it.extension == "java" }.mapNotNull { it.parentFile.absoluteFile }.distinct()
          @Suppress("invisible_member", "invisible_reference")
          libraries = compilation.classpaths + compilation.commonClasspaths()

          cachesDir =
            compilation.kspCachesDir.also {
              it.deleteRecursively()
              it.mkdirs()
            }.absoluteFile
          outputBaseDir =
            compilation.kspSourcesDir.also {
              it.deleteRecursively()
              it.mkdirs()
            }.absoluteFile
          classOutputDir =
            compilation.kspClassesDir.also {
              it.deleteRecursively()
              it.mkdirs()
            }.absoluteFile
          javaOutputDir =
            compilation.kspJavaSourceDir.also {
              it.deleteRecursively()
              it.mkdirs()
              compilation.registerGeneratedSourcesDir(it)
            }.absoluteFile
          kotlinOutputDir =
            compilation.kspKotlinSourceDir.also {
              it.deleteRecursively()
              it.mkdirs()
              compilation.registerGeneratedSourcesDir(it)
            }.absoluteFile
          resourceOutputDir =
            compilation.kspResources.also {
              it.deleteRecursively()
              it.mkdirs()
            }.absoluteFile

          onBuilder?.invoke(this)
        }
        .build()

    // Temporary until friend-paths is fully supported https://youtrack.jetbrains.com/issue/KT-34102
    @Suppress("invisible_member", "invisible_reference")
    val messageCollector = compilation.createMessageCollectorAccess("ksp")
    val logger =
      TestKSPLogger(
        messageCollector = messageCollector,
        allWarningsAsErrors = config.allWarningsAsErrors,
      )

    return try {
      when (KotlinSymbolProcessing(config, symbolProcessorProviders.toList(), logger).execute()) {
        KotlinSymbolProcessing.ExitCode.OK -> KotlinCompilation.ExitCode.OK
        KotlinSymbolProcessing.ExitCode.PROCESSING_ERROR ->
          KotlinCompilation.ExitCode.COMPILATION_ERROR
      }
    } finally {
      logger.reportAll()
    }
  }
}

/** Enables KSP2. */
@OptIn(ExperimentalCompilerApi::class)
fun KotlinCompilation.useKsp2() {
  precursorTools.getOrPut("ksp2", ::Ksp2PrecursorTool)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy