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:
+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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user