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:
+69
@@ -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")
|
||||
|
||||
+6
-1
@@ -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)
|
||||
}
|
||||
+13
@@ -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"
|
||||
}
|
||||
+19
@@ -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()
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
subprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
apply plugin: "kotlin"
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
}
|
||||
+11
@@ -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
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
include ':app', ':lib'
|
||||
+4
@@ -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")
|
||||
}
|
||||
|
||||
+29
-2
@@ -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()
|
||||
}
|
||||
+1
@@ -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(
|
||||
|
||||
+2
@@ -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 = ""
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ class KaptOptions(
|
||||
val processingOptions: MutableMap<String, String> = mutableMapOf()
|
||||
val javacOptions: MutableMap<String, String> = mutableMapOf()
|
||||
|
||||
val flags: MutableSet<KaptFlag> = mutableSetOf(KaptFlag.USE_LIGHT_ANALYSIS)
|
||||
val flags: MutableSet<KaptFlag> = mutableSetOf(
|
||||
KaptFlag.USE_LIGHT_ANALYSIS,
|
||||
KaptFlag.INCLUDE_COMPILE_CLASSPATH
|
||||
)
|
||||
|
||||
var mode: AptMode = AptMode.WITH_COMPILATION
|
||||
var detectMemoryLeaks: DetectMemoryLeaksMode = DetectMemoryLeaksMode.DEFAULT
|
||||
@@ -88,7 +91,8 @@ enum class KaptFlag(val description: String) {
|
||||
USE_LIGHT_ANALYSIS("Use light analysis"),
|
||||
CORRECT_ERROR_TYPES("Correct error types"),
|
||||
MAP_DIAGNOSTIC_LOCATIONS("Map diagnostic locations"),
|
||||
STRICT("Strict mode");
|
||||
STRICT("Strict mode"),
|
||||
INCLUDE_COMPILE_CLASSPATH("Detect annotation processors in compile classpath");
|
||||
}
|
||||
|
||||
interface KaptSelector {
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.base
|
||||
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||
import org.jetbrains.kotlin.kapt3.base.util.info
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
import java.net.URLClassLoader
|
||||
@@ -23,7 +25,12 @@ open class ProcessorLoader(private val options: KaptOptions, private val logger:
|
||||
fun loadProcessors(parentClassLoader: ClassLoader = ClassLoader.getSystemClassLoader()): LoadedProcessors {
|
||||
clearJarURLCache()
|
||||
|
||||
val classpath = (options.processingClasspath + options.compileClasspath).distinct()
|
||||
val classpath = LinkedHashSet<File>().apply {
|
||||
addAll(options.processingClasspath)
|
||||
if (options[KaptFlag.INCLUDE_COMPILE_CLASSPATH]) {
|
||||
addAll(options.compileClasspath)
|
||||
}
|
||||
}
|
||||
val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), parentClassLoader)
|
||||
this.annotationProcessingClassLoader = classLoader
|
||||
|
||||
|
||||
@@ -149,6 +149,11 @@ enum class KaptCliOption(
|
||||
),
|
||||
|
||||
DETECT_MEMORY_LEAKS_OPTION("detectMemoryLeaks", "true | false", "Detect memory leaks in annotation processors"),
|
||||
INCLUDE_COMPILE_CLASSPATH(
|
||||
"includeCompileClasspath",
|
||||
"true | false",
|
||||
"Discover annotation processors in compile classpath"
|
||||
),
|
||||
|
||||
INFO_AS_WARNINGS_OPTION("infoAsWarnings", "true | false", "Show information messages as warnings"),
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
INFO_AS_WARNINGS_OPTION -> setFlag(KaptFlag.INFO_AS_WARNINGS, value)
|
||||
STRICT_MODE_OPTION -> setFlag(KaptFlag.STRICT, value)
|
||||
SHOW_PROCESSOR_TIMINGS -> setFlag(KaptFlag.SHOW_PROCESSOR_TIMINGS, value)
|
||||
INCLUDE_COMPILE_CLASSPATH -> setFlag(KaptFlag.INCLUDE_COMPILE_CLASSPATH, value)
|
||||
|
||||
DETECT_MEMORY_LEAKS_OPTION -> setSelector(enumValues<DetectMemoryLeaksMode>(), value) { detectMemoryLeaks = it }
|
||||
APT_MODE_OPTION -> setSelector(enumValues<AptMode>(), value) { mode = it }
|
||||
|
||||
Reference in New Issue
Block a user