Test incremental facade to class conversion and vice versa

This commit is contained in:
Alexey Tsvetkov
2016-01-14 15:58:58 +03:00
parent 94d4dae1fe
commit 9bb876e6da
32 changed files with 239 additions and 13 deletions
@@ -84,8 +84,8 @@ open class IncrementalCacheImpl(
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
private val multifileClassFacadeMap = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
private val multifileClassPartMap = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
private val subtypesMap = registerExperimentalMap(SubtypesMap(SUBTYPES.storageFile))
@@ -160,7 +160,12 @@ open class IncrementalCacheImpl(
KotlinClassHeader.Kind.MULTIFILE_CLASS -> {
val partNames = kotlinClass.classHeader.data?.toList()
?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}")
multifileClassFacadeMap.add(className, partNames)
multifileFacadeToParts[className] = partNames
// When a class is replaced with a facade with the same name,
// the class' proto wouldn't ever be deleted,
// because we don't write proto for multifile facades.
// As a workaround we can remove proto values for multifile facades.
protoMap.remove(className)
// TODO NO_CHANGES? (delegates only)
constantsMap.process(kotlinClass) +
@@ -169,7 +174,7 @@ open class IncrementalCacheImpl(
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
assert(sourceFiles.size == 1) { "Multifile class part from several source files: $sourceFiles" }
packagePartMap.addPackagePart(className)
multifileClassPartMap.add(className.internalName, header.multifileClassName!!)
partToMultifileFacade.set(className.internalName, header.multifileClassName!!)
protoMap.process(kotlinClass, isPackage = true) +
constantsMap.process(kotlinClass) +
@@ -254,11 +259,31 @@ open class IncrementalCacheImpl(
info + newInfo
}
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
for (dirtyClass in dirtyClasses) {
val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue
val facadeClassName = JvmClassName.byInternalName(facade)
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
removedParts.add(dirtyClass.internalName)
}
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
val allParts = multifileFacadeToParts[facade.internalName] ?: continue
val notRemovedParts = allParts.filter { it !in removedParts }
if (notRemovedParts.isEmpty()) {
multifileFacadeToParts.remove(facade)
}
else {
multifileFacadeToParts[facade] = notRemovedParts
}
}
dirtyClasses.forEach {
protoMap.remove(it)
packagePartMap.remove(it)
multifileClassFacadeMap.remove(it)
multifileClassPartMap.remove(it)
multifileFacadeToParts.remove(it)
partToMultifileFacade.remove(it)
constantsMap.remove(it)
}
@@ -289,7 +314,7 @@ open class IncrementalCacheImpl(
override fun getObsoleteMultifileClasses(): Collection<String> {
val obsoleteMultifileClasses = linkedSetOf<String>()
for (dirtyClass in dirtyOutputClassesMap.getDirtyOutputClasses()) {
val dirtyFacade = multifileClassPartMap.getFacadeName(dirtyClass) ?: continue
val dirtyFacade = partToMultifileFacade.get(dirtyClass) ?: continue
obsoleteMultifileClasses.add(dirtyFacade)
}
KotlinBuilder.LOG.debug("Obsolete multifile class facades: $obsoleteMultifileClasses")
@@ -297,12 +322,12 @@ open class IncrementalCacheImpl(
}
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
val partNames = multifileClassFacadeMap.getMultifileClassParts(facadeInternalName) ?: return null
val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null
return partNames.filter { !dirtyOutputClassesMap.isDirty(it) }
}
override fun getMultifileFacade(partInternalName: String): String? {
return multifileClassPartMap.getFacadeName(partInternalName)
return partToMultifileFacade.get(partInternalName)
}
override fun getModuleMappingData(): ByteArray? {
@@ -443,11 +468,11 @@ open class IncrementalCacheImpl(
}
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
fun add(facadeName: JvmClassName, partNames: Collection<String>) {
operator fun set(facadeName: JvmClassName, partNames: Collection<String>) {
storage[facadeName.internalName] = partNames
}
fun getMultifileClassParts(facadeName: String): Collection<String>? = storage[facadeName]
operator fun get(facadeName: String): Collection<String>? = storage[facadeName]
fun remove(className: JvmClassName) {
storage.remove(className.internalName)
@@ -457,11 +482,11 @@ open class IncrementalCacheImpl(
}
private inner class MultifileClassPartMap(storageFile: File) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE) {
fun add(partName: String, facadeName: String) {
fun set(partName: String, facadeName: String) {
storage[partName] = facadeName
}
fun getFacadeName(partName: String): String? {
fun get(partName: String): String? {
return storage.get(partName)
}
@@ -1069,6 +1069,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
doTest(fileName);
}
@TestMetadata("classToPackageFacade")
public void testClassToPackageFacade() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/classToPackageFacade/");
doTest(fileName);
}
@TestMetadata("constructorVisibilityChanged")
public void testConstructorVisibilityChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/constructorVisibilityChanged/");
@@ -1153,6 +1159,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
doTest(fileName);
}
@TestMetadata("packageFacadeToClass")
public void testPackageFacadeToClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/packageFacadeToClass/");
doTest(fileName);
}
@TestMetadata("propertyNullabilityChanged")
public void testPropertyNullabilityChanged() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/propertyNullabilityChanged/");
@@ -0,0 +1,11 @@
open class A {
companion object {
@JvmStatic
fun f() {}
@JvmStatic
fun g() {}
}
fun h() {}
}
@@ -0,0 +1,3 @@
class AChild : A() {
fun j() {}
}
@@ -0,0 +1,3 @@
class AChild {
fun j() {}
}
@@ -0,0 +1,4 @@
@file:JvmName("A")
@file:JvmMultifileClass
fun f() {}
@@ -0,0 +1,4 @@
@file:JvmName("A")
@file:JvmMultifileClass
fun g() {}
@@ -0,0 +1,53 @@
Cleaning output files:
out/production/module/A$Companion.class
out/production/module/A.class
End of files
Compiling files:
src/APartF.kt
src/APartG.kt
End of files
Cleaning output files:
out/production/module/AChild.class
out/production/module/GetAKt.class
out/production/module/META-INF/module.kotlin_module
out/production/module/UseFKt.class
out/production/module/UseGKt.class
out/production/module/UseHKt.class
End of files
Compiling files:
src/AChild.kt
src/getA.kt
src/useF.kt
src/useG.kt
src/useH.kt
End of files
COMPILATION FAILED
Unresolved reference: A
Unresolved reference: A
Unresolved reference: A
Unresolved reference: A
Cleaning output files:
out/production/module/A.class
End of files
Cleaning output files:
out/production/module/A__APartFKt.class
out/production/module/A__APartGKt.class
End of files
Compiling files:
src/AChild.kt
src/APartF.kt
src/APartG.kt
src/useF.kt
src/useG.kt
End of files
Cleaning output files:
out/production/module/GetAChildKt.class
out/production/module/META-INF/module.kotlin_module
out/production/module/UseJKt.class
End of files
Compiling files:
src/getAChild.kt
src/useJ.kt
End of files
@@ -0,0 +1 @@
fun getA() = A()
@@ -0,0 +1 @@
fun getAChild() = AChild()
@@ -0,0 +1,3 @@
fun useF() {
A.f()
}
@@ -0,0 +1,3 @@
fun useF() {
f()
}
@@ -0,0 +1,3 @@
fun useG() {
A.g()
}
@@ -0,0 +1,3 @@
fun useG() {
g()
}
@@ -0,0 +1,3 @@
fun useH() {
getA().h()
}
@@ -0,0 +1,3 @@
fun useJ() {
getAChild().j()
}
@@ -0,0 +1,9 @@
class A {
companion object {
@JvmStatic
fun f() {}
@JvmStatic
fun g() {}
}
}
@@ -0,0 +1,5 @@
class AA {
companion object {
fun f() {}
}
}
@@ -0,0 +1,4 @@
@file:JvmName("A")
@file:JvmMultifileClass
fun f() {}
@@ -0,0 +1,4 @@
@file:JvmName("A")
@file:JvmMultifileClass
fun g() {}
@@ -0,0 +1,9 @@
class A {
companion object {
@JvmStatic
fun f() {}
@JvmStatic
fun g() {}
}
}
@@ -0,0 +1,5 @@
class UseFJava {
void doUse() {
A.f();
}
}
@@ -0,0 +1,40 @@
Cleaning output files:
out/production/module/A.class
out/production/module/A__APartFKt.class
out/production/module/META-INF/module.kotlin_module
End of files
Cleaning output files:
out/production/module/A__APartGKt.class
End of files
Compiling files:
src/A.kt
End of files
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/UseFJava.class
out/production/module/UseFKt.class
out/production/module/UseGKt.class
End of files
Compiling files:
src/useF.kt
src/useG.kt
End of files
COMPILATION FAILED
Unresolved reference: f
Unresolved reference: g
Cleaning output files:
out/production/module/A.class
End of files
Cleaning output files:
out/production/module/A$Companion.class
End of files
Compiling files:
src/A.kt
src/useF.kt
src/useG.kt
End of files
Compiling files:
src/UseFJava.java
End of files
@@ -0,0 +1,3 @@
fun useAA() {
AA.f()
}
@@ -0,0 +1,3 @@
fun useF() {
f()
}
@@ -0,0 +1,3 @@
fun useF() {
A.f()
}
@@ -0,0 +1,3 @@
fun useG() {
g()
}
@@ -0,0 +1,3 @@
fun useG() {
A.g()
}