Deserialization/class reading: pass chosen JvmMetadataVersion whenever possible

This commit is contained in:
Mikhail Glukhikh
2022-12-02 16:38:59 +01:00
parent 52ab565cc6
commit 0c4a0360ac
67 changed files with 399 additions and 163 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap;
import org.jetbrains.kotlin.descriptors.SourceElement;
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor;
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion;
import org.jetbrains.kotlin.name.ClassId;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
@@ -76,6 +77,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
@Nullable
public static <T> T create(
@NotNull byte[] fileContents,
@NotNull JvmMetadataVersion jvmMetadataVersionFromLanguageVersion,
@NotNull Function4<ClassId, Integer, KotlinClassHeader, InnerClassesInfo, T> factory
) {
ReadKotlinClassHeaderAnnotationVisitor readHeaderVisitor = new ReadKotlinClassHeaderAnnotationVisitor();
@@ -108,7 +110,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
String className = classNameRef.get();
if (className == null) return null;
KotlinClassHeader header = readHeaderVisitor.createHeader();
KotlinClassHeader header = readHeaderVisitor.createHeader(jvmMetadataVersionFromLanguageVersion);
if (header == null) return null;
ClassId id = resolveNameByInternalName(className, innerClasses);
@@ -12,7 +12,7 @@ import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Computable
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import java.lang.ref.WeakReference
import java.util.concurrent.CopyOnWriteArrayList
@@ -59,8 +59,19 @@ class KotlinBinaryClassCache : Disposable {
}
companion object {
@Deprecated(
"Please pass jvmMetadataVersion explicitly",
ReplaceWith(
"getKotlinBinaryClassOrClassFileContent(file, JvmMetadataVersion.INSTANCE, fileContent = fileContent)",
"org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion"
)
)
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, fileContent: ByteArray? = null
file: VirtualFile, fileContent: ByteArray?
) = getKotlinBinaryClassOrClassFileContent(file, jvmMetadataVersion = JvmMetadataVersion.INSTANCE, fileContent = fileContent)
fun getKotlinBinaryClassOrClassFileContent(
file: VirtualFile, jvmMetadataVersion: JvmMetadataVersion, fileContent: ByteArray? = null
): KotlinClassFinder.Result? {
if (file.extension != JavaClassFileType.INSTANCE.defaultExtension &&
file.fileType !== JavaClassFileType.INSTANCE
@@ -76,7 +87,7 @@ class KotlinBinaryClassCache : Disposable {
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
VirtualFileKotlinClass.create(file, fileContent)
VirtualFileKotlinClass.create(file, jvmMetadataVersion, fileContent)
})
return requestCache.cache(file, aClass)
@@ -11,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.util.PerformanceCounter
import java.io.FileNotFoundException
@@ -46,14 +47,14 @@ class VirtualFileKotlinClass private constructor(
private val LOG = Logger.getInstance(VirtualFileKotlinClass::class.java)
private val perfCounter = PerformanceCounter.create("Binary class from Kotlin file")
internal fun create(file: VirtualFile, fileContent: ByteArray?): KotlinClassFinder.Result? {
internal fun create(file: VirtualFile, jvmMetadataVersion: JvmMetadataVersion, fileContent: ByteArray?): KotlinClassFinder.Result? {
return perfCounter.time {
assert(file.extension == JavaClassFileType.INSTANCE.defaultExtension || file.fileType == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" }
try {
val byteContent = fileContent ?: file.contentsToByteArray(false)
if (byteContent.isNotEmpty()) {
val kotlinJvmBinaryClass = create(byteContent) { name, classVersion, header, innerClasses ->
val kotlinJvmBinaryClass = create(byteContent, jvmMetadataVersion) { name, classVersion, header, innerClasses ->
VirtualFileKotlinClass(file, name, classVersion, header, innerClasses)
}