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
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.java.createConstantOrError
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
import org.jetbrains.kotlin.utils.toMetadataVersion
internal class AnnotationsLoader(private val session: FirSession, private val kotlinClassFinder: KotlinClassFinder) {
private fun loadAnnotation(
@@ -190,7 +192,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
) return false
val klass = kotlinClassFinder.findKotlinClass(classId)
val klass = kotlinClassFinder.findKotlinClass(classId, session.languageVersionSettings.languageVersion.toMetadataVersion())
return klass != null && SpecialJvmAnnotations.isAnnotatedWithContainerMetaAnnotation(klass)
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.metadata.ProtoBuf
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.toMetadataVersion
class JvmBinaryAnnotationDeserializer(
val session: FirSession,
@@ -37,8 +39,9 @@ class JvmBinaryAnnotationDeserializer(
private val annotationInfoForDefaultImpls by lazy(LazyThreadSafetyMode.PUBLICATION) {
val defaultImplsClassId = kotlinBinaryClass.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
val (defaultImplsClass, defaultImplsByteContent) = kotlinClassFinder.findKotlinClassOrContent(defaultImplsClassId) as? KotlinClassFinder.Result.KotlinClass
?: return@lazy null
val (defaultImplsClass, defaultImplsByteContent) = kotlinClassFinder.findKotlinClassOrContent(
defaultImplsClassId, session.languageVersionSettings.languageVersion.toMetadataVersion()
) as? KotlinClassFinder.Result.KotlinClass ?: return@lazy null
session.loadMemberAnnotations(defaultImplsClass, defaultImplsByteContent, kotlinClassFinder)
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.deserialization.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.java.FirJavaFacade
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.load.kotlin.*
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.utils.toMetadataVersion
import java.nio.file.Path
import java.nio.file.Paths
@@ -60,12 +62,16 @@ class JvmClassFileBasedSymbolProvider(
if (partName in kotlinBuiltins) return@mapNotNull null
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
if (!javaFacade.hasTopLevelClassOf(classId)) return@mapNotNull null
val (kotlinJvmBinaryClass, byteContent) =
kotlinClassFinder.findKotlinClassOrContent(classId) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null
val jvmMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion()
val (kotlinJvmBinaryClass, byteContent) = kotlinClassFinder.findKotlinClassOrContent(
classId, jvmMetadataVersion
) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null
val facadeName = kotlinJvmBinaryClass.classHeader.multifileClassName?.takeIf { it.isNotEmpty() }
val facadeFqName = facadeName?.let { JvmClassName.byInternalName(it).fqNameForTopLevelClassMaybeWithDollars }
val facadeBinaryClass = facadeFqName?.let { kotlinClassFinder.findKotlinClass(ClassId.topLevel(it)) }
val facadeBinaryClass = facadeFqName?.let {
kotlinClassFinder.findKotlinClass(ClassId.topLevel(it), jvmMetadataVersion)
}
val moduleData = moduleDataProvider.getModuleData(kotlinJvmBinaryClass.containingLibrary.toPath()) ?: return@mapNotNull null
@@ -94,8 +100,11 @@ class JvmClassFileBasedSymbolProvider(
private val KotlinJvmBinaryClass.incompatibility: IncompatibleVersionErrorData<JvmMetadataVersion>?
get() {
// TODO: skipMetadataVersionCheck
if (classHeader.metadataVersion.isCompatible()) return null
return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId)
val expectedMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion()
if (classHeader.metadataVersion.isCompatible(expectedMetadataVersion)) return null
return IncompatibleVersionErrorData(
classHeader.metadataVersion, maxOf(expectedMetadataVersion, JvmMetadataVersion.INSTANCE.next()), location, classId
)
}
private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean
@@ -105,7 +114,9 @@ class JvmClassFileBasedSymbolProvider(
// Kotlin classes are annotated Java classes, so this check also looks for them.
if (!javaFacade.hasTopLevelClassOf(classId)) return null
val result = kotlinClassFinder.findKotlinClassOrContent(classId)
val result = kotlinClassFinder.findKotlinClassOrContent(
classId, session.languageVersionSettings.languageVersion.toMetadataVersion()
)
if (result !is KotlinClassFinder.Result.KotlinClass) {
if (parentContext != null || (classId.isNestedClass && getClass(classId.outermostClassId)?.fir !is FirJavaClass)) {
// Nested class of Kotlin class should have been a Kotlin class.