Incremental KAPT - analyze classpath changes
Use artifact transforms to capture structure and dependencies of classpath entries. In the KAPT task this information is used to compare previous classpath structure with the current one. Once changed classes are detected, all classes that transitively depend on those are identified, and that set is passed to KAPT invocation. In order to avoid unrelated classpath changes, we record an ABI snapshot of the classpath entry. This snapshot ignores all private members, and @Metadata annotation. #KT-23880
This commit is contained in:
committed by
Alexey Tsvetkov
parent
c85e21d43b
commit
7c78644eb9
+65
@@ -71,4 +71,69 @@ class KaptIncrementalWithAggregatingApt : KaptIncrementalIT() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClasspathChanges() {
|
||||
val project = Project(
|
||||
"incrementalMultiproject",
|
||||
GradleVersionRequired.None
|
||||
).apply {
|
||||
setupWorkingDir()
|
||||
val processorPath = generateProcessor("AGGREGATING")
|
||||
|
||||
projectDir.resolve("app/build.gradle").appendText(
|
||||
"""
|
||||
|
||||
apply plugin: "kotlin-kapt"
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${'$'}kotlin_version"
|
||||
kapt files("${processorPath.invariantSeparatorsPath}")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
projectDir.resolve("lib/build.gradle").appendText(
|
||||
"""
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${'$'}kotlin_version"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
project.build("clean", ":app:build") {
|
||||
assertSuccessful()
|
||||
}
|
||||
|
||||
project.projectFile("A.kt").modify { current ->
|
||||
val lastBrace = current.lastIndexOf("}")
|
||||
current.substring(0, lastBrace) + "fun anotherFun() {}\n }"
|
||||
}
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
|
||||
assertEquals(
|
||||
setOf(
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/AA.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/AAA.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/BB.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/FooUseAKt.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/FooUseBKt.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/FooUseAAKt.java").absolutePath,
|
||||
fileInWorkingDir("app/build/tmp/kapt3/stubs/main/foo/FooUseBBKt.java").absolutePath
|
||||
|
||||
), getProcessedSources(output)
|
||||
)
|
||||
}
|
||||
|
||||
project.projectFile("A.kt").modify { current ->
|
||||
val lastBrace = current.lastIndexOf("}")
|
||||
current.substring(0, lastBrace) + "private fun privateFunction() {}\n }"
|
||||
}
|
||||
project.build("build") {
|
||||
assertSuccessful()
|
||||
assertTrue(getProcessedSources(output).isEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-10
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
@@ -70,13 +71,22 @@ private const val patternApt = "Processing java sources with annotation processo
|
||||
fun getProcessedSources(output: String): Set<String> {
|
||||
val logging = output.lines().single { it.contains(patternApt) }
|
||||
val indexOf = logging.indexOf(patternApt) + patternApt.length
|
||||
return logging.drop(indexOf).split(",").map { it.trim() }.toSet()
|
||||
return logging.drop(indexOf).split(",").map { it.trim() }.filter { !it.isEmpty() }.toSet()
|
||||
}
|
||||
|
||||
fun BaseGradleIT.Project.setupIncrementalAptProject(procType: String) {
|
||||
fun BaseGradleIT.Project.setupIncrementalAptProject(procType: String, buildFile: File = projectDir.resolve("build.gradle")) {
|
||||
setupWorkingDir()
|
||||
val buildFile = projectDir.resolve("build.gradle")
|
||||
val content = buildFile.readText()
|
||||
val processorPath = generateProcessor(procType)
|
||||
|
||||
val updatedContent = content.replace(
|
||||
Regex("^\\s*kapt\\s\"org\\.jetbrain.*$", RegexOption.MULTILINE),
|
||||
" kapt files(\"${processorPath.invariantSeparatorsPath}\")"
|
||||
)
|
||||
buildFile.writeText(updatedContent)
|
||||
}
|
||||
|
||||
fun BaseGradleIT.Project.generateProcessor(procType: String): File {
|
||||
val processorPath = projectDir.resolve("incrementalProcessor.jar")
|
||||
|
||||
ZipOutputStream(processorPath.outputStream()).use {
|
||||
@@ -92,10 +102,5 @@ fun BaseGradleIT.Project.setupIncrementalAptProject(procType: String) {
|
||||
it.write(IncrementalProcessor::class.java.name.toByteArray())
|
||||
it.closeEntry()
|
||||
}
|
||||
|
||||
val updatedContent = content.replace(
|
||||
Regex("^\\s*kapt\\s\"org\\.jetbrain.*$", RegexOption.MULTILINE),
|
||||
" kapt files(\"${processorPath.invariantSeparatorsPath}\")"
|
||||
)
|
||||
buildFile.writeText(updatedContent)
|
||||
}
|
||||
return processorPath
|
||||
}
|
||||
Reference in New Issue
Block a user