From 6a8d0fbd75715bfb7c0706961ce752ba80983db1 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 21 Sep 2015 18:22:14 +0300 Subject: [PATCH] Introduce infrastructure to separate string table from metadata on JVM Nothing especially helpful happens here, this is only a big refactoring introducing a separate string array for the string table, which is currently always empty, but will contain actual strings soon --- .../org/jetbrains/kotlin/codegen/AsmUtil.java | 13 +++++ .../kotlin/codegen/ClosureCodegen.java | 8 +-- .../codegen/ImplementationBodyCodegen.java | 8 +-- .../codegen/MultifileClassPartCodegen.kt | 8 +-- .../kotlin/codegen/PackageCodegen.java | 8 +-- .../kotlin/codegen/PackagePartCodegen.java | 9 +--- .../IncrementalPackageFragmentProvider.kt | 17 ++++--- .../components/IncrementalCache.kt | 6 ++- .../kotlinr/RemoteIncrementalCacheServer.kt | 4 +- .../jetbrains/kotlin/rmi/CompileService.kt | 3 +- .../service/RemoteIncrementalCacheClient.kt | 3 +- .../codegen/KotlinClassAnnotationTest.java | 4 +- .../codegen/KotlinPackageAnnotationTest.java | 8 ++- .../kotlin/load/java/JvmAnnotationNames.java | 1 + .../DeserializedDescriptorResolver.java | 10 ++-- .../kotlin/load/kotlin/JavaClassDataFinder.kt | 7 +-- .../load/kotlin/header/KotlinClassHeader.kt | 1 + ...eadKotlinClassHeaderAnnotationVisitor.java | 49 +++++++++++++------ .../serialization/jvm/JvmProtoBufUtil.kt | 12 ++--- .../kotlin/jvm/internal/KotlinCallable.java | 2 + .../src/kotlin/jvm/internal/KotlinClass.java | 2 + .../kotlin/jvm/internal/KotlinFileFacade.java | 2 + .../jvm/internal/KotlinMultifileClass.java | 2 + .../internal/KotlinMultifileClassPart.java | 2 + .../kotlin/jvm/internal/KotlinPackage.java | 2 + .../stubBuilder/KotlinClsStubBuilder.kt | 11 +++-- .../decompiler/stubBuilder/clsStubBuilding.kt | 3 +- .../textBuilder/DeserializerForDecompiler.kt | 10 ++-- .../textBuilder/DirectoryBasedClassFinder.kt | 13 +++-- .../jps/incremental/IncrementalCacheImpl.kt | 41 ++++++++++------ .../jps/incremental/protoDifferenceUtils.kt | 10 ++-- .../AbstractProtoComparisonTest.kt | 11 +++-- 32 files changed, 177 insertions(+), 113 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index a1847ab7194..f432d7bf2f8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName; import org.jetbrains.kotlin.resolve.jvm.JvmPackage; import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; +import org.jetbrains.kotlin.serialization.jvm.BitEncoding; import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.TypesPackage; @@ -841,6 +842,18 @@ public class AsmUtil { av.visitEnd(); } + public static void writeAnnotationData(@NotNull AnnotationVisitor av, @NotNull byte[] bytes) { + JvmCodegenUtil.writeAbiVersion(av); + AnnotationVisitor data = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); + for (String string : BitEncoding.encodeBytes(bytes)) { + data.visit(null, string); + } + data.visitEnd(); + AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.STRINGS_FIELD_NAME); + // TODO: write the actual string table + strings.visitEnd(); + } + @NotNull public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) { return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index 79ad912e5a7..4f179c112fb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.serialization.DescriptorSerializer; import org.jetbrains.kotlin.serialization.ProtoBuf; -import org.jetbrains.kotlin.serialization.jvm.BitEncoding; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.expressions.OperatorConventions; import org.jetbrains.kotlin.utils.UtilsPackage; @@ -231,12 +230,7 @@ public class ClosureCodegen extends MemberCodegen { ProtoBuf.Callable callableProto = serializer.callableProto(funDescriptor).build(); AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CALLABLE), true); - JvmCodegenUtil.writeAbiVersion(av); - AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); - for (String string : BitEncoding.encodeBytes(serializer.serialize(callableProto))) { - array.visit(null, string); - } - array.visitEnd(); + writeAnnotationData(av, serializer.serialize(callableProto)); av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 7607e00a4bf..8bfcbf4d641 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -68,7 +68,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver; import org.jetbrains.kotlin.serialization.DescriptorSerializer; import org.jetbrains.kotlin.serialization.ProtoBuf; -import org.jetbrains.kotlin.serialization.jvm.BitEncoding; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.checker.JetTypeChecker; import org.jetbrains.org.objectweb.asm.*; @@ -254,7 +253,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true); - JvmCodegenUtil.writeAbiVersion(av); + writeAnnotationData(av, serializer.serialize(classProto)); if (kind != null) { av.visitEnum( JvmAnnotationNames.KIND_FIELD_NAME, @@ -262,11 +261,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { kind.toString() ); } - AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); - for (String string : BitEncoding.encodeBytes(serializer.serialize(classProto))) { - array.visit(null, string); - } - array.visitEnd(); av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt index 95657fe0428..32a5c11572c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.JetNamedFunction import org.jetbrains.kotlin.psi.JetProperty import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.serialization.DescriptorSerializer -import org.jetbrains.kotlin.serialization.jvm.BitEncoding import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import java.util.* @@ -96,13 +95,8 @@ public class MultifileClassPartCodegen( if (packageProto.memberCount == 0) return val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true) - JvmCodegenUtil.writeAbiVersion(av) + AsmUtil.writeAnnotationData(av, serializer.serialize(packageProto)) av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassFqName.shortName().asString()) - val dataArray = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME) - for (string in BitEncoding.encodeBytes(serializer.serialize(packageProto))) { - dataArray.visit(null, string) - } - dataArray.visitEnd() av.visitEnd() } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java index ef83e470684..204fb2db4e8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegen.java @@ -58,7 +58,6 @@ import org.jetbrains.kotlin.serialization.ProtoBuf; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor; -import org.jetbrains.kotlin.serialization.jvm.BitEncoding; import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.Type; @@ -291,12 +290,7 @@ public class PackageCodegen { ProtoBuf.Package packageProto = serializer.packageProtoWithoutDescriptors().build(); AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true); - JvmCodegenUtil.writeAbiVersion(av); - AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); - for (String string : BitEncoding.encodeBytes(serializer.serialize(packageProto))) { - array.visit(null, string); - } - array.visitEnd(); + AsmUtil.writeAnnotationData(av, serializer.serialize(packageProto)); av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java index 9cc8fa17a41..2ad4b24860e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java @@ -33,7 +33,6 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.serialization.DescriptorSerializer; import org.jetbrains.kotlin.serialization.ProtoBuf; -import org.jetbrains.kotlin.serialization.jvm.BitEncoding; import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.Type; @@ -41,6 +40,7 @@ import java.util.ArrayList; import java.util.List; import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; +import static org.jetbrains.kotlin.codegen.AsmUtil.writeAnnotationData; import static org.jetbrains.org.objectweb.asm.Opcodes.*; public class PackagePartCodegen extends MemberCodegen { @@ -128,12 +128,7 @@ public class PackagePartCodegen extends MemberCodegen { if (packageProto.getMemberCount() == 0) return; AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true); - JvmCodegenUtil.writeAbiVersion(av); - AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); - for (String string : BitEncoding.encodeBytes(serializer.serialize(packageProto))) { - array.visit(null, string); - } - array.visitEnd(); + writeAnnotationData(av, serializer.serialize(packageProto)); av.visitEnd(); } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt index 44c593f6100..bf015c5bf9e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt @@ -117,17 +117,20 @@ public class IncrementalPackageFragmentProvider( allParts.filterNot { it in obsoletePackageParts } } ?: emptyList() - val dataOfPackageParts = actualPackagePartFiles.map { incrementalCache.getPackagePartData(it) }.filterNotNull() + val scopes = actualPackagePartFiles + .map { + incrementalCache.getPackagePartData(it) + } + .filterNotNull() + .map { + IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(it.data, it.strings)) + } - if (dataOfPackageParts.isEmpty()) { + if (scopes.isEmpty()) { JetScope.Empty } else { - val scopes = dataOfPackageParts.map { IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(it)) } - ChainedScope(this, - "Member scope for incremental compilation: union of package parts data", - *scopes.toTypedArray() - ) + ChainedScope(this, "Member scope for incremental compilation: union of package parts data", *scopes.toTypedArray()) } } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCache.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCache.kt index 71e65d08887..f0ebcd5d323 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCache.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCache.kt @@ -16,10 +16,14 @@ package org.jetbrains.kotlin.load.kotlin.incremental.components +import java.io.Serializable + +data class JvmPackagePartProto(val data: ByteArray, val strings: Array) : Serializable + public interface IncrementalCache { public fun getObsoletePackageParts(): Collection - public fun getPackagePartData(fqName: String): ByteArray? + public fun getPackagePartData(fqName: String): JvmPackagePartProto? public fun getModuleMappingData(): ByteArray? diff --git a/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/RemoteIncrementalCacheServer.kt b/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/RemoteIncrementalCacheServer.kt index 9dee971c862..30dc0f1a96f 100644 --- a/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/RemoteIncrementalCacheServer.kt +++ b/compiler/rmi/kotlinr/src/org/jetbrains/kotlin/rmi/kotlinr/RemoteIncrementalCacheServer.kt @@ -17,12 +17,12 @@ package org.jetbrains.kotlin.rmi.kotlinr import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache +import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.rmi.CompileService import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT import java.rmi.server.UnicastRemoteObject - public class RemoteIncrementalCacheServer(val cache: IncrementalCache, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteIncrementalCache { init { @@ -31,7 +31,7 @@ public class RemoteIncrementalCacheServer(val cache: IncrementalCache, port: Int override fun getObsoletePackageParts(): Collection = cache.getObsoletePackageParts() - override fun getPackagePartData(fqName: String): ByteArray? = cache.getPackagePartData(fqName) + override fun getPackagePartData(fqName: String): JvmPackagePartProto? = cache.getPackagePartData(fqName) override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData() diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt index 302d2281c9a..922168ce1b7 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/CompileService.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.rmi import org.jetbrains.kotlin.incremental.components.ScopeKind +import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.modules.TargetId import java.io.Serializable import java.rmi.Remote @@ -34,7 +35,7 @@ public interface CompileService : Remote { public fun getObsoletePackageParts(): Collection @Throws(RemoteException::class) - public fun getPackagePartData(fqName: String): ByteArray? + public fun getPackagePartData(fqName: String): JvmPackagePartProto? @Throws(RemoteException::class) public fun getModuleMappingData(): ByteArray? diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteIncrementalCacheClient.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteIncrementalCacheClient.kt index 0120c038a12..13a68de84d5 100644 --- a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteIncrementalCacheClient.kt +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/RemoteIncrementalCacheClient.kt @@ -17,12 +17,13 @@ package org.jetbrains.kotlin.rmi.service import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache +import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.rmi.CompileService public class RemoteIncrementalCacheClient(val cache: CompileService.RemoteIncrementalCache): IncrementalCache { override fun getObsoletePackageParts(): Collection = cache.getObsoletePackageParts() - override fun getPackagePartData(fqName: String): ByteArray? = cache.getPackagePartData(fqName) + override fun getPackagePartData(fqName: String): JvmPackagePartProto? = cache.getPackagePartData(fqName) override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData() diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinClassAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinClassAnnotationTest.java index c589c7a2a90..68f42826063 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinClassAnnotationTest.java @@ -54,7 +54,9 @@ public class KotlinClassAnnotationTest extends CodegenTestCase { String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinClass, "data"); assertNotNull(data); - ClassData classData = JvmProtoBufUtil.readClassDataFrom(data); + String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinClass, "strings"); + assertNotNull(strings); + ClassData classData = JvmProtoBufUtil.readClassDataFrom(data, strings); Set callableNames = collectCallableNames(classData.getClassProto().getMemberList(), classData.getNameResolver()); assertSameElements(Arrays.asList("foo", "bar"), callableNames); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinPackageAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinPackageAnnotationTest.java index e32d0d03836..43cb171f3d6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinPackageAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinPackageAnnotationTest.java @@ -60,7 +60,9 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase { String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data"); assertNotNull(data); - PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data); + String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "strings"); + assertNotNull(strings); + PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings); Set callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver()); assertEmpty(callableNames); @@ -84,7 +86,9 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase { String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data"); assertNotNull(data); - PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data); + String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "strings"); + assertNotNull(strings); + PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings); Set callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver()); assertSameElements(callableNames, Arrays.asList("foo", "bar")); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index ee335c6aa36..081b2c398b7 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -48,6 +48,7 @@ public final class JvmAnnotationNames { public static final String FILE_PART_CLASS_NAMES_FIELD_NAME = "filePartClassNames"; public static final String MULTIFILE_CLASS_NAME_FIELD_NAME = "multifileClassName"; public static final String DATA_FIELD_NAME = "data"; + public static final String STRINGS_FIELD_NAME = "strings"; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); public static final Name TARGET_ANNOTATION_MEMBER_NAME = Name.identifier("allowedTargets"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java index 4f8642c2368..1dd78a0bfa8 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.java @@ -61,7 +61,9 @@ public final class DeserializedDescriptorResolver { public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) { String[] data = readData(kotlinClass, KOTLIN_CLASS); if (data != null) { - ClassData classData = JvmProtoBufUtil.readClassDataFrom(data); + String[] strings = kotlinClass.getClassHeader().getStrings(); + assert strings != null : "String table not found in " + kotlinClass; + ClassData classData = JvmProtoBufUtil.readClassDataFrom(data, strings); KotlinJvmBinarySourceElement sourceElement = new KotlinJvmBinarySourceElement(kotlinClass); return components.getClassDeserializer().deserializeClass( kotlinClass.getClassId(), @@ -75,13 +77,15 @@ public final class DeserializedDescriptorResolver { public JetScope createKotlinPackagePartScope(@NotNull PackageFragmentDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) { String[] data = readData(kotlinClass, KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART); if (data != null) { - //all classes are included in java scope - PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data); + String[] strings = kotlinClass.getClassHeader().getStrings(); + assert strings != null : "String table not found in " + kotlinClass; + PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings); return new DeserializedPackageMemberScope( descriptor, packageData.getPackageProto(), packageData.getNameResolver(), components, new Function0>() { @Override public Collection invoke() { + // All classes are included into Java scope return Collections.emptyList(); } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt index 717f7146b7a..0dd123e521d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt @@ -27,11 +27,12 @@ public class JavaClassDataFinder( ) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassDataWithSource? { val kotlinJvmBinaryClass = kotlinClassFinder.findKotlinClass(classId) ?: return null - assert(kotlinJvmBinaryClass.getClassId() == classId) { - "Class with incorrect id found: expected $classId, actual ${kotlinJvmBinaryClass.getClassId()}" + assert(kotlinJvmBinaryClass.classId == classId) { + "Class with incorrect id found: expected $classId, actual ${kotlinJvmBinaryClass.classId}" } val data = deserializedDescriptorResolver.readData(kotlinJvmBinaryClass, DeserializedDescriptorResolver.KOTLIN_CLASS) ?: return null - val classData = JvmProtoBufUtil.readClassDataFrom(data) + val strings = kotlinJvmBinaryClass.classHeader.strings ?: error("String table not found in $kotlinJvmBinaryClass") + val classData = JvmProtoBufUtil.readClassDataFrom(data, strings) return ClassDataWithSource(classData, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass)) } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt index b715612b7e9..3e10999ce98 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt @@ -25,6 +25,7 @@ public class KotlinClassHeader( public val kind: KotlinClassHeader.Kind, public val version: BinaryVersion, public val annotationData: Array?, + public val strings: Array?, public val classKind: KotlinClass.Kind?, public val syntheticClassKind: KotlinSyntheticClass.Kind?, public val filePartClassNames: Array?, diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index 183b88b53ec..921241b4964 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -64,6 +64,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private String multifileClassName = null; private String[] filePartClassNames = null; private String[] annotationData = null; + private String[] strings = null; private KotlinClassHeader.Kind headerKind = null; private KotlinClass.Kind classKind = null; private KotlinSyntheticClass.Kind syntheticClassKind = null; @@ -80,7 +81,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } if (!AbiVersionUtil.isAbiVersionCompatible(version)) { - return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind, null, null); + return new KotlinClassHeader(headerKind, version, null, strings, classKind, syntheticClassKind, null, null); } if (shouldHaveData() && annotationData == null) { @@ -89,7 +90,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor return null; } - return new KotlinClassHeader(headerKind, version, annotationData, classKind, syntheticClassKind, filePartClassNames, multifileClassName); + return new KotlinClassHeader( + headerKind, version, annotationData, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName + ); } private boolean shouldHaveData() { @@ -171,10 +174,14 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Override @Nullable public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) { - if (name.asString().equals(DATA_FIELD_NAME)) { + String string = name.asString(); + if (DATA_FIELD_NAME.equals(string)) { return dataArrayVisitor(); } - else if (name.asString().equals(FILE_PART_CLASS_NAMES_FIELD_NAME)) { + else if (STRINGS_FIELD_NAME.equals(string)) { + return stringsArrayVisitor(); + } + else if (FILE_PART_CLASS_NAMES_FIELD_NAME.equals(string)) { return filePartClassNamesVisitor(); } else { @@ -186,12 +193,32 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private AnnotationArrayArgumentVisitor filePartClassNamesVisitor() { return new CollectStringArrayAnnotationVisitor() { @Override - protected void visitEnd(String[] data) { + protected void visitEnd(@NotNull String[] data) { filePartClassNames = data; } }; } + @NotNull + private AnnotationArrayArgumentVisitor dataArrayVisitor() { + return new CollectStringArrayAnnotationVisitor() { + @Override + protected void visitEnd(@NotNull String[] data) { + annotationData = data; + } + }; + } + + @NotNull + private AnnotationArrayArgumentVisitor stringsArrayVisitor() { + return new CollectStringArrayAnnotationVisitor() { + @Override + protected void visitEnd(@NotNull String[] data) { + strings = data; + } + }; + } + @Override public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) { } @@ -202,16 +229,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor return null; } - @NotNull - private AnnotationArrayArgumentVisitor dataArrayVisitor() { - return new CollectStringArrayAnnotationVisitor() { - @Override - protected void visitEnd(String[] data) { - annotationData = data; - } - }; - } - @Override public void visitEnd() { } @@ -240,7 +257,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor visitEnd(strings.toArray(new String[strings.size()])); } - protected abstract void visitEnd(String[] data); + protected abstract void visitEnd(@NotNull String[] data); } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt index 94021decafc..54c626c67be 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt @@ -31,11 +31,11 @@ public object JvmProtoBufUtil { } @JvmStatic - public fun readClassDataFrom(data: Array): ClassData = - readClassDataFrom(BitEncoding.decodeBytes(data)) + public fun readClassDataFrom(data: Array, strings: Array): ClassData = + readClassDataFrom(BitEncoding.decodeBytes(data), strings) @JvmStatic - public fun readClassDataFrom(bytes: ByteArray): ClassData { + public fun readClassDataFrom(bytes: ByteArray, strings: Array): ClassData { val input = ByteArrayInputStream(bytes) val nameResolver = NameResolverImpl.read(input) val classProto = ProtoBuf.Class.parseFrom(input, EXTENSION_REGISTRY) @@ -43,11 +43,11 @@ public object JvmProtoBufUtil { } @JvmStatic - public fun readPackageDataFrom(data: Array): PackageData = - readPackageDataFrom(BitEncoding.decodeBytes(data)) + public fun readPackageDataFrom(data: Array, strings: Array): PackageData = + readPackageDataFrom(BitEncoding.decodeBytes(data), strings) @JvmStatic - public fun readPackageDataFrom(bytes: ByteArray): PackageData { + public fun readPackageDataFrom(bytes: ByteArray, strings: Array): PackageData { val input = ByteArrayInputStream(bytes) val nameResolver = NameResolverImpl.read(input) val packageProto = ProtoBuf.Package.parseFrom(input, EXTENSION_REGISTRY) diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinCallable.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinCallable.java index d801e024d72..8355dcff95a 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinCallable.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinCallable.java @@ -30,4 +30,6 @@ public @interface KotlinCallable { int[] version() default {}; String[] data(); + + String[] strings(); } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java index 638aec43330..77270d3e02b 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java @@ -33,6 +33,8 @@ public @interface KotlinClass { String[] data(); + String[] strings(); + enum Kind { CLASS, diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinFileFacade.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinFileFacade.java index 2ec82394047..7901f23e1c2 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinFileFacade.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinFileFacade.java @@ -30,4 +30,6 @@ public @interface KotlinFileFacade { int[] version() default {}; String[] data(); + + String[] strings(); } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClass.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClass.java index a36a33b1acb..bcdd6780804 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClass.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClass.java @@ -30,4 +30,6 @@ public @interface KotlinMultifileClass { int[] version() default {}; String[] filePartClassNames(); + + String[] strings(); } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClassPart.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClassPart.java index adff486377c..c8cdd3ecbe2 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClassPart.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinMultifileClassPart.java @@ -32,4 +32,6 @@ public @interface KotlinMultifileClassPart { String multifileClassName(); String[] data(); + + String[] strings(); } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackage.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackage.java index edb1977aa7d..1b4c5824cf6 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackage.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackage.java @@ -30,4 +30,6 @@ public @interface KotlinPackage { int[] version() default {}; String[] data(); + + String[] strings(); } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt index c28b2e68657..997e8179139 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt @@ -70,20 +70,25 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() { LOG.error("Corrupted kotlin header for file ${file.getName()}") return null } + val strings = header.strings + if (strings == null) { + LOG.error("String table not found in file ${file.getName()}") + return null + } return when { header.isCompatiblePackageFacadeKind() -> { - val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData) + val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName) createPackageFacadeStub(packageProto, packageFqName, context) } header.isCompatibleClassKind() -> { if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null - val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData) + val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName) createTopLevelClassStub(classId, classProto, context) } header.isCompatibleFileFacadeKind() -> { - val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData) + val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName) createFileFacadeStub(packageProto, classId.asSingleFqName(), context) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt index 6f4c41ca989..8009d1ff1bb 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt @@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinFileStubForIde import org.jetbrains.kotlin.lexer.JetModifierKeywordToken import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -87,7 +86,7 @@ fun createMultifileClassStub( val multifileClassContainer = ProtoContainer(null, packageFqName) for (partFile in partFiles) { val partHeader = partFile.classHeader - val partData = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!) + val partData = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!, partHeader.strings!!) val partContext = components.createContext(partData.nameResolver, packageFqName) for (partMember in partData.packageProto.memberList) { createCallableStub(fileStub, partMember, partContext, multifileClassContainer) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompiler.kt index e5cb018ddab..7f1797eb33d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DeserializerForDecompiler.kt @@ -62,12 +62,14 @@ public class DeserializerForDecompiler( "Was called for $facadeFqName; only members of $directoryPackageFqName package are expected." } val binaryClassForPackageClass = classFinder.findKotlinClass(ClassId.topLevel(facadeFqName)) - val annotationData = binaryClassForPackageClass?.classHeader?.annotationData - if (annotationData == null) { - LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.classId}") + val header = binaryClassForPackageClass?.classHeader + val annotationData = header?.annotationData + val strings = header?.strings + if (annotationData == null || strings == null) { + LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.getClassId()}") return emptyList() } - val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData) + val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) val membersScope = DeserializedPackageMemberScope( createDummyPackageFragment(packageFqName), packageProto, nameResolver, deserializationComponents ) { emptyList() } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DirectoryBasedClassFinder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DirectoryBasedClassFinder.kt index acb14260aec..881161651fe 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DirectoryBasedClassFinder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/textBuilder/DirectoryBasedClassFinder.kt @@ -73,14 +73,19 @@ class DirectoryBasedDataFinder( ) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassDataWithSource? { val binaryClass = classFinder.findKotlinClass(classId) ?: return null - val data = binaryClass.getClassHeader().annotationData + val classHeader = binaryClass.classHeader + val data = classHeader.annotationData if (data == null) { - log.error("Annotation data missing for ${binaryClass.getClassId()}") + log.error("Annotation data missing for ${binaryClass.classId}") + return null + } + val strings = classHeader.strings + if (strings == null) { + log.error("String table not found in class ${binaryClass.classId}") return null } - val classData = JvmProtoBufUtil.readClassDataFrom(data) - return ClassDataWithSource(classData) + return ClassDataWithSource(JvmProtoBufUtil.readClassDataFrom(data, strings)) } } diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt index 8bfa18534b3..b9f97d84ddc 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache +import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName.byInternalName import org.jetbrains.kotlin.serialization.jvm.BitEncoding @@ -167,7 +168,7 @@ public class IncrementalCacheImpl( public fun saveModuleMappingToCache(sourceFiles: Collection, file: File): ChangesInfo { val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME) - protoMap.process(jvmClassName, file.readBytes(), isPackage = false, checkChangesIsOpenPart = false) + protoMap.process(jvmClassName, file.readBytes(), emptyArray(), isPackage = false, checkChangesIsOpenPart = false) dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME) sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) } return ChangesInfo.NO_CHANGES @@ -249,8 +250,10 @@ public class IncrementalCacheImpl( return obsoletePackageParts } - override fun getPackagePartData(fqName: String): ByteArray? { - return protoMap[JvmClassName.byInternalName(fqName)]?.bytes + override fun getPackagePartData(fqName: String): JvmPackagePartProto? { + return protoMap[JvmClassName.byInternalName(fqName)]?.let { value -> + JvmPackagePartProto(value.bytes, value.strings) + } } override fun getModuleMappingData(): ByteArray? { @@ -275,19 +278,24 @@ public class IncrementalCacheImpl( public fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean, checkChangesIsOpenPart: Boolean = true): ChangesInfo { val header = kotlinClass.classHeader val bytes = BitEncoding.decodeBytes(header.annotationData!!) - return put(kotlinClass.className, bytes, isPackage, checkChangesIsOpenPart) + return put(kotlinClass.className, bytes, header.strings!!, isPackage, checkChangesIsOpenPart) } - public fun process(className: JvmClassName, data: ByteArray, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo { - return put(className, data, isPackage, checkChangesIsOpenPart) + public fun process(className: JvmClassName, data: ByteArray, strings: Array, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo { + return put(className, data, strings, isPackage, checkChangesIsOpenPart) } - private fun put(className: JvmClassName, bytes: ByteArray, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo { + private fun put( + className: JvmClassName, bytes: ByteArray, strings: Array, isPackage: Boolean, checkChangesIsOpenPart: Boolean + ): ChangesInfo { val key = className.internalName val oldData = storage[key] - val data = ProtoMapValue(isPackage, bytes) + val data = ProtoMapValue(isPackage, bytes, strings) - if (oldData == null || !Arrays.equals(bytes, oldData.bytes) || isPackage != oldData.isPackageFacade) { + if (oldData == null || + !Arrays.equals(bytes, oldData.bytes) || + !Arrays.equals(strings, oldData.strings) || + isPackage != oldData.isPackageFacade) { storage[key] = data } @@ -757,14 +765,19 @@ private object ProtoMapValueExternalizer : DataExternalizer { out.writeBoolean(value.isPackageFacade) out.writeInt(value.bytes.size()) out.write(value.bytes) + out.writeInt(value.strings.size()) + for (string in value.strings) { + out.writeUTF(string) + } } override fun read(`in`: DataInput): ProtoMapValue { val isPackageFacade = `in`.readBoolean() - val length = `in`.readInt() - val buf = ByteArray(length) - `in`.readFully(buf) - return ProtoMapValue(isPackageFacade, buf) + val bytesLength = `in`.readInt() + val bytes = ByteArray(bytesLength) + `in`.readFully(bytes, 0, bytesLength) + val stringsLength = `in`.readInt() + val strings = Array(stringsLength) { `in`.readUTF() } + return ProtoMapValue(isPackageFacade, bytes, strings) } } - diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/protoDifferenceUtils.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/protoDifferenceUtils.kt index 7bc06f13708..4a1508b3c38 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/protoDifferenceUtils.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/protoDifferenceUtils.kt @@ -31,7 +31,7 @@ public sealed class DifferenceKind() { public class MEMBERS(val names: Collection): DifferenceKind() } -data class ProtoMapValue(val isPackageFacade: Boolean, val bytes: ByteArray) +data class ProtoMapValue(val isPackageFacade: Boolean, val bytes: ByteArray, val strings: Array) public fun difference(oldData: ProtoMapValue, newData: ProtoMapValue): DifferenceKind { if (oldData.isPackageFacade != newData.isPackageFacade) return DifferenceKind.CLASS_SIGNATURE @@ -127,8 +127,8 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot ) } - val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData.bytes) - val newClassData = JvmProtoBufUtil.readClassDataFrom(newData.bytes) + val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData.bytes, oldData.strings) + val newClassData = JvmProtoBufUtil.readClassDataFrom(newData.bytes, newData.strings) val oldProto = oldClassData.classProto val newProto = newClassData.classProto @@ -217,8 +217,8 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot } private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newData: ProtoMapValue) : DifferenceCalculator() { - val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData.bytes) - val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData.bytes) + val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData.bytes, oldData.strings) + val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData.bytes, newData.strings) val oldProto = oldPackageData.packageProto val newProto = newPackageData.packageProto diff --git a/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt b/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt index 027be2715da..ce42b21f41b 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt +++ b/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.test.JetTestUtils import org.jetbrains.kotlin.test.MockLibraryUtil import org.jetbrains.kotlin.utils.Printer import java.io.File -import kotlin.test.assertEquals public abstract class AbstractProtoComparisonTest : UsefulTestCase() { @@ -85,8 +84,14 @@ public abstract class AbstractProtoComparisonTest : UsefulTestCase() { val oldProtoBytes = BitEncoding.decodeBytes(oldClassHeader.annotationData!!) val newProtoBytes = BitEncoding.decodeBytes(newClassHeader.annotationData!!) - val oldProto = ProtoMapValue(oldClassHeader.isCompatiblePackageFacadeKind() || oldClassHeader.isCompatibleFileFacadeKind(), oldProtoBytes) - val newProto = ProtoMapValue(newClassHeader.isCompatiblePackageFacadeKind() || newClassHeader.isCompatibleFileFacadeKind(), newProtoBytes) + val oldProto = ProtoMapValue( + oldClassHeader.isCompatiblePackageFacadeKind() || oldClassHeader.isCompatibleFileFacadeKind(), + oldProtoBytes, oldClassHeader.strings!! + ) + val newProto = ProtoMapValue( + newClassHeader.isCompatiblePackageFacadeKind() || newClassHeader.isCompatibleFileFacadeKind(), + newProtoBytes, newClassHeader.strings!! + ) val diff = when { newClassHeader.isCompatiblePackageFacadeKind(), newClassHeader.isCompatibleClassKind(), newClassHeader.isCompatibleFileFacadeKind() ->