From 1dd5f2bc2c238d30c0a5ea9b0b671c65e7dc6bf0 Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Sun, 20 Oct 2019 20:58:15 +0200 Subject: [PATCH 1/6] 15: enable adding list of ComponentRegistrar instances to the compilation --- .../compiletesting/KaptComponentRegistrar.kt | 27 +++----- .../compiletesting/KotlinCompilation.kt | 20 +++--- .../compiletesting/MainComponentRegistrar.kt | 51 ++++++++++++++ ....kotlin.compiler.plugin.ComponentRegistrar | 2 +- .../compiletesting/CompilerPluginsTest.kt | 69 +++++++++++++++++++ .../compiletesting/KotlinCompilationTests.kt | 33 --------- .../tschuchort/compiletesting/TestUtils.kt | 38 ++++++++++ 7 files changed, 178 insertions(+), 62 deletions(-) create mode 100644 src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt create mode 100644 src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt create mode 100644 src/test/kotlin/com/tschuchort/compiletesting/TestUtils.kt diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt b/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt index e807ac4a..67dd3af2 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.tschuchort.compiletesting +package com.facebook.buck.jvm.java.javax.com.tschuchort.compiletesting import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.base.kapt3.AptMode @@ -47,17 +47,19 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension import java.io.File -import javax.annotation.processing.Processor -internal class KaptComponentRegistrar : ComponentRegistrar { +internal class KaptComponentRegistrar( + private val processors: List, + private val kaptOptions: KaptOptions.Builder +) : ComponentRegistrar { override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { - if (threadLocalParameters.get().processors.isEmpty()) + if (processors.isEmpty()) return val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList() - val optionsBuilder = threadLocalParameters.get().kaptOptions.apply { + val optionsBuilder = kaptOptions.apply { projectBaseDir = project.basePath?.let(::File) compileClasspath.addAll(contentRoots.filterIsInstance().map { it.file }) javaSourceRoots.addAll(contentRoots.filterIsInstance().map { it.file }) @@ -88,7 +90,7 @@ internal class KaptComponentRegistrar : ComponentRegistrar { val kapt3AnalysisCompletedHandlerExtension = object : AbstractKapt3Extension(options, logger, configuration) { override fun loadProcessors() = LoadedProcessors( - processors = threadLocalParameters.get().processors, + processors = processors, classLoader = this::class.java.classLoader ) } @@ -161,17 +163,4 @@ internal class KaptComponentRegistrar : ComponentRegistrar { } } - companion object { - /** This kapt compiler plugin is instantiated by K2JVMCompiler using - * a service locator. So we can't just pass parameters to it easily. - * Instead we need to use a thread-local global variable to pass - * any parameters that change between compilations - */ - val threadLocalParameters: ThreadLocal = ThreadLocal() - } - - data class Parameters( - val processors: List, - val kaptOptions: KaptOptions.Builder - ) } \ No newline at end of file diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt index 777d4a84..45c3af89 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt @@ -70,6 +70,11 @@ class KotlinCompilation { */ var pluginClasspaths: List = emptyList() + /** + * Compiler plugins that should be added the compilation + */ + var compilerPlugins: List = emptyList() + /** Source files to be compiled */ var sources: List = emptyList() @@ -409,10 +414,6 @@ class KotlinCompilation { } /** Performs the 1st and 2nd compilation step to generate stubs and run annotation processors */ private fun stubsAndApt(sourceFiles: List): ExitCode { - if(annotationProcessors.isEmpty()) { - log("No services were given. Not running kapt steps.") - return ExitCode.OK - } val kaptOptions = KaptOptions.Builder().also { it.stubsOutputDir = kaptStubsDir @@ -436,10 +437,11 @@ class KotlinCompilation { * Instead we need to use a thread-local global variable to pass * any parameters that change between compilations */ - KaptComponentRegistrar.threadLocalParameters.set( - KaptComponentRegistrar.Parameters( + MainComponentRegistrar.threadLocalParameters.set( + MainComponentRegistrar.Parameters( annotationProcessors.map { IncrementalProcessor(it, DeclaredProcType.NON_INCREMENTAL) }, - kaptOptions + kaptOptions, + compilerPlugins ) ) @@ -510,7 +512,7 @@ class KotlinCompilation { } .find { resourcesPath -> ServiceLoaderLite.findImplementations(ComponentRegistrar::class.java, listOf(resourcesPath.toFile())) - .any { implementation -> implementation == KaptComponentRegistrar::class.java.name } + .any { implementation -> implementation == MainComponentRegistrar::class.java.name } }?.toString() ?: throw AssertionError("Could not get path to ComponentRegistrar service from META-INF") } @@ -703,7 +705,7 @@ class KotlinCompilation { return makeResult(exitCode) } } finally { - KaptComponentRegistrar.threadLocalParameters.remove() + MainComponentRegistrar.threadLocalParameters.remove() } // step 3: compile Kotlin files diff --git a/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt new file mode 100644 index 00000000..dd4763cb --- /dev/null +++ b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.tschuchort.compiletesting + +import com.facebook.buck.jvm.java.javax.com.tschuchort.compiletesting.KaptComponentRegistrar +import org.jetbrains.kotlin.base.kapt3.KaptOptions +import org.jetbrains.kotlin.com.intellij.mock.MockProject +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor + +internal class MainComponentRegistrar : ComponentRegistrar { + + override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { + val parameters = threadLocalParameters.get() + KaptComponentRegistrar(parameters.processors,parameters.kaptOptions).registerProjectComponents(project,configuration) + + parameters.compilerPlugins.forEach { componentRegistrar-> + componentRegistrar.registerProjectComponents(project,configuration) + } + } + + companion object { + /** This kapt compiler plugin is instantiated by K2JVMCompiler using + * a service locator. So we can't just pass parameters to it easily. + * Instead we need to use a thread-local global variable to pass + * any parameters that change between compilations + */ + val threadLocalParameters: ThreadLocal = ThreadLocal() + } + + data class Parameters( + val processors: List, + val kaptOptions: KaptOptions.Builder, + val compilerPlugins: List + ) +} \ No newline at end of file diff --git a/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar b/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar index 5997746c..80e59f28 100644 --- a/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +++ b/src/main/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar @@ -1 +1 @@ -com.tschuchort.compiletesting.KaptComponentRegistrar \ No newline at end of file +com.tschuchort.compiletesting.MainComponentRegistrar \ No newline at end of file diff --git a/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt new file mode 100644 index 00000000..7be26ba5 --- /dev/null +++ b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt @@ -0,0 +1,69 @@ +package com.tschuchort.compiletesting + +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.verify +import org.assertj.core.api.Assertions +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.junit.Assert +import org.junit.Test +import org.mockito.Mockito +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.element.TypeElement + +class CompilerPluginsTest{ + + @Test + fun whenCompilerPluginsAreAddedTheyGetExecuted() { + + val mockPlugin = Mockito.mock(ComponentRegistrar::class.java) + + val result = defaultCompilerConfig().apply { + compilerPlugins = listOf(mockPlugin) + inheritClassPath = true + }.compile() + + verify(mockPlugin).registerProjectComponents(any(), any()) + + Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } + + @Test + fun whenCompilerPluginsAndAnnotationProcessorsAreAddedTheyGetExecuted() { + + val annotationProcessor = object : AbstractProcessor() { + override fun getSupportedAnnotationTypes(): Set = setOf(ProcessElem::class.java.canonicalName) + + override fun process(p0: MutableSet?, p1: RoundEnvironment?): Boolean { + p1?.getElementsAnnotatedWith(ProcessElem::class.java)?.forEach { + Assert.assertEquals("JSource",it?.simpleName.toString()) + } + return false + } + } + + val mockPlugin = Mockito.mock(ComponentRegistrar::class.java) + + val jSource = SourceFile.java( + "JSource.java", """ + package com.tschuchort.compiletesting; + + @ProcessElem + class JSource { + void foo() { } + } + """ + ) + + val result = defaultCompilerConfig().apply { + sources = listOf(jSource) + annotationProcessors= listOf(annotationProcessor) + compilerPlugins = listOf(mockPlugin) + inheritClassPath = true + }.compile() + + verify(mockPlugin).registerProjectComponents(any(), any()) + + Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/tschuchort/compiletesting/KotlinCompilationTests.kt b/src/test/kotlin/com/tschuchort/compiletesting/KotlinCompilationTests.kt index 1ced94f4..facda086 100644 --- a/src/test/kotlin/com/tschuchort/compiletesting/KotlinCompilationTests.kt +++ b/src/test/kotlin/com/tschuchort/compiletesting/KotlinCompilationTests.kt @@ -649,38 +649,5 @@ class KotlinCompilationTests { assertThat(result.messages).contains("non-existing-plugin.jar not found") } - private fun defaultCompilerConfig(): KotlinCompilation { - return KotlinCompilation().apply { - workingDir = temporaryFolder.root - inheritClassPath = false - skipRuntimeVersionCheck = true - correctErrorTypes = true - verbose = true - reportOutputFiles = false - messageOutputStream = System.out - } - } - - private fun assertClassLoadable(compileResult: KotlinCompilation.Result, className: String): Class<*> { - try { - val clazz = compileResult.classLoader.loadClass(className) - assertThat(clazz).isNotNull - return clazz - } - catch(e: ClassNotFoundException) { - return fail("Class $className could not be loaded") - } - } - - /** - * Returns the classpath for a dependency (format $name-$version). - * This is necessary to know the actual location of a dependency - * which has been included in test runtime (build.gradle). - */ - private fun classpathOf(dependency: String): File { - val regex = Regex(".*$dependency\\.jar") - return ClassGraph().classpathFiles.first { classpath -> classpath.name.matches(regex) } - } - class InheritedClass {} } diff --git a/src/test/kotlin/com/tschuchort/compiletesting/TestUtils.kt b/src/test/kotlin/com/tschuchort/compiletesting/TestUtils.kt new file mode 100644 index 00000000..5bb7b09c --- /dev/null +++ b/src/test/kotlin/com/tschuchort/compiletesting/TestUtils.kt @@ -0,0 +1,38 @@ +package com.tschuchort.compiletesting + +import io.github.classgraph.ClassGraph +import org.assertj.core.api.Assertions +import java.io.File + +fun defaultCompilerConfig(): KotlinCompilation { + return KotlinCompilation( ).apply { + inheritClassPath = false + skipRuntimeVersionCheck = true + correctErrorTypes = true + verbose = true + reportOutputFiles = false + messageOutputStream = System.out + } +} + + +fun assertClassLoadable(compileResult: KotlinCompilation.Result, className: String): Class<*> { + try { + val clazz = compileResult.classLoader.loadClass(className) + Assertions.assertThat(clazz).isNotNull + return clazz + } + catch(e: ClassNotFoundException) { + return Assertions.fail("Class $className could not be loaded") + } +} + +/** + * Returns the classpath for a dependency (format $name-$version). + * This is necessary to know the actual location of a dependency + * which has been included in test runtime (build.gradle). + */ +fun classpathOf(dependency: String): File { + val regex = Regex(".*$dependency\\.jar") + return ClassGraph().classpathFiles.first { classpath -> classpath.name.matches(regex) } +} \ No newline at end of file From 4bacb84d9dd6a5ed679be94c54fef86f7b2e4d0d Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Sun, 20 Oct 2019 21:06:01 +0200 Subject: [PATCH 2/6] 15: enable adding list of ComponentRegistrar instances to the compilation --- .../com/tschuchort/compiletesting/KaptComponentRegistrar.kt | 2 +- .../com/tschuchort/compiletesting/MainComponentRegistrar.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt b/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt index 67dd3af2..e889e93d 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KaptComponentRegistrar.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.facebook.buck.jvm.java.javax.com.tschuchort.compiletesting +package com.tschuchort.compiletesting import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.base.kapt3.AptMode diff --git a/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt index dd4763cb..2d9ef791 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt @@ -16,7 +16,6 @@ package com.tschuchort.compiletesting -import com.facebook.buck.jvm.java.javax.com.tschuchort.compiletesting.KaptComponentRegistrar import org.jetbrains.kotlin.base.kapt3.KaptOptions import org.jetbrains.kotlin.com.intellij.mock.MockProject import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar From bd20eed917c86830b0cc96a2dc182ccd5ab63e3b Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Mon, 21 Oct 2019 22:01:45 +0200 Subject: [PATCH 3/6] 15: enable adding list of ComponentRegistar instances to the compilation --- .../compiletesting/KotlinCompilation.kt | 32 ++++++++++++++++--- .../compiletesting/MainComponentRegistrar.kt | 2 +- .../compiletesting/CompilerPluginsTest.kt | 13 ++++---- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt index 45c3af89..5862e7cc 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt @@ -414,6 +414,10 @@ class KotlinCompilation { } /** Performs the 1st and 2nd compilation step to generate stubs and run annotation processors */ private fun stubsAndApt(sourceFiles: List): ExitCode { + if(annotationProcessors.isEmpty()) { + log("No services were given. Not running kapt steps.") + return ExitCode.OK + } val kaptOptions = KaptOptions.Builder().also { it.stubsOutputDir = kaptStubsDir @@ -431,17 +435,18 @@ class KotlinCompilation { it.flags.addAll(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS, KaptFlag.VERBOSE) } - /* The kapt compiler plugin (KaptComponentRegistrar) + /** The main compiler plugin (MainComponentRegistrar) * is instantiated by K2JVMCompiler using * a service locator. So we can't just pass parameters to it easily. * Instead we need to use a thread-local global variable to pass * any parameters that change between compilations + * */ MainComponentRegistrar.threadLocalParameters.set( MainComponentRegistrar.Parameters( annotationProcessors.map { IncrementalProcessor(it, DeclaredProcType.NON_INCREMENTAL) }, kaptOptions, - compilerPlugins + listOf() ) ) @@ -518,17 +523,34 @@ class KotlinCompilation { /** Performs the 3rd compilation step to compile Kotlin source files */ private fun compileKotlin(sourceFiles: List): ExitCode { + + /** + * Here the list of compiler plugins is set + * + * To avoid that the annotation processors are executed twice, + * the list is set to empty + */ + MainComponentRegistrar.threadLocalParameters.set( + MainComponentRegistrar.Parameters( + listOf(), + KaptOptions.Builder(), + compilerPlugins + ) + ) + + val sources = sourceFiles + kaptKotlinGeneratedDir.listFilesRecursively() + kaptSourceDir.listFilesRecursively() // if no Kotlin sources are available, skip the compileKotlin step - if(sources.filter(File::hasKotlinFileExtension).isEmpty()) + if(sources.none(File::hasKotlinFileExtension)) return ExitCode.OK // in this step also include source files generated by kapt in the previous step - val k2JvmArgs = commonK2JVMArgs().also { - it.freeArgs = sources.map(File::getAbsolutePath).distinct() + val k2JvmArgs = commonK2JVMArgs().also {jvmArgs-> + jvmArgs.pluginClasspaths = (jvmArgs.pluginClasspaths ?: emptyArray()) + arrayOf(getResourcesPath()) + jvmArgs.freeArgs = sources.map(File::getAbsolutePath).distinct() } val compilerMessageCollector = PrintingMessageCollector( diff --git a/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt index 2d9ef791..40449eea 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/MainComponentRegistrar.kt @@ -34,7 +34,7 @@ internal class MainComponentRegistrar : ComponentRegistrar { } companion object { - /** This kapt compiler plugin is instantiated by K2JVMCompiler using + /** This compiler plugin is instantiated by K2JVMCompiler using * a service locator. So we can't just pass parameters to it easily. * Instead we need to use a thread-local global variable to pass * any parameters that change between compilations diff --git a/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt index 7be26ba5..593806c7 100644 --- a/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt +++ b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt @@ -14,11 +14,12 @@ import javax.lang.model.element.TypeElement class CompilerPluginsTest{ @Test - fun whenCompilerPluginsAreAddedTheyGetExecuted() { + fun `when compilerplugins are added they get executed`() { val mockPlugin = Mockito.mock(ComponentRegistrar::class.java) val result = defaultCompilerConfig().apply { + sources = listOf(SourceFile.new("emptyKotlinFile.kt", "")) compilerPlugins = listOf(mockPlugin) inheritClassPath = true }.compile() @@ -29,7 +30,7 @@ class CompilerPluginsTest{ } @Test - fun whenCompilerPluginsAndAnnotationProcessorsAreAddedTheyGetExecuted() { + fun `when compiler plugins and annotation processors are added they get executed`() { val annotationProcessor = object : AbstractProcessor() { override fun getSupportedAnnotationTypes(): Set = setOf(ProcessElem::class.java.canonicalName) @@ -44,13 +45,13 @@ class CompilerPluginsTest{ val mockPlugin = Mockito.mock(ComponentRegistrar::class.java) - val jSource = SourceFile.java( - "JSource.java", """ + val jSource = SourceFile.kotlin( + "JSource.kt", """ package com.tschuchort.compiletesting; @ProcessElem class JSource { - void foo() { } + fun foo() { } } """ ) @@ -62,7 +63,7 @@ class CompilerPluginsTest{ inheritClassPath = true }.compile() - verify(mockPlugin).registerProjectComponents(any(), any()) + verify(mockPlugin).registerProjectComponents(any(), any()) Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) } From bc48d3980524b9c8e951e3ce1c88c2e046255510 Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Mon, 28 Oct 2019 19:09:42 +0100 Subject: [PATCH 4/6] 15: enable adding list of ComponentRegistar instances to the compilation --- .../compiletesting/KotlinCompilation.kt | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt index 5862e7cc..d4e265f0 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt @@ -414,7 +414,7 @@ class KotlinCompilation { } /** Performs the 1st and 2nd compilation step to generate stubs and run annotation processors */ private fun stubsAndApt(sourceFiles: List): ExitCode { - if(annotationProcessors.isEmpty()) { + if(annotationProcessors.isEmpty() && compilerPlugins.isEmpty()) { log("No services were given. Not running kapt steps.") return ExitCode.OK } @@ -446,7 +446,7 @@ class KotlinCompilation { MainComponentRegistrar.Parameters( annotationProcessors.map { IncrementalProcessor(it, DeclaredProcType.NON_INCREMENTAL) }, kaptOptions, - listOf() + compilerPlugins ) ) @@ -523,22 +523,6 @@ class KotlinCompilation { /** Performs the 3rd compilation step to compile Kotlin source files */ private fun compileKotlin(sourceFiles: List): ExitCode { - - /** - * Here the list of compiler plugins is set - * - * To avoid that the annotation processors are executed twice, - * the list is set to empty - */ - MainComponentRegistrar.threadLocalParameters.set( - MainComponentRegistrar.Parameters( - listOf(), - KaptOptions.Builder(), - compilerPlugins - ) - ) - - val sources = sourceFiles + kaptKotlinGeneratedDir.listFilesRecursively() + kaptSourceDir.listFilesRecursively() @@ -548,9 +532,8 @@ class KotlinCompilation { return ExitCode.OK // in this step also include source files generated by kapt in the previous step - val k2JvmArgs = commonK2JVMArgs().also {jvmArgs-> - jvmArgs.pluginClasspaths = (jvmArgs.pluginClasspaths ?: emptyArray()) + arrayOf(getResourcesPath()) - jvmArgs.freeArgs = sources.map(File::getAbsolutePath).distinct() + val k2JvmArgs = commonK2JVMArgs().also { + it.freeArgs = sources.map(File::getAbsolutePath).distinct() } val compilerMessageCollector = PrintingMessageCollector( From b778d2677112df6f978c97b5e98bb2dbde7c0097 Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Wed, 6 Nov 2019 19:34:44 +0100 Subject: [PATCH 5/6] 15: enable adding list of ComponentRegistar instances to the compilation - add plugins in compileKotlin --- .../compiletesting/KotlinCompilation.kt | 21 +++++++++++++++++-- .../compiletesting/CompilerPluginsTest.kt | 13 ++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt index 6545c943..eeedd01c 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt @@ -529,6 +529,22 @@ class KotlinCompilation { /** Performs the 3rd compilation step to compile Kotlin source files */ private fun compileKotlin(sourceFiles: List): ExitCode { + + /** + * Here the list of compiler plugins is set + * + * To avoid that the annotation processors are executed twice, + * the list is set to empty + */ + MainComponentRegistrar.threadLocalParameters.set( + MainComponentRegistrar.Parameters( + listOf(), + KaptOptions.Builder(), + compilerPlugins + ) + ) + + val sources = sourceFiles + kaptKotlinGeneratedDir.listFilesRecursively() + kaptSourceDir.listFilesRecursively() @@ -538,8 +554,9 @@ class KotlinCompilation { return ExitCode.OK // in this step also include source files generated by kapt in the previous step - val k2JvmArgs = commonK2JVMArgs().also { - it.freeArgs = sources.map(File::getAbsolutePath).distinct() + val k2JvmArgs = commonK2JVMArgs().also {jvmArgs-> + jvmArgs.pluginClasspaths = (jvmArgs.pluginClasspaths ?: emptyArray()) + arrayOf(getResourcesPath()) + jvmArgs.freeArgs = sources.map(File::getAbsolutePath).distinct() } val compilerMessageCollector = PrintingMessageCollector( diff --git a/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt index 593806c7..4d590c53 100644 --- a/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt +++ b/src/test/kotlin/com/tschuchort/compiletesting/CompilerPluginsTest.kt @@ -1,6 +1,7 @@ package com.tschuchort.compiletesting import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.atLeastOnce import com.nhaarman.mockitokotlin2.verify import org.assertj.core.api.Assertions import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar @@ -11,10 +12,10 @@ import javax.annotation.processing.AbstractProcessor import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.TypeElement -class CompilerPluginsTest{ +class CompilerPluginsTest { @Test - fun `when compilerplugins are added they get executed`() { + fun `when compiler plugins are added they get executed`() { val mockPlugin = Mockito.mock(ComponentRegistrar::class.java) @@ -24,7 +25,7 @@ class CompilerPluginsTest{ inheritClassPath = true }.compile() - verify(mockPlugin).registerProjectComponents(any(), any()) + verify(mockPlugin, atLeastOnce()).registerProjectComponents(any(), any()) Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) } @@ -37,7 +38,7 @@ class CompilerPluginsTest{ override fun process(p0: MutableSet?, p1: RoundEnvironment?): Boolean { p1?.getElementsAnnotatedWith(ProcessElem::class.java)?.forEach { - Assert.assertEquals("JSource",it?.simpleName.toString()) + Assert.assertEquals("JSource", it?.simpleName.toString()) } return false } @@ -58,12 +59,12 @@ class CompilerPluginsTest{ val result = defaultCompilerConfig().apply { sources = listOf(jSource) - annotationProcessors= listOf(annotationProcessor) + annotationProcessors = listOf(annotationProcessor) compilerPlugins = listOf(mockPlugin) inheritClassPath = true }.compile() - verify(mockPlugin).registerProjectComponents(any(), any()) + verify(mockPlugin, atLeastOnce()).registerProjectComponents(any(), any()) Assertions.assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) } From 725bed3574a96949387d81d309699017ec9b3107 Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Wed, 6 Nov 2019 19:45:50 +0100 Subject: [PATCH 6/6] 15: enable adding list of ComponentRegistar instances to the compilation - add plugins in compileKotlin --- .../kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt index eeedd01c..1be2a43d 100644 --- a/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt +++ b/src/main/kotlin/com/tschuchort/compiletesting/KotlinCompilation.kt @@ -420,7 +420,7 @@ class KotlinCompilation { } /** Performs the 1st and 2nd compilation step to generate stubs and run annotation processors */ private fun stubsAndApt(sourceFiles: List): ExitCode { - if(annotationProcessors.isEmpty() && compilerPlugins.isEmpty()) { + if(annotationProcessors.isEmpty()) { log("No services were given. Not running kapt steps.") return ExitCode.OK }