Serialize descriptors for local/anonymous classes on JVM

Reflection needs this information to work for local classes and anonymous
objects

Original commit: 6ce8d6bd2e
This commit is contained in:
Alexander Udalov
2015-02-14 03:27:05 +03:00
parent 52fb79b0be
commit ce38b4c43f
6 changed files with 63 additions and 35 deletions
@@ -30,11 +30,9 @@ import org.jetbrains.org.objectweb.asm.*
import com.intellij.util.io.EnumeratorStringDescriptor
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.util.HashSet
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
import java.util.HashMap
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import com.intellij.openapi.util.io.FileUtil
import java.security.MessageDigest
import org.jetbrains.jps.incremental.storage.StorageOwner
import org.jetbrains.jps.builders.storage.StorageProvider
@@ -137,41 +135,34 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
dirtyOutputClassesMap.notDirty(className.getInternalName())
sourceFiles.forEach { sourceToClassesMap.addSourceToClass(it, className) }
val annotationDataEncoded = header.annotationData
if (annotationDataEncoded != null) {
val data = BitEncoding.decodeBytes(annotationDataEncoded)
return when {
header.isCompatiblePackageFacadeKind() ->
getRecompilationDecision(
protoChanged = protoMap.put(className, data),
constantsChanged = false,
inlinesChanged = false
)
header.isCompatibleClassKind() ->
getRecompilationDecision(
protoChanged = protoMap.put(className, data),
constantsChanged = constantsMap.process(className, fileBytes),
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
)
else -> {
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
}
return when {
header.isCompatiblePackageFacadeKind() ->
getRecompilationDecision(
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData)),
constantsChanged = false,
inlinesChanged = false
)
header.isCompatibleClassKind() ->
getRecompilationDecision(
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData)),
constantsChanged = constantsMap.process(className, fileBytes),
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
)
header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> {
assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" }
packagePartMap.addPackagePart(className)
getRecompilationDecision(
protoChanged = false,
constantsChanged = constantsMap.process(className, fileBytes),
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
)
}
else -> {
DO_NOTHING
}
}
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" }
packagePartMap.addPackagePart(className)
return getRecompilationDecision(
protoChanged = false,
constantsChanged = constantsMap.process(className, fileBytes),
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
)
}
return DO_NOTHING
}
public fun clearCacheForRemovedClasses(): RecompilationDecision {
@@ -135,6 +135,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
doTest(fileName);
}
@TestMetadata("anonymousObjectChanged")
public void testAnonymousObjectChanged() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/anonymousObjectChanged/");
doTest(fileName);
}
@TestMetadata("classInlineFunctionChanged")
public void testClassInlineFunctionChanged() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/classInlineFunctionChanged/");
@@ -0,0 +1,5 @@
package a
fun foo() = object {
fun bar() = ":("
}
@@ -0,0 +1,6 @@
package a
// Signatures in the class "...$main$1" have changed, thus we need to recompile the whole module
fun foo() = object {
fun baz() = ":)"
}
@@ -0,0 +1,15 @@
Cleaning output files:
out/production/module/a/APackage$a$*$foo$1.class
out/production/module/a/APackage$a$*.class
out/production/module/a/APackage.class
End of files
Compiling files:
src/a.kt
End of files
Cleaning output files:
out/production/module/usage/UsagePackage$usage$*.class
out/production/module/usage/UsagePackage.class
End of files
Compiling files:
src/usage.kt
End of files
@@ -0,0 +1,5 @@
package usage
import a.foo
fun bar() = foo()