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.

Original commit: bd47e9d47b
This commit is contained in:
Alexander Udalov
2015-12-28 20:01:00 +03:00
parent 00075fc837
commit a230c85fe2
3 changed files with 31 additions and 28 deletions
@@ -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) +
@@ -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()
}
}
@@ -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}")