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:
@@ -30,11 +30,9 @@ import org.jetbrains.org.objectweb.asm.*
|
|||||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import java.util.HashSet
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import org.jetbrains.jps.incremental.storage.StorageOwner
|
import org.jetbrains.jps.incremental.storage.StorageOwner
|
||||||
import org.jetbrains.jps.builders.storage.StorageProvider
|
import org.jetbrains.jps.builders.storage.StorageProvider
|
||||||
@@ -137,41 +135,34 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
|||||||
dirtyOutputClassesMap.notDirty(className.getInternalName())
|
dirtyOutputClassesMap.notDirty(className.getInternalName())
|
||||||
sourceFiles.forEach { sourceToClassesMap.addSourceToClass(it, className) }
|
sourceFiles.forEach { sourceToClassesMap.addSourceToClass(it, className) }
|
||||||
|
|
||||||
val annotationDataEncoded = header.annotationData
|
return when {
|
||||||
if (annotationDataEncoded != null) {
|
header.isCompatiblePackageFacadeKind() ->
|
||||||
val data = BitEncoding.decodeBytes(annotationDataEncoded)
|
getRecompilationDecision(
|
||||||
return when {
|
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData)),
|
||||||
header.isCompatiblePackageFacadeKind() ->
|
constantsChanged = false,
|
||||||
getRecompilationDecision(
|
inlinesChanged = false
|
||||||
protoChanged = protoMap.put(className, data),
|
)
|
||||||
constantsChanged = false,
|
header.isCompatibleClassKind() ->
|
||||||
inlinesChanged = false
|
getRecompilationDecision(
|
||||||
)
|
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData)),
|
||||||
header.isCompatibleClassKind() ->
|
constantsChanged = constantsMap.process(className, fileBytes),
|
||||||
getRecompilationDecision(
|
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||||
protoChanged = protoMap.put(className, data),
|
)
|
||||||
constantsChanged = constantsMap.process(className, fileBytes),
|
header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART -> {
|
||||||
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
assert(sourceFiles.size() == 1) { "Package part from several source files: $sourceFiles" }
|
||||||
)
|
|
||||||
else -> {
|
packagePartMap.addPackagePart(className)
|
||||||
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
|
|
||||||
}
|
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 {
|
public fun clearCacheForRemovedClasses(): RecompilationDecision {
|
||||||
|
|||||||
@@ -135,6 +135,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObjectChanged")
|
||||||
|
public void testAnonymousObjectChanged() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/anonymousObjectChanged/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("classInlineFunctionChanged")
|
@TestMetadata("classInlineFunctionChanged")
|
||||||
public void testClassInlineFunctionChanged() throws Exception {
|
public void testClassInlineFunctionChanged() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/classInlineFunctionChanged/");
|
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()
|
||||||
Reference in New Issue
Block a user