Kapt3: Avoid annotation processing execution when possible (KT-17620)
Do not execute annotation processing if no stubs (and Java files) were changed since the previous execution.
This commit is contained in:
+29
@@ -74,6 +74,35 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean, val useKapt3:
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testChangeFunctionBodyWithoutChangingSignature() {
|
||||
val project = getProject()
|
||||
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
checkStubUsage()
|
||||
checkGenerated(*annotatedElements)
|
||||
checkNotGenerated("notAnnotatedFun")
|
||||
assertContains("foo.ATest PASSED")
|
||||
}
|
||||
|
||||
val utilKt = project.projectDir.getFileByName("util.kt")
|
||||
utilKt.modify { oldContent ->
|
||||
assert(oldContent.contains("2 * 2 == 4"))
|
||||
oldContent.replace("2 * 2 == 4", "2 * 2 == 5")
|
||||
}
|
||||
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
checkStubUsage()
|
||||
|
||||
if (useKapt3) {
|
||||
assertNotContains(":kaptGenerateStubsKotlin UP-TO-DATE")
|
||||
assertContains(":kaptKotlin UP-TO-DATE")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddAnnotatedElement() {
|
||||
val project = getProject()
|
||||
|
||||
+7
-1
@@ -6,4 +6,10 @@ val valUtil = 0
|
||||
@example.ExampleAnnotation
|
||||
fun funUtil() {}
|
||||
|
||||
fun notAnnotatedFun() {}
|
||||
fun notAnnotatedFun() {}
|
||||
|
||||
fun functionWithBody() {
|
||||
if (2 * 2 == 4) {
|
||||
// All's right
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -68,7 +68,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
File(project.project.buildDir, "tmp/kapt3/classes/$sourceSetName")
|
||||
}
|
||||
|
||||
private val kotlinToKaptTasksMap = mutableMapOf<KotlinCompile, KaptTask>()
|
||||
private val kotlinToKaptGenerateStubsTasksMap = mutableMapOf<KotlinCompile, KaptGenerateStubsTask>()
|
||||
|
||||
override fun isApplicable(project: Project, task: KotlinCompile) = Kapt3GradleSubplugin.isEnabled(project)
|
||||
@@ -158,9 +157,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
override fun getSubpluginKotlinTasks(project: Project, kotlinCompile: KotlinCompile): List<AbstractCompile> {
|
||||
val kaptTask = kotlinToKaptTasksMap[kotlinCompile]
|
||||
val kaptGenerateStubsTask = kotlinToKaptGenerateStubsTasksMap[kotlinCompile]
|
||||
return listOf(kaptTask, kaptGenerateStubsTask).filterNotNull()
|
||||
return if (kaptGenerateStubsTask == null) emptyList() else listOf(kaptGenerateStubsTask)
|
||||
}
|
||||
|
||||
// This method should be called no more than once for each Kapt3SubpluginContext
|
||||
@@ -254,7 +252,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
private fun Kapt3SubpluginContext.createKaptKotlinTask(kaptGenerateStubsTask: KaptGenerateStubsTask) {
|
||||
val kaptTask = project.tasks.create(getKaptTaskName("kapt"), KaptTask::class.java)
|
||||
kaptTask.kotlinCompileTask = kotlinCompile
|
||||
kotlinToKaptTasksMap[kotlinCompile] = kaptTask
|
||||
|
||||
kaptClasspathArtifacts.forEach { kaptTask.pluginOptions.addClasspathEntry(it) }
|
||||
|
||||
@@ -263,6 +260,16 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
kaptTask.mapClasspath { kotlinCompile.classpath }
|
||||
kaptTask.classesDir = classesOutputDir
|
||||
|
||||
kaptTask.mapSource {
|
||||
val sourcesFromKotlinTask = kotlinCompile.source
|
||||
.filter { it.extension == "java" && !kaptTask.isInsideDestinationDirs(it) }
|
||||
.asFileTree
|
||||
|
||||
val stubSources = project.fileTree(kaptTask.stubsDir)
|
||||
|
||||
sourcesFromKotlinTask + stubSources
|
||||
}
|
||||
|
||||
kaptTask.dependsOn(kaptGenerateStubsTask)
|
||||
kotlinCompile.dependsOn(kaptTask)
|
||||
|
||||
|
||||
+1
-6
@@ -18,19 +18,16 @@ package org.jetbrains.kotlin.gradle.internal
|
||||
|
||||
import org.gradle.api.tasks.SourceTask
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.GradleICReporter
|
||||
import org.jetbrains.kotlin.incremental.ICReporter
|
||||
import org.jetbrains.kotlin.incremental.pathsAsStringRelativeTo
|
||||
import java.io.File
|
||||
|
||||
open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
override val sourceRootsContainer = FilteringSourceRootsContainer({ isSourceRootAllowed(it) })
|
||||
override val sourceRootsContainer = FilteringSourceRootsContainer(emptyList(), { isSourceRootAllowed(it) })
|
||||
|
||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||
|
||||
@@ -56,8 +53,6 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
val sourceRoots = kotlinCompileTask.getSourceRoots()
|
||||
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
||||
|
||||
generatedSourcesDir.deleteRecursively()
|
||||
|
||||
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(project.rootProject.projectDir)}" }
|
||||
|
||||
if (allKotlinSources.isEmpty()) {
|
||||
|
||||
+8
-24
@@ -1,7 +1,6 @@
|
||||
package org.jetbrains.kotlin.gradle.internal
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.tasks.SourceTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
@@ -9,33 +8,16 @@ import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
||||
import org.jetbrains.kotlin.gradle.dsl.fillDefaultValues
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
import java.io.File
|
||||
import java.net.URLDecoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
open class KaptTask : AbstractCompile() {
|
||||
private val rawSourceRoots = FilteringSourceRootsContainer({ !it.isInsideDestinationDir() })
|
||||
|
||||
internal val pluginOptions = CompilerPluginOptions()
|
||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||
|
||||
override fun setSource(sources: Any?) {
|
||||
val filteredSources = rawSourceRoots.set(sources)
|
||||
super.setSource(filteredSources)
|
||||
}
|
||||
|
||||
override fun source(vararg sources: Any?): SourceTask? {
|
||||
val filteredSources = rawSourceRoots.add(*sources)
|
||||
return super.source(filteredSources)
|
||||
}
|
||||
|
||||
private fun File.isInsideDestinationDir(): Boolean {
|
||||
return FileUtil.isAncestor(destinationDir, this, /* strict = */ false)
|
||||
fun isInsideDestinationDirs(file: File): Boolean {
|
||||
return FileUtil.isAncestor(destinationDir, file, /* strict = */ false)
|
||||
|| FileUtil.isAncestor(classesDir, file, /* strict = */ false)
|
||||
}
|
||||
|
||||
lateinit var classesDir: File
|
||||
@@ -43,12 +25,14 @@ open class KaptTask : AbstractCompile() {
|
||||
|
||||
@TaskAction
|
||||
override fun compile() {
|
||||
/** Delete everything inside the [destinationDir] (sources output dir) */
|
||||
/** Delete everything inside generated sources and classes output directory
|
||||
* (annotation processing is not incremental) */
|
||||
destinationDir.clearDirectory()
|
||||
|
||||
classesDir.clearDirectory()
|
||||
|
||||
val sourceRoots = SourceRoots.ForJvm.create(getSource(), rawSourceRoots)
|
||||
val sourceRootsFromKotlin = kotlinCompileTask.sourceRootsContainer.sourceRoots
|
||||
val rawSourceRoots = FilteringSourceRootsContainer(sourceRootsFromKotlin, { !isInsideDestinationDirs(it) })
|
||||
val sourceRoots = SourceRoots.ForJvm.create(kotlinCompileTask.source, rawSourceRoots)
|
||||
|
||||
val args = K2JVMCompilerArguments()
|
||||
kotlinCompileTask.setupCompilerArgs(args)
|
||||
|
||||
+5
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.FileTree
|
||||
import org.gradle.api.internal.HasConvention
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
@@ -50,6 +51,10 @@ internal fun AbstractCompile.mapClasspath(fn: () -> FileCollection) {
|
||||
conventionMapping.map("classpath", fn)
|
||||
}
|
||||
|
||||
internal fun AbstractCompile.mapSource(fn: () -> FileTree) {
|
||||
conventionMapping.map("source", fn)
|
||||
}
|
||||
|
||||
internal inline fun <reified T : Any> Any.addConvention(name: String, plugin: T) {
|
||||
(this as HasConvention).convention.plugins[name] = plugin
|
||||
}
|
||||
|
||||
+2
-2
@@ -58,8 +58,8 @@ internal sealed class SourceRoots(val kotlinSourceFiles: List<File>) {
|
||||
}
|
||||
}
|
||||
|
||||
internal class FilteringSourceRootsContainer(val filter: (File) -> Boolean = { true }) {
|
||||
private val mutableSourceRoots = mutableListOf<File>()
|
||||
internal class FilteringSourceRootsContainer(roots: List<File> = emptyList(), val filter: (File) -> Boolean = { true }) {
|
||||
private val mutableSourceRoots = roots.filterTo(mutableListOf(), filter)
|
||||
|
||||
val sourceRoots: List<File>
|
||||
get() = mutableSourceRoots
|
||||
|
||||
Reference in New Issue
Block a user