KT-41456: Incremental KAPT - represent source and class file structure differently

When storing source information needed for type analysis, store
.java file and .class file information separately. This is because
for class files only declared typed is needed.

Tests: updating existing ones

^KT-41456 In Progress
This commit is contained in:
Ivan Gavrilovic
2022-02-19 14:40:17 +00:00
committed by teamcity
parent 570189e833
commit c7e73ce88d
6 changed files with 54 additions and 40 deletions
@@ -26,10 +26,8 @@ class JavaClassCacheManager(val file: File) : Closeable {
// Compilation is fully incremental, record types defined in generated .class files // Compilation is fully incremental, record types defined in generated .class files
processors.forEach { processor -> processors.forEach { processor ->
processor.getGeneratedClassFilesToTypes().forEach { (classFile, type) -> processor.getGeneratedClassFilesToTypes().forEach { (classFile, type) ->
val typeInformation = SourceFileStructure(classFile.toURI()).also { val classFileStructure = ClassFileStructure(classFile.toURI(), type)
it.addDeclaredType(type) javaCache.addSourceStructure(classFileStructure)
}
javaCache.addSourceStructure(typeInformation)
} }
} }
} }
@@ -18,7 +18,7 @@ import java.net.URI
* exists i.e we know all referenced types. For .class files we only know which type is defined in the .class file. * exists i.e we know all referenced types. For .class files we only know which type is defined in the .class file.
*/ */
class JavaClassCache() : Serializable { class JavaClassCache() : Serializable {
private var sourceCache = mutableMapOf<URI, SourceFileStructure>() private var sourceCache = mutableMapOf<URI, JavaFileStructure>()
/** Map from types to files they are mentioned in. */ /** Map from types to files they are mentioned in. */
@Transient @Transient
@@ -27,7 +27,7 @@ class JavaClassCache() : Serializable {
@Transient @Transient
private var nonTransitiveCache = mutableMapOf<String, MutableSet<URI>>() private var nonTransitiveCache = mutableMapOf<String, MutableSet<URI>>()
fun addSourceStructure(sourceStructure: SourceFileStructure) { fun addSourceStructure(sourceStructure: JavaFileStructure) {
sourceCache[sourceStructure.sourceFile] = sourceStructure sourceCache[sourceStructure.sourceFile] = sourceStructure
} }
@@ -35,7 +35,7 @@ class JavaClassCache() : Serializable {
fun getTypesForFiles(files: Collection<File>): Set<String> { fun getTypesForFiles(files: Collection<File>): Set<String> {
val typesFromFiles = HashSet<String>(files.size) val typesFromFiles = HashSet<String>(files.size)
for (file in files) { for (file in files) {
sourceCache[file.toURI()]?.getDeclaredTypes()?.let { sourceCache[file.toURI()]?.declaredTypes?.let {
typesFromFiles.addAll(it) typesFromFiles.addAll(it)
} }
} }
@@ -44,10 +44,11 @@ class JavaClassCache() : Serializable {
private fun readObject(input: ObjectInputStream) { private fun readObject(input: ObjectInputStream) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
sourceCache = input.readObject() as MutableMap<URI, SourceFileStructure> sourceCache = input.readObject() as MutableMap<URI, JavaFileStructure>
dependencyCache = HashMap(sourceCache.size * 4) dependencyCache = HashMap(sourceCache.size * 4)
for (sourceInfo in sourceCache.values) { for (sourceInfo in sourceCache.values) {
if (sourceInfo !is SourceFileStructure) continue
for (mentionedType in sourceInfo.getMentionedTypes()) { for (mentionedType in sourceInfo.getMentionedTypes()) {
val dependants = dependencyCache[mentionedType] ?: mutableSetOf() val dependants = dependencyCache[mentionedType] ?: mutableSetOf()
dependants.add(sourceInfo.sourceFile) dependants.add(sourceInfo.sourceFile)
@@ -62,6 +63,7 @@ class JavaClassCache() : Serializable {
} }
nonTransitiveCache = HashMap(sourceCache.size * 2) nonTransitiveCache = HashMap(sourceCache.size * 2)
for (sourceInfo in sourceCache.values) { for (sourceInfo in sourceCache.values) {
if (sourceInfo !is SourceFileStructure) continue
for (privateType in sourceInfo.getPrivateTypes()) { for (privateType in sourceInfo.getPrivateTypes()) {
val dependants = nonTransitiveCache[privateType] ?: mutableSetOf() val dependants = nonTransitiveCache[privateType] ?: mutableSetOf()
dependants.add(sourceInfo.sourceFile) dependants.add(sourceInfo.sourceFile)
@@ -104,12 +106,12 @@ class JavaClassCache() : Serializable {
fun findImpactedTypes(changedType: String, transitiveDeps: MutableSet<String>, nonTransitiveDeps: MutableSet<String>) { fun findImpactedTypes(changedType: String, transitiveDeps: MutableSet<String>, nonTransitiveDeps: MutableSet<String>) {
dependencyCache[changedType]?.let { impactedSources -> dependencyCache[changedType]?.let { impactedSources ->
impactedSources.forEach { impactedSources.forEach {
transitiveDeps.addAll(sourceCache.getValue(it).getDeclaredTypes()) transitiveDeps.addAll(sourceCache.getValue(it).declaredTypes)
} }
} }
nonTransitiveCache[changedType]?.let { impactedSources -> nonTransitiveCache[changedType]?.let { impactedSources ->
impactedSources.forEach { impactedSources.forEach {
nonTransitiveDeps.addAll(sourceCache.getValue(it).getDeclaredTypes()) nonTransitiveDeps.addAll(sourceCache.getValue(it).declaredTypes)
} }
} }
} }
@@ -139,7 +141,7 @@ class JavaClassCache() : Serializable {
fun getSourceForType(type: String): File { fun getSourceForType(type: String): File {
sourceCache.forEach { (fileUri, typeInfo) -> sourceCache.forEach { (fileUri, typeInfo) ->
if (type in typeInfo.getDeclaredTypes()) { if (type in typeInfo.declaredTypes) {
return File(fileUri) return File(fileUri)
} }
} }
@@ -149,7 +151,7 @@ class JavaClassCache() : Serializable {
fun invalidateDataForTypes(impactedTypes: MutableSet<String>) { fun invalidateDataForTypes(impactedTypes: MutableSet<String>) {
val allSources = mutableSetOf<URI>() val allSources = mutableSetOf<URI>()
sourceCache.forEach { (fileUri, typeInfo) -> sourceCache.forEach { (fileUri, typeInfo) ->
if (typeInfo.getDeclaredTypes().any { it in impactedTypes }) { if (typeInfo.declaredTypes.any { it in impactedTypes }) {
allSources.add(fileUri) allSources.add(fileUri)
} }
} }
@@ -161,11 +163,23 @@ class JavaClassCache() : Serializable {
private val IGNORE_TYPES = { name: String -> name == "java.lang.Object" } private val IGNORE_TYPES = { name: String -> name == "java.lang.Object" }
class SourceFileStructure( interface JavaFileStructure {
val sourceFile: URI val sourceFile: URI
) : Serializable { val declaredTypes: Set<String>
}
private val declaredTypes: MutableSet<String> = mutableSetOf() class ClassFileStructure(
override val sourceFile: URI,
declaredType: String
) : JavaFileStructure, Serializable {
override val declaredTypes: Set<String> = setOf(declaredType)
}
class SourceFileStructure(
override val sourceFile: URI
) : JavaFileStructure, Serializable {
private val _declaredTypes: MutableSet<String> = mutableSetOf()
private val mentionedTypes: MutableSet<String> = mutableSetOf() private val mentionedTypes: MutableSet<String> = mutableSetOf()
private val privateTypes: MutableSet<String> = mutableSetOf() private val privateTypes: MutableSet<String> = mutableSetOf()
@@ -173,14 +187,14 @@ class SourceFileStructure(
private val mentionedAnnotations: MutableSet<String> = mutableSetOf() private val mentionedAnnotations: MutableSet<String> = mutableSetOf()
private val mentionedConstants: MutableMap<String, MutableSet<String>> = mutableMapOf() private val mentionedConstants: MutableMap<String, MutableSet<String>> = mutableMapOf()
fun getDeclaredTypes(): Set<String> = declaredTypes override val declaredTypes: Set<String> = _declaredTypes
fun getMentionedTypes(): Set<String> = mentionedTypes fun getMentionedTypes(): Set<String> = mentionedTypes
fun getPrivateTypes(): Set<String> = privateTypes fun getPrivateTypes(): Set<String> = privateTypes
fun getMentionedAnnotations(): Set<String> = mentionedAnnotations fun getMentionedAnnotations(): Set<String> = mentionedAnnotations
fun getMentionedConstants(): Map<String, Set<String>> = mentionedConstants fun getMentionedConstants(): Map<String, Set<String>> = mentionedConstants
fun addDeclaredType(declaredType: String) { fun addDeclaredType(declaredType: String) {
declaredTypes.add(declaredType) _declaredTypes.add(declaredType)
} }
fun addMentionedType(mentionedType: String) { fun addMentionedType(mentionedType: String) {
@@ -9,7 +9,6 @@ import com.sun.source.tree.*
import com.sun.source.util.* import com.sun.source.util.*
import com.sun.tools.javac.code.Symbol import com.sun.tools.javac.code.Symbol
import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree
import java.io.File
import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementKind
import javax.lang.model.element.Modifier import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement import javax.lang.model.element.TypeElement
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.kapt.base.test.org.jetbrains.kotlin.kapt3.base.incr
import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager
import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener
import org.jetbrains.kotlin.kapt3.base.incremental.SourceFileStructure
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.BeforeClass import org.junit.BeforeClass
import org.junit.ClassRule import org.junit.ClassRule
@@ -51,9 +52,9 @@ class TestInheritedAnnotation {
@Test @Test
fun testAnnotationInherited() { fun testAnnotationInherited() {
val shouldInheritAnnotation = cache.javaCache.getStructure(MY_TEST_DIR.resolve("ExtendsBase.java"))!! val shouldInheritAnnotation = cache.javaCache.getStructure(MY_TEST_DIR.resolve("ExtendsBase.java"))!! as SourceFileStructure
assertEquals(setOf("test.ExtendsBase"), shouldInheritAnnotation.getDeclaredTypes()) assertEquals(setOf("test.ExtendsBase"), shouldInheritAnnotation.declaredTypes)
assertEquals(setOf("test.InheritableAnnotation"), shouldInheritAnnotation.getMentionedAnnotations()) assertEquals(setOf("test.InheritableAnnotation"), shouldInheritAnnotation.getMentionedAnnotations())
assertEquals(emptySet<String>(), shouldInheritAnnotation.getPrivateTypes()) assertEquals(emptySet<String>(), shouldInheritAnnotation.getPrivateTypes())
assertEquals( assertEquals(
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.kapt.base.test.org.jetbrains.kotlin.kapt3.base.incr
import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager
import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener
import org.jetbrains.kotlin.kapt3.base.incremental.SourceFileStructure
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.BeforeClass import org.junit.BeforeClass
import org.junit.ClassRule import org.junit.ClassRule
@@ -54,9 +55,9 @@ class ReferencedConstantsTest {
@Test @Test
fun testConstantInField() { fun testConstantInField() {
val klassA = cache.javaCache.getStructure(MY_TEST_DIR.resolve("A.java"))!! val klassA = cache.javaCache.getStructure(MY_TEST_DIR.resolve("A.java"))!! as SourceFileStructure
assertEquals(setOf("test.A"), klassA.getDeclaredTypes()) assertEquals(setOf("test.A"), klassA.declaredTypes)
assertEquals(emptySet<String>(), klassA.getMentionedAnnotations()) assertEquals(emptySet<String>(), klassA.getMentionedAnnotations())
assertEquals(emptySet<String>(), klassA.getPrivateTypes()) assertEquals(emptySet<String>(), klassA.getPrivateTypes())
assertEquals(setOf("test.A"), klassA.getMentionedTypes()) assertEquals(setOf("test.A"), klassA.getMentionedTypes())
@@ -70,9 +71,9 @@ class ReferencedConstantsTest {
@Test @Test
fun testConstantInDefaultValue() { fun testConstantInDefaultValue() {
val annotationA = cache.javaCache.getStructure(MY_TEST_DIR.resolve("AnnotationA.java"))!! val annotationA = cache.javaCache.getStructure(MY_TEST_DIR.resolve("AnnotationA.java"))!! as SourceFileStructure
assertEquals(setOf("test.AnnotationA"), annotationA.getDeclaredTypes()) assertEquals(setOf("test.AnnotationA"), annotationA.declaredTypes)
assertEquals(emptySet<String>(), annotationA.getMentionedAnnotations()) assertEquals(emptySet<String>(), annotationA.getMentionedAnnotations())
assertEquals(emptySet<String>(), annotationA.getPrivateTypes()) assertEquals(emptySet<String>(), annotationA.getPrivateTypes())
assertEquals(setOf("test.AnnotationA"), annotationA.getMentionedTypes()) assertEquals(setOf("test.AnnotationA"), annotationA.getMentionedTypes())
@@ -82,9 +83,9 @@ class ReferencedConstantsTest {
@Test @Test
fun testConstantInAnnotationElementValue() { fun testConstantInAnnotationElementValue() {
val annotated = cache.javaCache.getStructure(MY_TEST_DIR.resolve("AnnotatedType.java"))!! val annotated = cache.javaCache.getStructure(MY_TEST_DIR.resolve("AnnotatedType.java"))!! as SourceFileStructure
assertEquals(setOf("test.AnnotatedType"), annotated.getDeclaredTypes()) assertEquals(setOf("test.AnnotatedType"), annotated.declaredTypes)
assertEquals(setOf("test.AnnotationA"), annotated.getMentionedAnnotations()) assertEquals(setOf("test.AnnotationA"), annotated.getMentionedAnnotations())
assertEquals(emptySet<String>(), annotated.getPrivateTypes()) assertEquals(emptySet<String>(), annotated.getPrivateTypes())
assertEquals(setOf("test.AnnotatedType", "test.AnnotationA"), annotated.getMentionedTypes()) assertEquals(setOf("test.AnnotatedType", "test.AnnotationA"), annotated.getMentionedTypes())
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.kapt.base.test.org.jetbrains.kotlin.kapt3.base.incr
import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager import org.jetbrains.kotlin.kapt3.base.incremental.JavaClassCacheManager
import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener import org.jetbrains.kotlin.kapt3.base.incremental.MentionedTypesTaskListener
import org.jetbrains.kotlin.kapt3.base.incremental.SourceFileStructure
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.BeforeClass import org.junit.BeforeClass
import org.junit.ClassRule import org.junit.ClassRule
@@ -53,9 +54,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testEnum() { fun testEnum() {
val myEnum = cache.javaCache.getStructure(MY_TEST_DIR.resolve("MyEnum.java"))!! val myEnum = cache.javaCache.getStructure(MY_TEST_DIR.resolve("MyEnum.java"))!! as SourceFileStructure
assertEquals(setOf("test.MyEnum"), myEnum.getDeclaredTypes()) assertEquals(setOf("test.MyEnum"), myEnum.declaredTypes)
assertEquals(emptySet<String>(), myEnum.getMentionedAnnotations()) assertEquals(emptySet<String>(), myEnum.getMentionedAnnotations())
assertEquals(emptySet<String>(), myEnum.getPrivateTypes()) assertEquals(emptySet<String>(), myEnum.getPrivateTypes())
assertEquals(setOf("test.MyEnum", "test.TypeGeneratedByApt"), myEnum.getMentionedTypes()) assertEquals(setOf("test.MyEnum", "test.TypeGeneratedByApt"), myEnum.getMentionedTypes())
@@ -63,7 +64,7 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testMyNumber() { fun testMyNumber() {
val myNumber = cache.javaCache.getStructure(MY_TEST_DIR.resolve("MyNumber.java"))!! val myNumber = cache.javaCache.getStructure(MY_TEST_DIR.resolve("MyNumber.java"))!! as SourceFileStructure
assertEquals( assertEquals(
setOf( setOf(
@@ -74,7 +75,7 @@ class TestComplexIncrementalAptCache {
"test.TypeUseAnnotation", "test.TypeUseAnnotation",
"test.AnotherTypeUseAnnotation", "test.AnotherTypeUseAnnotation",
"test.ThrowTypeUseAnnotation" "test.ThrowTypeUseAnnotation"
), myNumber.getDeclaredTypes() ), myNumber.declaredTypes
) )
assertEquals( assertEquals(
setOf( setOf(
@@ -116,9 +117,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testAnnotation() { fun testAnnotation() {
val numberAnnotation = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberAnnotation.java"))!! val numberAnnotation = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberAnnotation.java"))!! as SourceFileStructure
assertEquals(setOf("test.NumberAnnotation", "test.BaseAnnotation"), numberAnnotation.getDeclaredTypes()) assertEquals(setOf("test.NumberAnnotation", "test.BaseAnnotation"), numberAnnotation.declaredTypes)
assertEquals(setOf("test.BaseAnnotation"), numberAnnotation.getMentionedAnnotations()) assertEquals(setOf("test.BaseAnnotation"), numberAnnotation.getMentionedAnnotations())
assertEquals(emptySet<String>(), numberAnnotation.getPrivateTypes()) assertEquals(emptySet<String>(), numberAnnotation.getPrivateTypes())
assertEquals( assertEquals(
@@ -134,9 +135,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testNumberException() { fun testNumberException() {
val numberException = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberException.java"))!! val numberException = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberException.java"))!! as SourceFileStructure
assertEquals(setOf("test.NumberException"), numberException.getDeclaredTypes()) assertEquals(setOf("test.NumberException"), numberException.declaredTypes)
assertEquals(emptySet<String>(), numberException.getMentionedAnnotations()) assertEquals(emptySet<String>(), numberException.getMentionedAnnotations())
assertEquals(emptySet<String>(), numberException.getPrivateTypes()) assertEquals(emptySet<String>(), numberException.getPrivateTypes())
assertEquals(setOf("test.NumberException", "java.lang.RuntimeException"), numberException.getMentionedTypes()) assertEquals(setOf("test.NumberException", "java.lang.RuntimeException"), numberException.getMentionedTypes())
@@ -144,9 +145,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testNumberHolder() { fun testNumberHolder() {
val numberHolder = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberHolder.java"))!! val numberHolder = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberHolder.java"))!! as SourceFileStructure
assertEquals(setOf("test.NumberHolder", "test.NumberHolder.MyInnerClass"), numberHolder.getDeclaredTypes()) assertEquals(setOf("test.NumberHolder", "test.NumberHolder.MyInnerClass"), numberHolder.declaredTypes)
assertEquals(setOf("test.NumberAnnotation"), numberHolder.getMentionedAnnotations()) assertEquals(setOf("test.NumberAnnotation"), numberHolder.getMentionedAnnotations())
assertEquals(setOf("test.NumberManager"), numberHolder.getPrivateTypes()) assertEquals(setOf("test.NumberManager"), numberHolder.getPrivateTypes())
assertEquals( assertEquals(
@@ -166,9 +167,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testNumberManager() { fun testNumberManager() {
val numberManager = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberManager.java"))!! val numberManager = cache.javaCache.getStructure(MY_TEST_DIR.resolve("NumberManager.java"))!! as SourceFileStructure
assertEquals(setOf("test.NumberManager"), numberManager.getDeclaredTypes()) assertEquals(setOf("test.NumberManager"), numberManager.declaredTypes)
assertEquals(emptySet<String>(), numberManager.getMentionedAnnotations()) assertEquals(emptySet<String>(), numberManager.getMentionedAnnotations())
assertEquals(setOf("test.MyEnum"), numberManager.getPrivateTypes()) assertEquals(setOf("test.MyEnum"), numberManager.getPrivateTypes())
assertEquals( assertEquals(
@@ -182,9 +183,9 @@ class TestComplexIncrementalAptCache {
@Test @Test
fun testGenericNumber() { fun testGenericNumber() {
val genericNumber = cache.javaCache.getStructure(MY_TEST_DIR.resolve("GenericNumber.java"))!! val genericNumber = cache.javaCache.getStructure(MY_TEST_DIR.resolve("GenericNumber.java"))!! as SourceFileStructure
assertEquals(setOf("test.GenericNumber"), genericNumber.getDeclaredTypes()) assertEquals(setOf("test.GenericNumber"), genericNumber.declaredTypes)
assertEquals(emptySet<String>(), genericNumber.getMentionedAnnotations()) assertEquals(emptySet<String>(), genericNumber.getMentionedAnnotations())
assertEquals(emptySet<String>(), genericNumber.getPrivateTypes()) assertEquals(emptySet<String>(), genericNumber.getPrivateTypes())
assertEquals( assertEquals(