Skip to content

Commit 7049701

Browse files
yigittschuchortdev
authored andcommitted
adds tests for multiple calls to symbol processors
1 parent 43ea802 commit 7049701

File tree

2 files changed

+50
-25
lines changed
  • ksp/src
    • main/kotlin/com/tschuchort/compiletesting
    • test/kotlin/com/tschuchort/compiletesting

2 files changed

+50
-25
lines changed

ksp/src/main/kotlin/com/tschuchort/compiletesting/Ksp.kt

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,63 @@ package com.tschuchort.compiletesting
66
import org.jetbrains.kotlin.ksp.KotlinSymbolProcessingCommandLineProcessor
77
import org.jetbrains.kotlin.ksp.KotlinSymbolProcessingComponentRegistrar
88
import org.jetbrains.kotlin.ksp.processing.SymbolProcessor
9+
import java.io.File
910

1011
private const val KSP_PLUGIN_ID = "org.jetbrains.kotlin.ksp"
1112

12-
fun KotlinCompilation.symbolProcessor(
13+
private fun KotlinCompilation.initAndGetKspConfig(): KspConfiguration {
14+
val config = KspConfiguration(workingDir.resolve("ksp"))
15+
if (config.workingDir.exists()) {
16+
// already configured, just return
17+
return config
18+
}
19+
config.classesOutDir.mkdirs()
20+
config.sourcesOurDir.mkdirs()
21+
config.syntheticSources.mkdirs()
22+
val kspOptions = listOf(
23+
PluginOption(KSP_PLUGIN_ID, "apclasspath", config.syntheticSources.path),
24+
PluginOption(KSP_PLUGIN_ID, "classes", config.classesOutDir.path),
25+
PluginOption(KSP_PLUGIN_ID, "sources", config.sourcesOurDir.path)
26+
)
27+
compilerPlugins = compilerPlugins + KotlinSymbolProcessingComponentRegistrar()
28+
commandLineProcessors = commandLineProcessors + listOf(KotlinSymbolProcessingCommandLineProcessor())
29+
pluginOptions = pluginOptions + kspOptions
30+
return config
31+
}
32+
33+
fun KotlinCompilation.symbolProcessors(
1334
vararg processors: Class<out SymbolProcessor>
1435
) {
1536
check(processors.isNotEmpty()) {
1637
"Must provide at least 1 symbol processor"
1738
}
18-
val kspWorkingDir = workingDir.resolve("ksp")
39+
val config = initAndGetKspConfig()
1940

2041
// create a fake classpath that references our symbol processor
21-
val processorClasspath = kspWorkingDir.resolve("synthetic-ksp-service").apply {
42+
config.syntheticSources.apply {
2243
resolve("META-INF/services/org.jetbrains.kotlin.ksp.processing.SymbolProcessor").apply {
2344
parentFile.mkdirs()
24-
val processorNames = processors.joinToString(System.lineSeparator()) {
45+
// keep existing ones in case this function is called multiple times
46+
val existing = if (exists()) {
47+
readLines(Charsets.UTF_8)
48+
} else {
49+
emptyList()
50+
}
51+
val processorNames = existing + processors.map {
2552
it.typeName
2653
}
2754
writeText(
28-
processorNames
55+
processorNames.joinToString(System.lineSeparator())
2956
)
3057
}
3158
}
32-
33-
val classesFolder = kspWorkingDir.resolve("outClasses").also {
34-
it.mkdirs()
35-
}
36-
val sourceFolder = kspWorkingDir.resolve("outSources").also {
37-
it.mkdirs()
38-
}
39-
val kspOptions = listOf(
40-
PluginOption(KSP_PLUGIN_ID, "apclasspath", processorClasspath.path),
41-
PluginOption(KSP_PLUGIN_ID, "classes", classesFolder.path),
42-
PluginOption(KSP_PLUGIN_ID, "sources", sourceFolder.path)
43-
)
44-
compilerPlugins = compilerPlugins + KotlinSymbolProcessingComponentRegistrar()
45-
commandLineProcessors = commandLineProcessors + listOf(KotlinSymbolProcessingCommandLineProcessor())
46-
pluginOptions = pluginOptions + kspOptions
4759
this.kaptSourceDir
4860
}
61+
62+
private data class KspConfiguration(
63+
val workingDir: File
64+
) {
65+
val classesOutDir = workingDir.resolve("classesOutput")
66+
val sourcesOurDir = workingDir.resolve("sourcesOutput")
67+
val syntheticSources = workingDir.resolve("synthetic-ksp-service")
68+
}

ksp/src/test/kotlin/com/tschuchort/compiletesting/KspTest.kt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class KspTest {
2323
fun failedKspTest() {
2424
val result = KotlinCompilation().apply {
2525
sources = listOf(DUMMY_KOTLIN_SRC)
26-
symbolProcessor(processorRule.delegateTo(object : AbstractSymbolProcessor() {
26+
symbolProcessors(processorRule.delegateTo(object : AbstractSymbolProcessor() {
2727
override fun process(resolver: Resolver) {
2828
throw RuntimeException("intentional fail")
2929
}
@@ -38,7 +38,7 @@ class KspTest {
3838
val instance = mock<SymbolProcessor>()
3939
val result = KotlinCompilation().apply {
4040
sources = listOf(DUMMY_KOTLIN_SRC)
41-
symbolProcessor(processorRule.delegateTo(instance))
41+
symbolProcessors(processorRule.delegateTo(instance))
4242
}.compile()
4343
assertThat(result.exitCode).isEqualTo(ExitCode.OK)
4444
instance.inOrder {
@@ -92,7 +92,7 @@ class KspTest {
9292
}
9393
val result = KotlinCompilation().apply {
9494
sources = listOf(annotation, targetClass)
95-
symbolProcessor(processorRule.delegateTo(processor))
95+
symbolProcessors(processorRule.delegateTo(processor))
9696
}.compile()
9797
assertThat(result.exitCode).isEqualTo(ExitCode.OK)
9898
}
@@ -105,12 +105,14 @@ class KspTest {
105105
package foo.bar
106106
import generated.A
107107
import generated.B
108-
class Dummy(val a:A, val b:B)
108+
import generated.C
109+
class Dummy(val a:A, val b:B, val c:C)
109110
""".trimIndent()
110111
)
111112
val result = KotlinCompilation().apply {
112113
sources = listOf(source)
113-
symbolProcessor(Write_foo_bar_A::class.java, Write_foo_bar_B::class.java)
114+
symbolProcessors(Write_foo_bar_A::class.java, Write_foo_bar_B::class.java)
115+
symbolProcessors(Write_foo_bar_C::class.java)
114116
}.compile()
115117
assertThat(result.exitCode).isEqualTo(ExitCode.OK)
116118
}
@@ -121,6 +123,9 @@ class KspTest {
121123
@Suppress("ClassName")
122124
internal class Write_foo_bar_B() : ClassGeneratingProcessor("generated", "B")
123125

126+
@Suppress("ClassName")
127+
internal class Write_foo_bar_C() : ClassGeneratingProcessor("generated", "C")
128+
124129
internal open class ClassGeneratingProcessor(
125130
private val packageName: String,
126131
private val className: String

0 commit comments

Comments
 (0)