Skip to content

Commit

Permalink
fix behavior for KSP error case with compilation.
Browse files Browse the repository at this point in the history
respect returnOkOnError when withCompilation is set true.
  • Loading branch information
neetopia committed Sep 7, 2022
1 parent 4f5f880 commit 5a19640
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 1 deletion.
Expand Up @@ -129,6 +129,9 @@ abstract class AbstractKotlinSymbolProcessingExtension(
if (finished) {
if (!options.withCompilation)
throw IllegalStateException("KSP is re-entered unexpectedly.")
if (!options.returnOkOnError && logger.hasError()) {
return AnalysisResult.compilationError(BindingContext.EMPTY)
}
return null
}

Expand Down
Expand Up @@ -158,7 +158,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool
options += SubpluginOption("projectBaseDir", project.project.projectDir.canonicalPath)
options += SubpluginOption("allWarningsAsErrors", allWarningsAsErrors.toString())
options += FilesSubpluginOption("apclasspath", classpath.toList())
// Turn this on by default to work KT-30172 around. It is off by default in the ccompiler plugin.
// Turn this on by default to work KT-30172 around. It is off by default in the compiler plugin.
options += SubpluginOption(
"returnOkOnError",
project.findProperty("ksp.return.ok.on.error")?.toString() ?: "true"
Expand Down
1 change: 1 addition & 0 deletions integration-tests/build.gradle.kts
Expand Up @@ -9,6 +9,7 @@ plugins {
dependencies {
testImplementation("junit:junit:$junitVersion")
testImplementation(gradleTestKit())
testImplementation("org.jetbrains.kotlin:kotlin-compiler:$kotlinBaseVersion")
}

tasks.named<Test>("test") {
Expand Down
@@ -0,0 +1,85 @@
package com.google.devtools.ksp.test

import org.gradle.testkit.runner.GradleRunner
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.net.URLClassLoader

data class CompileResult(val exitCode: ExitCode, val output: String)

class KSPCmdLineOptionsIT {
@Rule
@JvmField
val project: TemporaryTestProject = TemporaryTestProject("cmd-options")

private fun runCmdCompiler(pluginOptions: List<String>): CompileResult {
val gradleRunner = GradleRunner.create().withProjectDir(project.root)
gradleRunner.withArguments("clean", ":processors:build").build()
val processorJar = File(project.root, "processors/build/libs/processors-1.0-SNAPSHOT.jar")
val classLoader = URLClassLoader(arrayOf(processorJar.toURI().toURL()), javaClass.classLoader)
val compiler = classLoader.loadClass(K2JVMCompiler::class.java.name).newInstance() as K2JVMCompiler
val repoPath = "../build/repos/test/com/google/devtools/ksp/"
val kspPluginId = "com.google.devtools.ksp.symbol-processing"
val kspPluginJar = File("$repoPath/symbol-processing-cmdline/2.0.255-SNAPSHOT").listFiles()!!.filter {
it.name.matches(Regex(".*-\\d.jar"))
}.maxByOrNull { it.lastModified() }!!
val kspApiJar = File("$repoPath/symbol-processing-api/2.0.255-SNAPSHOT").listFiles()!!.filter {
it.name.matches(Regex(".*-\\d.jar"))
}.maxByOrNull { it.lastModified() }!!
val compilerArgs = mutableListOf(
"-no-stdlib",
"-Xplugin=${kspPluginJar.absolutePath}",
"-Xplugin=${kspApiJar.absolutePath}",
"-P", "plugin:$kspPluginId:apclasspath=${processorJar.absolutePath}",
"-P", "plugin:$kspPluginId:projectBaseDir=${project.root}/build",
"-P", "plugin:$kspPluginId:classOutputDir=${project.root}/build",
"-P", "plugin:$kspPluginId:javaOutputDir=${project.root}/build/out",
"-P", "plugin:$kspPluginId:kotlinOutputDir=${project.root}/build/out",
"-P", "plugin:$kspPluginId:resourceOutputDir=${project.root}/build/out",
"-P", "plugin:$kspPluginId:kspOutputDir=${project.root}/build/out",
"-P", "plugin:$kspPluginId:cachesDir=${project.root}/build/out",
"-P", "plugin:$kspPluginId:incremental=false",
"-d", "${project.root}/build/out"
)
pluginOptions.forEach {
compilerArgs.add("-P")
compilerArgs.add("plugin:$kspPluginId:$it")
}
compilerArgs.add(File(project.root, "workload/src/main/kotlin/com/example/A.kt").absolutePath)
val outStream = ByteArrayOutputStream()
val exitCode = compiler.exec(PrintStream(outStream), *compilerArgs.toTypedArray())
return CompileResult(exitCode, outStream.toString())
}

@Test
fun testWithCompilationOnError() {
val result = runCmdCompiler(listOf("apoption=error=true", "withCompilation=true"))
val errors = result.output.lines().filter { it.startsWith("error: [ksp]") }
val exitCode = result.exitCode
Assert.assertTrue(exitCode == ExitCode.COMPILATION_ERROR)
Assert.assertTrue(
errors.any {
it.startsWith("error: [ksp] java.lang.IllegalStateException: Error on request")
}
)
}

@Test
fun testWithCompilationOnErrorOk() {
val result = runCmdCompiler(listOf("apoption=error=true", "returnOkOnError=true", "withCompilation=true"))
val errors = result.output.lines().filter { it.startsWith("error: [ksp]") }
val exitCode = result.exitCode
Assert.assertTrue(exitCode == ExitCode.OK)
Assert.assertTrue(
errors.any {
it.startsWith("error: [ksp] java.lang.IllegalStateException: Error on request")
}
)
}
}
@@ -0,0 +1,8 @@
plugins {
kotlin("jvm")
}

repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap/")
}
Empty file.
@@ -0,0 +1,23 @@
val kspVersion: String by project
val testRepo: String by project

plugins {
kotlin("jvm")
}

group = "com.example"
version = "1.0-SNAPSHOT"

repositories {
maven(testRepo)
mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap/")
}

dependencies {
implementation("com.google.devtools.ksp:symbol-processing-api:$kspVersion")
}

sourceSets.main {
java.srcDirs("src/main/kotlin")
}
@@ -0,0 +1,37 @@
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.*

class TestProcessor : SymbolProcessor {
lateinit var codeGenerator: CodeGenerator
lateinit var logger: KSPLogger
lateinit var options: Map<String, String>
var rounds = 0

fun init(
options: Map<String, String>,
kotlinVersion: KotlinVersion,
codeGenerator: CodeGenerator,
logger: KSPLogger
) {
this.logger = logger
this.options = options
this.codeGenerator = codeGenerator
}

override fun process(resolver: Resolver): List<KSAnnotated> {
if (options.containsKey("error")) {
throw IllegalStateException("Error on request")
}
return emptyList()
}
}

class TestProcessorProvider : SymbolProcessorProvider {
override fun create(
env: SymbolProcessorEnvironment
): SymbolProcessor {
return TestProcessor().apply {
init(env.options, env.kotlinVersion, env.codeGenerator, env.logger)
}
}
}
@@ -0,0 +1 @@
TestProcessorProvider
@@ -0,0 +1,19 @@
pluginManagement {
val kspVersion: String by settings
val kotlinVersion: String by settings
val testRepo: String by settings
plugins {
id("com.google.devtools.ksp") version kspVersion
kotlin("jvm") version kotlinVersion
}
repositories {
maven(testRepo)
gradlePluginPortal()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap/")
}
}

rootProject.name = "cmd-options"

include(":workload")
include(":processors")
@@ -0,0 +1,19 @@
val testRepo: String by project

plugins {
id("com.google.devtools.ksp")
kotlin("jvm")
}

version = "1.0-SNAPSHOT"

repositories {
maven(testRepo)
mavenCentral()
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap/")
}

dependencies {
implementation(kotlin("stdlib"))
ksp(project(":processors"))
}
@@ -0,0 +1,4 @@
package com.example

fun main() {
}

0 comments on commit 5a19640

Please sign in to comment.