Split JVM binary version into two: metadata and bytecode interface
Currently all code only uses the first one (JvmMetadataVersion), later the bytecode interface version (JvmBytecodeBinaryVersion) will be used only in codegen and reflection to avoid compiling against or calling methods with unsupported conventions like default method naming and signature, getters/setters naming etc.
This commit is contained in:
+4
@@ -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<Int>
|
||||
) : BinaryVersion(major, minor, patch, rest) {
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
+2
-2
@@ -115,8 +115,8 @@ public final class DeserializedDescriptorResolver {
|
||||
@Nullable
|
||||
public String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @NotNull Set<KotlinClassHeader.Kind> 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();
|
||||
|
||||
+43
@@ -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<Int>
|
||||
) : 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)
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -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<String>?,
|
||||
val strings: Array<String>?,
|
||||
val filePartClassNames: Array<String>?,
|
||||
@@ -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
|
||||
|
||||
+16
-5
@@ -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;
|
||||
|
||||
+1
-1
@@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+25
-24
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -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)
|
||||
|
||||
@@ -79,7 +79,7 @@ object KotlinClassFileIndex : KotlinFileIndexBase<KotlinClassFileIndex>(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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) +
|
||||
|
||||
+11
-10
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+10
-9
@@ -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}")
|
||||
|
||||
Reference in New Issue
Block a user