diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt index 1773a963b48..b3b8c61eaec 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt @@ -18,6 +18,10 @@ package org.jetbrains.kotlin.load.java import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion +/** + * The version of conventions used in bytecode of generated .class files, such as default method naming & signatures, + * internal member name mangling specifics, property getter/setter names, etc. + */ class JvmBytecodeBinaryVersion protected constructor( major: Int, minor: Int, patch: Int, rest: List ) : BinaryVersion(major, minor, patch, rest) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/resolvers.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/resolvers.kt index cab83407cd1..590697fa71d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/resolvers.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/resolvers.kt @@ -70,8 +70,8 @@ fun LazyJavaResolverContext.resolveKotlinBinaryClass(kotlinClass: KotlinJvmBinar val header = kotlinClass.classHeader return when { - !header.version.isCompatible() -> { - components.errorReporter.reportIncompatibleAbiVersion(kotlinClass.classId, kotlinClass.location, header.version) + !header.metadataVersion.isCompatible() -> { + components.errorReporter.reportIncompatibleAbiVersion(kotlinClass.classId, kotlinClass.location, header.metadataVersion) KotlinClassLookupResult.NotFound } header.kind == KotlinClassHeader.Kind.CLASS -> { 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 229ce8d2025..c391f2d6c4b 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 @@ -115,8 +115,8 @@ public final class DeserializedDescriptorResolver { @Nullable public String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @NotNull Set expectedKinds) { KotlinClassHeader header = kotlinClass.getClassHeader(); - if (!header.getVersion().isCompatible()) { - errorReporter.reportIncompatibleAbiVersion(kotlinClass.getClassId(), kotlinClass.getLocation(), header.getVersion()); + if (!header.getMetadataVersion().isCompatible()) { + errorReporter.reportIncompatibleAbiVersion(kotlinClass.getClassId(), kotlinClass.getLocation(), header.getMetadataVersion()); } else if (expectedKinds.contains(header.getKind())) { return header.getAnnotationData(); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt new file mode 100644 index 00000000000..0f8acc6b315 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmMetadataVersion.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.kotlin + +import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion + +/** + * The version of the metadata serialized by the compiler and deserialized by the compiler and reflection. + * This version includes the version of the core protobuf messages (descriptors.proto) as well as JVM extensions (jvm_descriptors.proto). + */ +class JvmMetadataVersion protected constructor( + major: Int, minor: Int, patch: Int, rest: List +) : BinaryVersion(major, minor, patch, rest) { + override fun isCompatible() = this.isCompatibleTo(INSTANCE) + + companion object { + @JvmField + val INSTANCE = create(1, 0, 2) + + @JvmField + val INVALID_VERSION = JvmMetadataVersion.create(IntArray(0)) + + @JvmStatic + fun create(version: IntArray) = create(version, ::JvmMetadataVersion) + + @JvmStatic + fun create(major: Int, minor: Int, patch: Int) = create(major, minor, patch, ::JvmMetadataVersion) + } +} 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 71763c99701..5fb3cc8e433 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 @@ -16,11 +16,13 @@ package org.jetbrains.kotlin.load.kotlin.header -import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion +import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion +import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion class KotlinClassHeader( val kind: KotlinClassHeader.Kind, - val version: BinaryVersion, + val metadataVersion: JvmMetadataVersion, + val bytecodeVersion: JvmBytecodeBinaryVersion, val annotationData: Array?, val strings: Array?, val filePartClassNames: Array?, @@ -36,10 +38,5 @@ class KotlinClassHeader( SYNTHETIC_CLASS } - override fun toString() = "$kind " + (if (isLocalClass) "(local) " else "") + "version=$version" + override fun toString() = "$kind " + (if (isLocalClass) "(local) " else "") + "version=$metadataVersion" } - -fun KotlinClassHeader.isCompatibleClassKind(): Boolean = version.isCompatible() && kind == KotlinClassHeader.Kind.CLASS -fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = version.isCompatible() && kind == KotlinClassHeader.Kind.FILE_FACADE -fun KotlinClassHeader.isCompatibleMultifileClassKind(): Boolean = version.isCompatible() && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS -fun KotlinClassHeader.isCompatibleMultifileClassPartKind(): Boolean = version.isCompatible() && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART 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 779d0c994b1..8cee066627c 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 @@ -20,10 +20,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion; +import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; import java.util.ArrayList; import java.util.HashMap; @@ -45,7 +45,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor HEADER_KINDS.put(ClassId.topLevel(KOTLIN_SYNTHETIC_CLASS), SYNTHETIC_CLASS); } - private BinaryVersion version = JvmBytecodeBinaryVersion.INVALID_VERSION; + private JvmMetadataVersion metadataVersion = null; + private JvmBytecodeBinaryVersion bytecodeVersion = null; private String multifileClassName = null; private String[] filePartClassNames = null; private String[] annotationData = null; @@ -60,7 +61,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor return null; } - if (!version.isCompatible()) { + if (metadataVersion == null || !metadataVersion.isCompatible()) { annotationData = null; } else if (shouldHaveData() && annotationData == null) { @@ -70,7 +71,10 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } return new KotlinClassHeader( - headerKind, version, annotationData, strings, filePartClassNames, multifileClassName, isInterfaceDefaultImpls, isLocalClass + headerKind, + metadataVersion != null ? metadataVersion : JvmMetadataVersion.INVALID_VERSION, + bytecodeVersion != null ? bytecodeVersion : JvmBytecodeBinaryVersion.INVALID_VERSION, + annotationData, strings, filePartClassNames, multifileClassName, isInterfaceDefaultImpls, isLocalClass ); } @@ -118,7 +122,14 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor String string = name.asString(); if (VERSION_FIELD_NAME.equals(string)) { - version = value instanceof int[] ? JvmBytecodeBinaryVersion.create((int[]) value) : JvmBytecodeBinaryVersion.INVALID_VERSION; + if (value instanceof int[]) { + metadataVersion = JvmMetadataVersion.create((int[]) value); + + // If there's no bytecode binary version in the class file, we assume it to be equal to the metadata version + if (bytecodeVersion == null) { + bytecodeVersion = JvmBytecodeBinaryVersion.create((int[]) value); + } + } } else if (MULTIFILE_CLASS_NAME_FIELD_NAME.equals(string)) { multifileClassName = value instanceof String ? (String) value : null; 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 9e6c2c48b96..4a1450ff26e 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 @@ -54,7 +54,7 @@ fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean { if (!isKotlinJvmCompiledFile(file)) return false val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) - return kotlinClass != null && kotlinClass.classHeader.version.isCompatible() + return kotlinClass != null && kotlinClass.classHeader.metadataVersion.isCompatible() } /** diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt index 379a9c1f299..8ad7369e4f0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt @@ -29,9 +29,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolverForDecompiler import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassKind +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.types.flexibility import org.jetbrains.kotlin.types.isFlexible @@ -79,30 +77,33 @@ fun buildDecompiledTextForClassFile( classFile: VirtualFile, resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile) ): DecompiledText { - val kotlinClassHeaderInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(classFile) - assert(kotlinClassHeaderInfo != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile } - val classId = kotlinClassHeaderInfo!!.classId - val classHeader = kotlinClassHeaderInfo.classHeader - val packageFqName = classId.packageFqName + val (classHeader, classId) = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(classFile) + ?: error("Decompiled data factory shouldn't be called on an unsupported file: " + classFile) - return when { - !classHeader.version.isCompatible() -> { - DecompiledText( - INCOMPATIBLE_ABI_VERSION_COMMENT - .replace(CURRENT_ABI_VERSION_MARKER, JvmBytecodeBinaryVersion.INSTANCE.toString()) - .replace(FILE_ABI_VERSION_MARKER, classHeader.version.toString()), - mapOf()) - } - classHeader.isCompatibleFileFacadeKind() -> - buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())), decompilerRendererForClassFiles) - classHeader.isCompatibleClassKind() -> - buildDecompiledText(packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), decompilerRendererForClassFiles) - classHeader.isCompatibleMultifileClassKind() -> { + if (!classHeader.metadataVersion.isCompatible()) { + return DecompiledText( + INCOMPATIBLE_ABI_VERSION_COMMENT + .replace(CURRENT_ABI_VERSION_MARKER, JvmBytecodeBinaryVersion.INSTANCE.toString()) + .replace(FILE_ABI_VERSION_MARKER, classHeader.metadataVersion.toString()), + mapOf() + ) + } + + return when (classHeader.kind) { + KotlinClassHeader.Kind.FILE_FACADE -> + buildDecompiledText(classId.packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())), + decompilerRendererForClassFiles) + KotlinClassHeader.Kind.CLASS -> + buildDecompiledText(classId.packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), + decompilerRendererForClassFiles) + KotlinClassHeader.Kind.MULTIFILE_CLASS -> { val partClasses = findMultifileClassParts(classFile, classId, classHeader) - val partMembers = partClasses.flatMap { partClass -> resolver.resolveDeclarationsInFacade(partClass.classId.asSingleFqName()) } - buildDecompiledText(packageFqName, partMembers, decompilerRendererForClassFiles) + val partMembers = partClasses.flatMap { partClass -> + resolver.resolveDeclarationsInFacade(partClass.classId.asSingleFqName()) + } + buildDecompiledText(classId.packageFqName, partMembers, decompilerRendererForClassFiles) } else -> - throw UnsupportedOperationException("Unknown header kind: ${classHeader.kind} ${classHeader.version.isCompatible()}") + throw UnsupportedOperationException("Unknown header kind: $classHeader, class $classId") } } 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 d9701de9632..f4113bef9d1 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 @@ -30,9 +30,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter import org.jetbrains.kotlin.load.kotlin.AbstractBinaryClassAnnotationAndConstantLoader import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassKind +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile @@ -62,12 +60,12 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { val header = kotlinClassHeaderInfo.classHeader val classId = kotlinClassHeaderInfo.classId val packageFqName = classId.packageFqName - if (!header.version.isCompatible()) { + if (!header.metadataVersion.isCompatible()) { return createIncompatibleAbiVersionFileStub() } val components = createStubBuilderComponents(file, packageFqName) - if (header.isCompatibleMultifileClassKind()) { + if (header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS) { val partFiles = findMultifileClassParts(file, classId, header) return createMultifileClassStub(header, partFiles, classId.asSingleFqName(), components) } @@ -82,14 +80,14 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { LOG.error("String table not found in file ${file.name}") return null } - return when { - header.isCompatibleClassKind() -> { + return when (header.kind) { + KotlinClassHeader.Kind.CLASS -> { if (header.isLocalClass) return null val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable)) createTopLevelClassStub(classId, classProto, context) } - header.isCompatibleFileFacadeKind() -> { + KotlinClassHeader.Kind.FILE_FACADE -> { val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) createFileFacadeStub(packageProto, classId.asSingleFqName(), context) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt index 54ac1645835..4ed9782ccc0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt @@ -79,7 +79,7 @@ object KotlinClassFileIndex : KotlinFileIndexBase(KotlinCl private val INDEXER = indexer() { fileContent -> val headerInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(fileContent.file, fileContent.content) - if (headerInfo != null && headerInfo.classHeader.version.isCompatible()) headerInfo.classId.asSingleFqName() else null + if (headerInfo != null && headerInfo.classHeader.metadataVersion.isCompatible()) headerInfo.classId.asSingleFqName() else null } } 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 21537fd9d34..afb9f5032c7 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -30,10 +30,7 @@ import org.jetbrains.kotlin.jps.build.GeneratedJvmClass import org.jetbrains.kotlin.jps.build.KotlinBuilder import org.jetbrains.kotlin.jps.incremental.storage.* import org.jetbrains.kotlin.load.kotlin.ModuleMapping -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassPartKind +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.name.FqName @@ -147,8 +144,12 @@ open class IncrementalCacheImpl( } val header = kotlinClass.classHeader - val changesInfo = when { - header.isCompatibleFileFacadeKind() -> { + if (header.isLocalClass) { + return CompilationResult.NO_CHANGES + } + + val changesInfo = when (header.kind) { + KotlinClassHeader.Kind.FILE_FACADE -> { assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" } packagePartMap.addPackagePart(className) @@ -156,7 +157,7 @@ open class IncrementalCacheImpl( constantsMap.process(kotlinClass) + additionalProcessChangedClass(kotlinClass, isPackage = true) } - header.isCompatibleMultifileClassKind() -> { + KotlinClassHeader.Kind.MULTIFILE_CLASS -> { val partNames = kotlinClass.classHeader.filePartClassNames?.toList() ?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}") multifileClassFacadeMap.add(className, partNames) @@ -165,7 +166,7 @@ open class IncrementalCacheImpl( constantsMap.process(kotlinClass) + additionalProcessChangedClass(kotlinClass, isPackage = true) } - header.isCompatibleMultifileClassPartKind() -> { + 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!!) @@ -174,7 +175,7 @@ open class IncrementalCacheImpl( constantsMap.process(kotlinClass) + additionalProcessChangedClass(kotlinClass, isPackage = true) } - header.isCompatibleClassKind() && !header.isLocalClass -> { + KotlinClassHeader.Kind.CLASS -> { addToClassStorage(kotlinClass) protoMap.process(kotlinClass, isPackage = false) + 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 4fa17591046..a9e51f5b98d 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 @@ -22,9 +22,7 @@ import com.google.common.io.Files import com.google.protobuf.ExtensionRegistry import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.jps.incremental.LocalFileKotlinClass -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassPartKind +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.serialization.DebugProtoBuf import org.jetbrains.kotlin.serialization.jvm.BitEncoding import org.jetbrains.kotlin.serialization.jvm.DebugJvmProtoBuf @@ -141,14 +139,17 @@ fun classFileToString(classFile: File): String { out.write("\n------ string table types proto -----\n${DebugJvmProtoBuf.StringTableTypes.parseDelimitedFrom(input)}") - when { - classHeader!!.isCompatibleFileFacadeKind() -> - out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}") - classHeader.isCompatibleClassKind() -> - out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}") - classHeader.isCompatibleMultifileClassPartKind() -> - out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}") + if (!classHeader!!.metadataVersion.isCompatible()) { + error("Incompatible class ($classHeader): $classFile") + } + when (classHeader.kind) { + KotlinClassHeader.Kind.FILE_FACADE -> + out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}") + KotlinClassHeader.Kind.CLASS -> + out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}") + KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> + out.write("\n------ multi-file part proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}") else -> throw IllegalStateException() } } 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 f9ae0e18edc..77fdb5fc752 100644 --- a/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt +++ b/jps-plugin/test/org/jetbrains/kotlin/jps/incremental/AbstractProtoComparisonTest.kt @@ -20,9 +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.header.isCompatibleClassKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind -import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassPartKind +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.serialization.jvm.BitEncoding import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.MockLibraryUtil @@ -93,19 +91,22 @@ abstract class AbstractProtoComparisonTest : UsefulTestCase() { 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.isCompatibleFileFacadeKind() || oldClassHeader.isCompatibleMultifileClassPartKind(), + oldClassHeader.kind == KotlinClassHeader.Kind.FILE_FACADE || + oldClassHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, oldProtoBytes, oldClassHeader.strings!! ) val newProto = ProtoMapValue( - newClassHeader.isCompatibleFileFacadeKind() || newClassHeader.isCompatibleMultifileClassPartKind(), + newClassHeader.kind == KotlinClassHeader.Kind.FILE_FACADE || + newClassHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, newProtoBytes, newClassHeader.strings!! ) - val diff = when { - newClassHeader.isCompatibleClassKind() || - newClassHeader.isCompatibleFileFacadeKind() || - newClassHeader.isCompatibleMultifileClassPartKind() -> + 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}")