From 661af854fa148ba92f62970afc4eda3dbfb56fa8 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 30 Dec 2015 17:02:55 +0300 Subject: [PATCH] Drop KotlinClassHeader#filePartClassNames, use 'data' instead --- .../org/jetbrains/kotlin/inline/inlineUtil.kt | 2 +- .../DeserializedDescriptorResolver.java | 2 +- .../load/kotlin/header/KotlinClassHeader.kt | 3 +- ...eadKotlinClassHeaderAnnotationVisitor.java | 26 ++------ .../classFile/ClassFileDecompilerUtil.kt | 4 +- .../DeserializerForClassfileDecompiler.kt | 4 +- .../classFile/KotlinClsStubBuilder.kt | 2 +- .../decompiler/stubBuilder/clsStubBuilding.kt | 6 +- .../jps/incremental/IncrementalCacheImpl.kt | 6 +- .../classFilesComparison.kt | 2 +- .../AbstractProtoComparisonTest.kt | 60 ++++++++----------- 11 files changed, 45 insertions(+), 72 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt index dde4f074de6..8ac0ebde441 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil fun inlineFunctionsJvmNames(bytes: ByteArray): Set { val header = readKotlinHeader(bytes) - val annotationData = header.annotationData + val annotationData = header.data val strings = header.strings if (annotationData == null || strings == null) return emptySet() 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 ba09b6a8a15..d4dd9e16460 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 @@ -119,7 +119,7 @@ public final class DeserializedDescriptorResolver { errorReporter.reportIncompatibleMetadataVersion(kotlinClass.getClassId(), kotlinClass.getLocation(), header.getMetadataVersion()); } else if (expectedKinds.contains(header.getKind())) { - return header.getAnnotationData(); + return header.getData(); } return null; 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 5fb3cc8e433..c3d02e8fc57 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 @@ -23,9 +23,8 @@ class KotlinClassHeader( val kind: KotlinClassHeader.Kind, val metadataVersion: JvmMetadataVersion, val bytecodeVersion: JvmBytecodeBinaryVersion, - val annotationData: Array?, + val data: Array?, val strings: Array?, - val filePartClassNames: Array?, val multifileClassName: String?, val isInterfaceDefaultImpls: Boolean, val isLocalClass: Boolean 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 8cee066627c..ee5fb9ccbda 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 @@ -48,8 +48,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private JvmMetadataVersion metadataVersion = null; private JvmBytecodeBinaryVersion bytecodeVersion = null; private String multifileClassName = null; - private String[] filePartClassNames = null; - private String[] annotationData = null; + private String[] data = null; private String[] strings = null; private KotlinClassHeader.Kind headerKind = null; private boolean isInterfaceDefaultImpls = false; @@ -62,9 +61,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } if (metadataVersion == null || !metadataVersion.isCompatible()) { - annotationData = null; + data = null; } - else if (shouldHaveData() && annotationData == null) { + else if (shouldHaveData() && data == null) { // This means that the annotation is found and its ABI version is compatible, but there's no "data" string array in it. // We tell the outside world that there's really no annotation at all return null; @@ -74,7 +73,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor headerKind, metadataVersion != null ? metadataVersion : JvmMetadataVersion.INVALID_VERSION, bytecodeVersion != null ? bytecodeVersion : JvmBytecodeBinaryVersion.INVALID_VERSION, - annotationData, strings, filePartClassNames, multifileClassName, isInterfaceDefaultImpls, isLocalClass + data, strings, multifileClassName, isInterfaceDefaultImpls, isLocalClass ); } @@ -140,36 +139,23 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Nullable public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) { String string = name.asString(); - if (DATA_FIELD_NAME.equals(string)) { + if (DATA_FIELD_NAME.equals(string) || FILE_PART_CLASS_NAMES_FIELD_NAME.equals(string)) { return dataArrayVisitor(); } else if (STRINGS_FIELD_NAME.equals(string)) { return stringsArrayVisitor(); } - else if (FILE_PART_CLASS_NAMES_FIELD_NAME.equals(string)) { - return filePartClassNamesVisitor(); - } else { return null; } } - @NotNull - private AnnotationArrayArgumentVisitor filePartClassNamesVisitor() { - return new CollectStringArrayAnnotationVisitor() { - @Override - protected void visitEnd(@NotNull String[] data) { - filePartClassNames = data; - } - }; - } - @NotNull private AnnotationArrayArgumentVisitor dataArrayVisitor() { return new CollectStringArrayAnnotationVisitor() { @Override protected void visitEnd(@NotNull String[] data) { - annotationData = data; + ReadKotlinClassHeaderAnnotationVisitor.this.data = data; } }; } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt index 4a1450ff26e..ea03a102c60 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt @@ -76,10 +76,10 @@ fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean { header.isLocalClass } -fun findMultifileClassParts(file: VirtualFile, classId: ClassId, kotlinClassHeader: KotlinClassHeader): List { +fun findMultifileClassParts(file: VirtualFile, classId: ClassId, header: KotlinClassHeader): List { val packageFqName = classId.packageFqName val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName) - val partNames = kotlinClassHeader.filePartClassNames ?: return emptyList() + val partNames = header.data ?: return emptyList() return partNames.mapNotNull { partsFinder.findKotlinClass(ClassId(packageFqName, Name.identifier(it.substringAfterLast('/')))) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt index eb13c238687..42be78e3623 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt @@ -72,7 +72,7 @@ class DeserializerForClassfileDecompiler( } val binaryClassForPackageClass = classFinder.findKotlinClass(ClassId.topLevel(facadeFqName)) val header = binaryClassForPackageClass?.classHeader - val annotationData = header?.annotationData + val annotationData = header?.data val strings = header?.strings if (annotationData == null || strings == null) { LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.classId}") @@ -117,7 +117,7 @@ class DirectoryBasedDataFinder( override fun findClassData(classId: ClassId): ClassDataWithSource? { val binaryClass = classFinder.findKotlinClass(classId) ?: return null val classHeader = binaryClass.classHeader - val data = classHeader.annotationData + val data = classHeader.data if (data == null) { log.error("Annotation data missing for ${binaryClass.classId}") return null diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt index f4113bef9d1..0b8ae32591f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt @@ -70,7 +70,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { return createMultifileClassStub(header, partFiles, classId.asSingleFqName(), components) } - val annotationData = header.annotationData + val annotationData = header.data if (annotationData == null) { LOG.error("Corrupted kotlin header for file ${file.name}") return null 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 0bed4997dc7..482056d27e3 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 @@ -75,18 +75,18 @@ fun createFileFacadeStub( } fun createMultifileClassStub( - kotlinClassHeader: KotlinClassHeader, + header: KotlinClassHeader, partFiles: List, facadeFqName: FqName, components: ClsStubBuilderComponents ): KotlinFileStubImpl { val packageFqName = facadeFqName.parent() - val partNames = kotlinClassHeader.filePartClassNames?.asList()?.map { it.substringAfterLast('/') } + val partNames = header.data?.asList()?.map { it.substringAfterLast('/') } val fileStub = KotlinFileStubForIde.forMultifileClassStub(facadeFqName, partNames, packageFqName.isRoot) setupFileStub(fileStub, packageFqName) for (partFile in partFiles) { val partHeader = partFile.classHeader - val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!, partHeader.strings!!) + val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(partHeader.data!!, partHeader.strings!!) val partContext = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) val container = ProtoContainer.Package(packageFqName, partContext.nameResolver, partContext.typeTable, JvmPackagePartSource(partFile.classId)) 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 afb9f5032c7..57192fdf139 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -158,7 +158,7 @@ open class IncrementalCacheImpl( additionalProcessChangedClass(kotlinClass, isPackage = true) } KotlinClassHeader.Kind.MULTIFILE_CLASS -> { - val partNames = kotlinClass.classHeader.filePartClassNames?.toList() + val partNames = kotlinClass.classHeader.data?.toList() ?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}") multifileClassFacadeMap.add(className, partNames) @@ -324,7 +324,7 @@ open class IncrementalCacheImpl( fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean): CompilationResult { val header = kotlinClass.classHeader - val bytes = BitEncoding.decodeBytes(header.annotationData!!) + val bytes = BitEncoding.decodeBytes(header.data!!) return put(kotlinClass.className, bytes, header.strings!!, isPackage, checkChangesIsOpenPart = true) } @@ -498,7 +498,7 @@ open class IncrementalCacheImpl( private fun addToClassStorage(kotlinClass: LocalFileKotlinClass) { if (!IncrementalCompilation.isExperimental()) return - val classData = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.annotationData!!, kotlinClass.classHeader.strings!!) + val classData = JvmProtoBufUtil.readClassDataFrom(kotlinClass.classHeader.data!!, kotlinClass.classHeader.strings!!) val supertypes = classData.classProto.supertypes(TypeTable(classData.classProto.typeTable)) val parents = supertypes.map { classData.nameResolver.getClassId(it.className).asSingleFqName() } .filter { it.asString() != "kotlin.Any" } diff --git a/jps-plugin/test/org/jetbrains/kotlin/jps/build/classFilesComparison/classFilesComparison.kt b/jps-plugin/test/org/jetbrains/kotlin/jps/build/classFilesComparison/classFilesComparison.kt index a9e51f5b98d..ff1accafe69 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/jps/build/classFilesComparison/classFilesComparison.kt +++ b/jps-plugin/test/org/jetbrains/kotlin/jps/build/classFilesComparison/classFilesComparison.kt @@ -132,7 +132,7 @@ fun classFileToString(classFile: File): String { val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader - val annotationDataEncoded = classHeader?.annotationData + val annotationDataEncoded = classHeader?.data if (annotationDataEncoded != null) { ByteArrayInputStream(BitEncoding.decodeBytes(annotationDataEncoded)).use { input -> 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 77fdb5fc752..6193643825c 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt +++ b/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.testFramework.UsefulTestCase import com.intellij.util.SmartList import org.jetbrains.kotlin.jps.incremental.storage.ProtoMapValue +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.serialization.jvm.BitEncoding import org.jetbrains.kotlin.test.KotlinTestUtils @@ -28,7 +29,6 @@ import org.jetbrains.kotlin.utils.Printer import java.io.File abstract class AbstractProtoComparisonTest : UsefulTestCase() { - fun doTest(testDataPath: String) { val testDir = KotlinTestUtils.tmpDir("testDirectory") @@ -77,43 +77,31 @@ abstract class AbstractProtoComparisonTest : UsefulTestCase() { } private fun Printer.printDifference(oldClassFile: File, newClassFile: File) { - val oldLocalFileKotlinClass = LocalFileKotlinClass.create(oldClassFile)!! - val newLocalFileKotlinClass = LocalFileKotlinClass.create(newClassFile)!! - - val oldClassHeader = oldLocalFileKotlinClass.classHeader - val newClassHeader = newLocalFileKotlinClass.classHeader - - if (oldClassHeader.annotationData == null || newClassHeader.annotationData == null) { - println("skip ${oldLocalFileKotlinClass.classId}") - return - } - - val oldProtoBytes = BitEncoding.decodeBytes(oldClassHeader.annotationData!!) - val newProtoBytes = BitEncoding.decodeBytes(newClassHeader.annotationData!!) - - assert(oldClassHeader.metadataVersion.isCompatible()) { "Incompatible class ($oldClassHeader): $oldClassFile" } - assert(newClassHeader.metadataVersion.isCompatible()) { "Incompatible class ($newClassHeader): $newClassFile" } - - val oldProto = ProtoMapValue( - oldClassHeader.kind == KotlinClassHeader.Kind.FILE_FACADE || - oldClassHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, - oldProtoBytes, oldClassHeader.strings!! - ) - val newProto = ProtoMapValue( - newClassHeader.kind == KotlinClassHeader.Kind.FILE_FACADE || - newClassHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, - newProtoBytes, newClassHeader.strings!! - ) - - val diff = when (newClassHeader.kind) { - KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> - difference(oldProto, newProto) - else -> { - println("ignore ${oldLocalFileKotlinClass.classId}") - return + fun KotlinJvmBinaryClass.readProto(): ProtoMapValue? { + assert(classHeader.metadataVersion.isCompatible()) { "Incompatible class ($classHeader): $location" } + return when (classHeader.kind) { + KotlinClassHeader.Kind.CLASS, KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> { + ProtoMapValue( + classHeader.kind != KotlinClassHeader.Kind.CLASS, + BitEncoding.decodeBytes(classHeader.data!!), + classHeader.strings!! + ) + } + else -> { + println("skip $classId") + return null + } } } + val oldClass = LocalFileKotlinClass.create(oldClassFile)!! + val newClass = LocalFileKotlinClass.create(newClassFile)!! + + val diff = difference( + oldClass.readProto() ?: return, + newClass.readProto() ?: return + ) + val changes = SmartList() if (diff.isClassSignatureChanged) { @@ -128,7 +116,7 @@ abstract class AbstractProtoComparisonTest : UsefulTestCase() { changes.add("NONE") } - println("changes in ${oldLocalFileKotlinClass.classId}: ${changes.joinToString()}") + println("changes in ${oldClass.classId}: ${changes.joinToString()}") } private fun File.createSubDirectory(relativePath: String): File {