Kapt3: Set correct compiler options when the annotation processing classpath is empty (KT-15146). Disable annotation processing in Javac task a bit earlier

This commit is contained in:
Yan Zhulanow
2016-12-19 19:35:16 +03:00
committed by Yan Zhulanow
parent f8edf51c1b
commit 568523b065
5 changed files with 81 additions and 11 deletions
@@ -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")
@@ -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
@@ -141,12 +141,15 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
(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<KotlinCompile> {
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") {
@@ -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<String> =
@@ -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<JavaSourceRoot>().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<KtFile>,
bindingTrace: BindingTrace,
componentProvider: ComponentProvider
): AnalysisResult? {
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
}
override fun analysisCompleted(
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
return AnalysisResult.Companion.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
}
}
}
@@ -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)
}