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
|
@Test
|
||||||
fun testAddAnnotatedElement() {
|
fun testAddAnnotatedElement() {
|
||||||
val project = getProject()
|
val project = getProject()
|
||||||
|
|||||||
+6
@@ -7,3 +7,9 @@ val valUtil = 0
|
|||||||
fun funUtil() {}
|
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")
|
File(project.project.buildDir, "tmp/kapt3/classes/$sourceSetName")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val kotlinToKaptTasksMap = mutableMapOf<KotlinCompile, KaptTask>()
|
|
||||||
private val kotlinToKaptGenerateStubsTasksMap = mutableMapOf<KotlinCompile, KaptGenerateStubsTask>()
|
private val kotlinToKaptGenerateStubsTasksMap = mutableMapOf<KotlinCompile, KaptGenerateStubsTask>()
|
||||||
|
|
||||||
override fun isApplicable(project: Project, task: KotlinCompile) = Kapt3GradleSubplugin.isEnabled(project)
|
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> {
|
override fun getSubpluginKotlinTasks(project: Project, kotlinCompile: KotlinCompile): List<AbstractCompile> {
|
||||||
val kaptTask = kotlinToKaptTasksMap[kotlinCompile]
|
|
||||||
val kaptGenerateStubsTask = kotlinToKaptGenerateStubsTasksMap[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
|
// 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) {
|
private fun Kapt3SubpluginContext.createKaptKotlinTask(kaptGenerateStubsTask: KaptGenerateStubsTask) {
|
||||||
val kaptTask = project.tasks.create(getKaptTaskName("kapt"), KaptTask::class.java)
|
val kaptTask = project.tasks.create(getKaptTaskName("kapt"), KaptTask::class.java)
|
||||||
kaptTask.kotlinCompileTask = kotlinCompile
|
kaptTask.kotlinCompileTask = kotlinCompile
|
||||||
kotlinToKaptTasksMap[kotlinCompile] = kaptTask
|
|
||||||
|
|
||||||
kaptClasspathArtifacts.forEach { kaptTask.pluginOptions.addClasspathEntry(it) }
|
kaptClasspathArtifacts.forEach { kaptTask.pluginOptions.addClasspathEntry(it) }
|
||||||
|
|
||||||
@@ -263,6 +260,16 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
|||||||
kaptTask.mapClasspath { kotlinCompile.classpath }
|
kaptTask.mapClasspath { kotlinCompile.classpath }
|
||||||
kaptTask.classesDir = classesOutputDir
|
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)
|
kaptTask.dependsOn(kaptGenerateStubsTask)
|
||||||
kotlinCompile.dependsOn(kaptTask)
|
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.SourceTask
|
||||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
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.com.intellij.openapi.util.io.FileUtil
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
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 org.jetbrains.kotlin.incremental.pathsAsStringRelativeTo
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class KaptGenerateStubsTask : KotlinCompile() {
|
open class KaptGenerateStubsTask : KotlinCompile() {
|
||||||
override val sourceRootsContainer = FilteringSourceRootsContainer({ isSourceRootAllowed(it) })
|
override val sourceRootsContainer = FilteringSourceRootsContainer(emptyList(), { isSourceRootAllowed(it) })
|
||||||
|
|
||||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||||
|
|
||||||
@@ -56,8 +53,6 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
|||||||
val sourceRoots = kotlinCompileTask.getSourceRoots()
|
val sourceRoots = kotlinCompileTask.getSourceRoots()
|
||||||
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
||||||
|
|
||||||
generatedSourcesDir.deleteRecursively()
|
|
||||||
|
|
||||||
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(project.rootProject.projectDir)}" }
|
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(project.rootProject.projectDir)}" }
|
||||||
|
|
||||||
if (allKotlinSources.isEmpty()) {
|
if (allKotlinSources.isEmpty()) {
|
||||||
|
|||||||
+8
-24
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.kotlin.gradle.internal
|
package org.jetbrains.kotlin.gradle.internal
|
||||||
|
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.tasks.SourceTask
|
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
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.GradleCompilerEnvironment
|
||||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
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.gradle.tasks.*
|
||||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLDecoder
|
|
||||||
import java.nio.charset.Charset
|
|
||||||
|
|
||||||
open class KaptTask : AbstractCompile() {
|
open class KaptTask : AbstractCompile() {
|
||||||
private val rawSourceRoots = FilteringSourceRootsContainer({ !it.isInsideDestinationDir() })
|
|
||||||
|
|
||||||
internal val pluginOptions = CompilerPluginOptions()
|
internal val pluginOptions = CompilerPluginOptions()
|
||||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||||
|
|
||||||
override fun setSource(sources: Any?) {
|
fun isInsideDestinationDirs(file: File): Boolean {
|
||||||
val filteredSources = rawSourceRoots.set(sources)
|
return FileUtil.isAncestor(destinationDir, file, /* strict = */ false)
|
||||||
super.setSource(filteredSources)
|
|| FileUtil.isAncestor(classesDir, file, /* strict = */ false)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var classesDir: File
|
lateinit var classesDir: File
|
||||||
@@ -43,12 +25,14 @@ open class KaptTask : AbstractCompile() {
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
override fun compile() {
|
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()
|
destinationDir.clearDirectory()
|
||||||
|
|
||||||
classesDir.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()
|
val args = K2JVMCompilerArguments()
|
||||||
kotlinCompileTask.setupCompilerArgs(args)
|
kotlinCompileTask.setupCompilerArgs(args)
|
||||||
|
|||||||
+5
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.gradle.plugin
|
|||||||
|
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.FileTree
|
||||||
import org.gradle.api.internal.HasConvention
|
import org.gradle.api.internal.HasConvention
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.plugins.ExtensionAware
|
import org.gradle.api.plugins.ExtensionAware
|
||||||
@@ -50,6 +51,10 @@ internal fun AbstractCompile.mapClasspath(fn: () -> FileCollection) {
|
|||||||
conventionMapping.map("classpath", fn)
|
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) {
|
internal inline fun <reified T : Any> Any.addConvention(name: String, plugin: T) {
|
||||||
(this as HasConvention).convention.plugins[name] = plugin
|
(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 }) {
|
internal class FilteringSourceRootsContainer(roots: List<File> = emptyList(), val filter: (File) -> Boolean = { true }) {
|
||||||
private val mutableSourceRoots = mutableListOf<File>()
|
private val mutableSourceRoots = roots.filterTo(mutableListOf(), filter)
|
||||||
|
|
||||||
val sourceRoots: List<File>
|
val sourceRoots: List<File>
|
||||||
get() = mutableSourceRoots
|
get() = mutableSourceRoots
|
||||||
|
|||||||
Reference in New Issue
Block a user