From 568523b0652889f66ddde65819aceba5e0902ebf Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Mon, 19 Dec 2016 19:35:16 +0300 Subject: [PATCH] Kapt3: Set correct compiler options when the annotation processing classpath is empty (KT-15146). Disable annotation processing in Javac task a bit earlier --- .../org/jetbrains/kotlin/gradle/Kapt3IT.kt | 4 +- .../app/src/test/java/SimpleClass.kt | 19 +++++++ .../internal/Kapt3KotlinGradleSubplugin.kt | 8 ++- .../org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt | 56 +++++++++++++++++-- .../jetbrains/kotlin/kapt3/util/KaptLogger.kt | 5 ++ 5 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/src/test/java/SimpleClass.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 73b88c60f30..c010b36244d 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -39,7 +39,7 @@ class Kapt3IT : BaseGradleIT() { private fun CompiledProject.assertKaptSuccessful() { - KAPT_SUCCESSFUL_REGEX.findAll(this.output).single() + KAPT_SUCCESSFUL_REGEX.findAll(this.output).count() > 0 } @Test @@ -151,7 +151,7 @@ class Kapt3IT : BaseGradleIT() { val project = Project("android-dagger", GRADLE_VERSION, directoryPrefix = "kapt2") val options = androidBuildOptions() - project.build("compileReleaseSources", options = options) { + project.build("compileReleaseSources", ":app:compileDebugUnitTestJavaWithJavac", options = options) { assertSuccessful() assertKaptSuccessful() assertFileExists("app/build/generated/source/kapt/release/com/example/dagger/kotlin/DaggerApplicationComponent.java") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/src/test/java/SimpleClass.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/src/test/java/SimpleClass.kt new file mode 100644 index 00000000000..d08e0a5e862 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/android-dagger/app/src/test/java/SimpleClass.kt @@ -0,0 +1,19 @@ +/* + * 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.myapp + +class SimpleClass \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt index 869e16a7015..86cd4fc5018 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt @@ -141,12 +141,15 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { (variantData as BaseVariantData<*>).addJavaSourceFoldersToModel(generatedFilesDir) } + pluginOptions += SubpluginOption("aptOnly", "true") + disableAnnotationProcessingInJavaTask() + // Skip annotation processing in kotlinc if no kapt dependencies were provided - if (kaptClasspath.isEmpty()) return emptyList() + if (kaptClasspath.isEmpty()) return pluginOptions + kaptClasspath.forEach { pluginOptions += SubpluginOption("apclasspath", it.absolutePath) } javaCompile.source(generatedFilesDir) - disableAnnotationProcessingInJavaTask() pluginOptions += SubpluginOption("sources", generatedFilesDir.canonicalPath) pluginOptions += SubpluginOption("classes", kotlinCompile.destinationDir.canonicalPath) @@ -176,7 +179,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { project.logger.warn("'kapt.generateStubs' is not used by the 'kotlin-kapt' plugin") } - pluginOptions += SubpluginOption("aptOnly", "true") pluginOptions += SubpluginOption("useLightAnalysis", "${kaptExtension.useLightAnalysis}") if (project.hasProperty(VERBOSE_OPTION_NAME) && project.property(VERBOSE_OPTION_NAME) == "true") { diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt index 7ca760a3984..56d0f59c306 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.kapt3 import com.intellij.mock.MockProject import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTIONS import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot @@ -29,11 +31,18 @@ import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.container.ComponentProvider +import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.kapt3.diagnostic.DefaultErrorMessagesKapt3 import org.jetbrains.kotlin.kapt3.util.KaptLogger +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 java.util.* object Kapt3ConfigurationKeys { val SOURCE_OUTPUT_DIR: CompilerConfigurationKey = @@ -121,11 +130,24 @@ class Kapt3CommandLineProcessor : CommandLineProcessor { class Kapt3ComponentRegistrar : ComponentRegistrar { override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { - val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File) ?: return - val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File) ?: return + val isAptOnly = configuration.get(Kapt3ConfigurationKeys.APT_ONLY) == "true" + val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true" + val logger = KaptLogger(isVerbose) + + val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File) + val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File) val stubsOutputDir = configuration.get(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR)?.let(::File) - val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File) ?: return + val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File) + + if (sourcesOutputDir == null || classFilesOutputDir == null || apClasspath == null) { + if (isAptOnly) { + val subject = if (apClasspath == null) "Annotation processing classpath" else "Generated files output directories" + logger.warn("$subject is not specified, skipping annotation processing") + AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension()) + } + return + } val apOptions = (configuration.get(APT_OPTIONS) ?: listOf()) .map { it.split(':', limit = 2) } @@ -141,13 +163,10 @@ class Kapt3ComponentRegistrar : ComponentRegistrar { val javaSourceRoots = contentRoots.filterIsInstance().map { it.file } - val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true" - val isAptOnly = configuration.get(Kapt3ConfigurationKeys.APT_ONLY) == "true" val useLightAnalysis = configuration.get(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS) == "true" Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesKapt3()) - val logger = KaptLogger(isVerbose) if (isVerbose) { logger.info("Kapt3 is enabled.") logger.info("Do annotation processing only: $isAptOnly") @@ -165,4 +184,29 @@ class Kapt3ComponentRegistrar : ComponentRegistrar { isAptOnly, useLightAnalysis, System.currentTimeMillis(), logger) AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension) } + + /* This extension simply disables both code analysis and code generation. + * When aptOnly is true, and any of required kapt options was not passed, we just abort compilation by providing this extension. + * */ + private class AbortAnalysisHandlerExtension : AnalysisHandlerExtension { + override fun doAnalysis( + project: Project, + module: ModuleDescriptor, + projectContext: ProjectContext, + files: Collection, + bindingTrace: BindingTrace, + componentProvider: ComponentProvider + ): AnalysisResult? { + return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false) + } + + override fun analysisCompleted( + project: Project, + module: ModuleDescriptor, + bindingTrace: BindingTrace, + files: Collection + ): AnalysisResult? { + return AnalysisResult.Companion.success(bindingTrace.bindingContext, module, shouldGenerateCode = false) + } + } } \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt index c2d20077014..543333a941b 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt @@ -32,6 +32,11 @@ class KaptLogger(val isVerbose: Boolean) { info(message()) } } + + fun warn(message: String) { + println(PREFIX + message) + } + fun error(message: String) { System.err.println(PREFIX + message) }