11package com.tschuchort.compiletesting
22
3- import com.google.devtools.ksp.processing.Dependencies
4- import com.google.devtools.ksp.processing.Resolver
5- import com.google.devtools.ksp.processing.SymbolProcessor
3+ import com.google.devtools.ksp.processing.*
64import com.google.devtools.ksp.symbol.KSAnnotated
75import com.google.devtools.ksp.symbol.KSClassDeclaration
86import com.nhaarman.mockitokotlin2.any
@@ -21,12 +19,14 @@ class KspTest {
2119 @Test
2220 fun failedKspTest () {
2321 val instance = mock<SymbolProcessor >()
22+ val providerInstance = mock<SymbolProcessorProvider >()
23+ `when `(providerInstance.create(any(), any(), any(), any())).thenReturn(instance)
2424 `when `(instance.process(any())).thenThrow(
2525 RuntimeException (" intentional fail" )
2626 )
2727 val result = KotlinCompilation ().apply {
2828 sources = listOf (DUMMY_KOTLIN_SRC )
29- symbolProcessors = listOf (instance )
29+ symbolProcessorProviders = listOf (providerInstance )
3030 }.compile()
3131 assertThat(result.exitCode).isEqualTo(ExitCode .INTERNAL_ERROR )
3232 assertThat(result.messages).contains(" intentional fail" )
@@ -35,13 +35,17 @@ class KspTest {
3535 @Test
3636 fun allProcessorMethodsAreCalled () {
3737 val instance = mock<SymbolProcessor >()
38+ val providerInstance = mock<SymbolProcessorProvider >()
39+ `when `(providerInstance.create(any(), any(), any(), any())).thenReturn(instance)
3840 val result = KotlinCompilation ().apply {
3941 sources = listOf (DUMMY_KOTLIN_SRC )
40- symbolProcessors = listOf (instance )
42+ symbolProcessorProviders = listOf (providerInstance )
4143 }.compile()
4244 assertThat(result.exitCode).isEqualTo(ExitCode .OK )
45+ providerInstance.inOrder {
46+ verify().create(any(), any(), any(), any())
47+ }
4348 instance.inOrder {
44- verify().init (any(), any(), any(), any())
4549 verify().process(any())
4650 verify().finish()
4751 }
@@ -68,33 +72,34 @@ class KspTest {
6872 }
6973 """ .trimIndent()
7074 )
71- val processor = object : AbstractTestSymbolProcessor () {
72- override fun process (resolver : Resolver ): List <KSAnnotated > {
73- val symbols = resolver.getSymbolsWithAnnotation(" foo.bar.TestAnnotation" )
74- if (symbols.isNotEmpty()) {
75- assertThat(symbols.size).isEqualTo(1 )
76- val klass = symbols.first()
77- check(klass is KSClassDeclaration )
78- val qName = klass.qualifiedName ? : error(" should've found qualified name" )
79- val genPackage = " ${qName.getQualifier()} .generated"
80- val genClassName = " ${qName.getShortName()} _Gen"
81- codeGenerator.createNewFile(
82- dependencies = Dependencies .ALL_FILES ,
83- packageName = genPackage,
84- fileName = genClassName
85- ).bufferedWriter(Charsets .UTF_8 ).use {
86- it.write("""
75+ val result = KotlinCompilation ().apply {
76+ sources = listOf (annotation, targetClass)
77+ symbolProcessorProviders = listOf (processorProviderOf { _, _, codeGenerator, logger ->
78+ object : AbstractTestSymbolProcessor (codeGenerator) {
79+ override fun process (resolver : Resolver ): List <KSAnnotated > {
80+ val symbols = resolver.getSymbolsWithAnnotation(" foo.bar.TestAnnotation" )
81+ if (symbols.isNotEmpty()) {
82+ assertThat(symbols.size).isEqualTo(1 )
83+ val klass = symbols.first()
84+ check(klass is KSClassDeclaration )
85+ val qName = klass.qualifiedName ? : error(" should've found qualified name" )
86+ val genPackage = " ${qName.getQualifier()} .generated"
87+ val genClassName = " ${qName.getShortName()} _Gen"
88+ codeGenerator.createNewFile(
89+ dependencies = Dependencies .ALL_FILES ,
90+ packageName = genPackage,
91+ fileName = genClassName
92+ ).bufferedWriter(Charsets .UTF_8 ).use {
93+ it.write("""
8794 package $genPackage
8895 class $genClassName () {}
8996 """ .trimIndent())
97+ }
98+ }
99+ return emptyList()
90100 }
91101 }
92- return emptyList()
93- }
94- }
95- val result = KotlinCompilation ().apply {
96- sources = listOf (annotation, targetClass)
97- symbolProcessors = listOf (processor)
102+ })
98103 }.compile()
99104 assertThat(result.exitCode).isEqualTo(ExitCode .OK )
100105 }
@@ -113,25 +118,26 @@ class KspTest {
113118 )
114119 val result = KotlinCompilation ().apply {
115120 sources = listOf (source)
116- symbolProcessors = listOf (
117- ClassGeneratingProcessor (" generated" , " A" ),
118- ClassGeneratingProcessor (" generated" , " B" ))
119- symbolProcessors = symbolProcessors + ClassGeneratingProcessor (" generated" , " C" )
121+ symbolProcessorProviders = listOf (
122+ processorProviderOf { _, _, codeGenerator, logger -> ClassGeneratingProcessor (codeGenerator, " generated" , " A" ) },
123+ processorProviderOf { _, _, codeGenerator, logger -> ClassGeneratingProcessor (codeGenerator, " generated" , " B" ) })
124+ symbolProcessorProviders = symbolProcessorProviders +
125+ processorProviderOf { _, _, codeGenerator, logger -> ClassGeneratingProcessor (codeGenerator, " generated" , " C" ) }
120126 }.compile()
121127 assertThat(result.exitCode).isEqualTo(ExitCode .OK )
122128 }
123129
124130 @Test
125131 fun readProcessors () {
126- val instance1 = mock<SymbolProcessor >()
127- val instance2 = mock<SymbolProcessor >()
132+ val instance1 = mock<SymbolProcessorProvider >()
133+ val instance2 = mock<SymbolProcessorProvider >()
128134 KotlinCompilation ().apply {
129- symbolProcessors = listOf (instance1)
130- assertThat(symbolProcessors ).containsExactly(instance1)
131- symbolProcessors = listOf (instance2)
132- assertThat(symbolProcessors ).containsExactly(instance2)
133- symbolProcessors = symbolProcessors + instance1
134- assertThat(symbolProcessors ).containsExactly(instance2, instance1)
135+ symbolProcessorProviders = listOf (instance1)
136+ assertThat(symbolProcessorProviders ).containsExactly(instance1)
137+ symbolProcessorProviders = listOf (instance2)
138+ assertThat(symbolProcessorProviders ).containsExactly(instance2)
139+ symbolProcessorProviders = symbolProcessorProviders + instance1
140+ assertThat(symbolProcessorProviders ).containsExactly(instance2, instance1)
135141 }
136142 }
137143
@@ -152,7 +158,9 @@ class KspTest {
152158 fun outputDirectoryContents () {
153159 val compilation = KotlinCompilation ().apply {
154160 sources = listOf (DUMMY_KOTLIN_SRC )
155- symbolProcessors = listOf (ClassGeneratingProcessor (" generated" , " Gen" ))
161+ symbolProcessorProviders = listOf (processorProviderOf { _, _, codeGenerator, logger ->
162+ ClassGeneratingProcessor (codeGenerator, " generated" , " Gen" )
163+ })
156164 }
157165 val result = compilation.compile()
158166 assertThat(result.exitCode).isEqualTo(ExitCode .OK )
@@ -181,32 +189,34 @@ class KspTest {
181189 """ .trimIndent()
182190 )
183191 val result = mutableListOf<String >()
184- val processor = object : AbstractTestSymbolProcessor () {
185- override fun process (resolver : Resolver ): List <KSAnnotated > {
186- resolver.getSymbolsWithAnnotation(
187- SuppressWarnings ::class .java.canonicalName
188- ).filterIsInstance<KSClassDeclaration >()
189- .forEach {
190- result.add(it.qualifiedName!! .asString())
191- }
192- return emptyList()
193- }
194- }
195192 val compilation = KotlinCompilation ().apply {
196193 sources = listOf (javaSource, kotlinSource)
197- symbolProcessors + = processor
194+ symbolProcessorProviders + = processorProviderOf { _, _, codeGenerator, logger ->
195+ object : AbstractTestSymbolProcessor (codeGenerator) {
196+ override fun process (resolver : Resolver ): List <KSAnnotated > {
197+ resolver.getSymbolsWithAnnotation(
198+ SuppressWarnings ::class .java.canonicalName
199+ ).filterIsInstance<KSClassDeclaration >()
200+ .forEach {
201+ result.add(it.qualifiedName!! .asString())
202+ }
203+ return emptyList()
204+ }
205+ }
206+ }
198207 }
199208 compilation.compile()
200209 assertThat(result).containsExactlyInAnyOrder(
201210 " JavaSubject" , " KotlinSubject"
202211 )
203212 }
204213
205- internal open class ClassGeneratingProcessor (
214+ internal class ClassGeneratingProcessor (
215+ codeGenerator : CodeGenerator ,
206216 private val packageName : String ,
207217 private val className : String ,
208218 times : Int = 1
209- ) : AbstractTestSymbolProcessor() {
219+ ) : AbstractTestSymbolProcessor(codeGenerator ) {
210220 val times = AtomicInteger (times)
211221 override fun process (resolver : Resolver ): List <KSAnnotated > {
212222 super .process(resolver)
@@ -241,17 +251,18 @@ class KspTest {
241251 class AppCode
242252 """ .trimIndent()
243253 )
244- val processor = object : AbstractTestSymbolProcessor () {
245- override fun process (resolver : Resolver ): List <KSAnnotated > {
246- logger.logging(" This is a log message" )
247- logger.info(" This is an info message" )
248- logger.warn(" This is an warn message" )
249- return emptyList()
250- }
251- }
252254 val result = KotlinCompilation ().apply {
253255 sources = listOf (annotation, targetClass)
254- symbolProcessors = listOf (processor)
256+ symbolProcessorProviders = listOf (processorProviderOf { _, _, codeGenerator, logger ->
257+ object : AbstractTestSymbolProcessor (codeGenerator) {
258+ override fun process (resolver : Resolver ): List <KSAnnotated > {
259+ logger.logging(" This is a log message" )
260+ logger.info(" This is an info message" )
261+ logger.warn(" This is an warn message" )
262+ return emptyList()
263+ }
264+ }
265+ })
255266 }.compile()
256267 assertThat(result.exitCode).isEqualTo(ExitCode .OK )
257268 assertThat(result.messages).contains(" This is a log message" )
@@ -274,16 +285,17 @@ class KspTest {
274285 class AppCode
275286 """ .trimIndent()
276287 )
277- val processor = object : AbstractTestSymbolProcessor () {
278- override fun process (resolver : Resolver ): List <KSAnnotated > {
279- logger.error(" This is an error message" )
280- logger.exception(Throwable (" This is a failure" ))
281- return emptyList()
282- }
283- }
284288 val result = KotlinCompilation ().apply {
285289 sources = listOf (annotation, targetClass)
286- symbolProcessors = listOf (processor)
290+ symbolProcessorProviders = listOf (processorProviderOf { _, _, codeGenerator, logger ->
291+ object : AbstractTestSymbolProcessor (codeGenerator) {
292+ override fun process (resolver : Resolver ): List <KSAnnotated > {
293+ logger.error(" This is an error message" )
294+ logger.exception(Throwable (" This is a failure" ))
295+ return emptyList()
296+ }
297+ }
298+ })
287299 }.compile()
288300 assertThat(result.exitCode).isEqualTo(ExitCode .COMPILATION_ERROR )
289301 assertThat(result.messages).contains(" This is an error message" )
0 commit comments