Add option to disable AP discovery in compile classpath

#KT-24530 Fixed

To disable discovery and enable avoidance for kapt tasks,
use "kapt.includeCompileClasspath = false"
This commit is contained in:
Alexey Tsvetkov
2018-12-07 14:42:25 +03:00
parent 445c85f829
commit d6459e6c49
16 changed files with 197 additions and 6 deletions
@@ -443,6 +443,75 @@ open class Kapt3IT : Kapt3BaseIT() {
}
}
@Test
fun testDisableDiscoveryInCompileClasspath() = with(Project("kaptAvoidance", directoryPrefix = "kapt2")) {
setupWorkingDir()
val buildGradle = projectDir.resolve("app/build.gradle")
buildGradle.modify {
it.addBeforeSubstring("//", "kapt \"org.jetbrains.kotlin")
}
build("assemble") {
assertSuccessful()
}
buildGradle.modify {
"$it\n\nkapt.includeCompileClasspath = false"
}
build("assemble") {
assertFailed()
}
}
@Test
fun testKaptAvoidance() = with(Project("kaptAvoidance", directoryPrefix = "kapt2")) {
build("assemble") {
assertSuccessful()
assertTasksExecuted(
":app:kaptGenerateStubsKotlin",
":app:kaptKotlin",
":app:compileKotlin",
":app:compileJava",
":lib:compileKotlin"
)
}
val original = "fun foo() = 0"
val replacement1 = "fun foo() = 1"
val replacement2 = "fun foo() = 2"
val libClassKt = projectDir.getFileByName("LibClass.kt")
libClassKt.modify { it.checkedReplace(original, replacement1) }
build("assemble") {
assertSuccessful()
assertTasksExecuted(
":lib:compileKotlin",
":app:kaptGenerateStubsKotlin",
":app:kaptKotlin"
)
}
// enable discovery
projectDir.resolve("app/build.gradle").modify {
"$it\n\nkapt.includeCompileClasspath = false"
}
build("assemble") {
assertSuccessful()
assertTasksUpToDate(":lib:compileKotlin")
assertTasksExecuted(
":app:kaptGenerateStubsKotlin",
":app:kaptKotlin"
)
}
libClassKt.modify { it.checkedReplace(replacement1, replacement2) }
build("assemble") {
assertSuccessful()
assertTasksExecuted(":lib:compileKotlin", ":app:kaptGenerateStubsKotlin")
assertTasksUpToDate(":app:kaptKotlin")
}
}
@Test
fun testKt19179() {
val project = Project("kt19179", directoryPrefix = "kapt2")
@@ -1,4 +1,9 @@
package org.jetbrains.kotlin.gradle.util
fun String.addBeforeSubstring(prefix: String, substring: String): String =
replace(substring, prefix + substring)
replace(substring, prefix + substring)
fun String.checkedReplace(original: String, replacement: String): String {
check(contains(original)) { "Substring '$original' is not found in '$this'" }
return replace(original, replacement)
}
@@ -0,0 +1,13 @@
apply plugin: "kotlin"
apply plugin: "kotlin-kapt"
dependencies {
compile project(":lib")
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version"
kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version"
// actually unused, but kapt skips AP when annotation processing classpath is empty (see checkOptions)
kapt "com.google.auto.service:auto-service:1.0-rc4"
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package app
import lib.*
@example.ExampleAnnotation
class AppClass {
@example.ExampleAnnotation
val testVal: String = "text"
@example.ExampleAnnotation
fun testFunction(): AppClassGenerated = AppClassGenerated()
fun useLibClass(libClass: LibClass) = libClass.foo()
}
@@ -0,0 +1,17 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
subprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
@@ -0,0 +1,5 @@
apply plugin: "kotlin"
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
@@ -0,0 +1,11 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package lib
class LibClass {
fun foo() = 0
}
@@ -266,6 +266,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
pluginOptions += SubpluginOption("javacArguments", encodeList(kaptExtension.getJavacOptions()))
pluginOptions += SubpluginOption("includeCompileClasspath", kaptExtension.includeCompileClasspath.toString())
addMiscOptions(pluginOptions)
return pluginOptions
@@ -390,6 +392,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
kaptTask.annotationProcessorOptionProviders.add(it)
}
kaptTask.includeCompileClasspath = kaptExtension.includeCompileClasspath
if (kaptTask is KaptWithKotlincTask) {
buildAndAddOptionsTo(kaptTask, kaptTask.pluginOptions, aptMode = "apt")
}
@@ -54,11 +54,35 @@ abstract class KaptTask : ConventionTask() {
@get:Nested
internal val annotationProcessorOptionProviders: MutableList<Any> = mutableListOf()
@get:Classpath
@get:InputFiles
@get:Input
internal var includeCompileClasspath: Boolean = true
// @Internal because _abiClasspath and _nonAbiClasspath are used for actual checks
@get:Internal
val classpath: FileCollection
get() = kotlinCompileTask.classpath
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
@Deprecated(
message = "Don't use directly. Used only for up-to-date checks",
level = DeprecationLevel.ERROR
)
@get:CompileClasspath
@get:InputFiles
internal val internalAbiClasspath: FileCollection
get() = if (includeCompileClasspath) project.files() else kotlinCompileTask.classpath
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
@Deprecated(
message = "Don't use directly. Used only for up-to-date checks",
level = DeprecationLevel.ERROR
)
@get:Classpath
@get:InputFiles
internal val internalNonAbiClasspath: FileCollection
get() = if (includeCompileClasspath) kotlinCompileTask.classpath else project.files()
@get:Internal
var useBuildCache: Boolean = false
@@ -82,4 +106,7 @@ abstract class KaptTask : ConventionTask() {
file.exists() &&
!FileUtil.isAncestor(destinationDir, file, /* strict = */ false) &&
!FileUtil.isAncestor(classesDir, file, /* strict = */ false)
private fun FileCollection?.orEmpty(): FileCollection =
this ?: project.files()
}
@@ -58,6 +58,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
val kaptFlagsForWorker = mutableSetOf<String>().apply {
if (isVerbose) add("VERBOSE")
if (mapDiagnosticLocations) add("MAP_DIAGNOSTIC_LOCATIONS")
if (includeCompileClasspath) add("INCLUDE_COMPILE_CLASSPATH")
}
val optionsForWorker = KaptOptionsForWorker(
@@ -37,6 +37,8 @@ open class KaptExtension {
open var detectMemoryLeaks: String = "default"
open var includeCompileClasspath: Boolean = true
@Deprecated("Use `annotationProcessor()` and `annotationProcessors()` instead")
open var processors: String = ""