FIR: support (partially) type annotations in JVM deserialized

This commit is contained in:
Mikhail Glukhikh
2019-04-22 18:44:14 +03:00
parent 48cd9e3251
commit e3e7eea3fe
15 changed files with 96 additions and 39 deletions
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.java.deserialization
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver
class JvmBinaryAnnotationDeserializer(
session: FirSession, nameResolver: JvmNameResolver
) : AbstractAnnotationDeserializer(session, nameResolver) {
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type): List<FirAnnotationCall> {
val annotations = typeProto.getExtension(JvmProtoBuf.typeAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it) }
}
}
@@ -100,7 +100,10 @@ class KotlinDeserializedJvmSymbolsProvider(
PackagePartsCacheData(
packageProto,
FirDeserializationContext.createForPackage(packageFqName, packageProto, nameResolver, session)
FirDeserializationContext.createForPackage(
packageFqName, packageProto, nameResolver, session,
JvmBinaryAnnotationDeserializer(session, nameResolver)
)
)
}
}
@@ -272,7 +275,6 @@ class KotlinDeserializedJvmSymbolsProvider(
return loadAnnotation(annotationClassId, result)
}
private fun findAndDeserializeClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null
@@ -299,7 +301,11 @@ class KotlinDeserializedJvmSymbolsProvider(
val symbol = FirClassSymbol(classId)
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session, parentContext,
classId, classProto, symbol, nameResolver, session,
parentContext ?: FirDeserializationContext.createForClass(
classId, classProto, nameResolver, session,
JvmBinaryAnnotationDeserializer(session, nameResolver)
),
this::findAndDeserializeClass
)
val annotations = mutableListOf<FirAnnotationCall>()
@@ -29,11 +29,11 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial
import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.serialization.deserialization.getName
class FirAnnotationDeserializer(
abstract class AbstractAnnotationDeserializer(
private val session: FirSession,
private val nameResolver: NameResolver
) {
private val protocol = BuiltInSerializerProtocol
protected val protocol = BuiltInSerializerProtocol
fun loadClassAnnotations(classProto: ProtoBuf.Class): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(classProto.flags)) return emptyList()
@@ -65,13 +65,9 @@ class FirAnnotationDeserializer(
return annotations.map { deserializeAnnotation(it) }
}
fun loadTypeAnnotations(typeProto: ProtoBuf.Type): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(typeProto.flags)) return emptyList()
val annotations = typeProto.getExtension(protocol.typeAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it) }
}
abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type): List<FirAnnotationCall>
private fun deserializeAnnotation(proto: ProtoBuf.Annotation): FirAnnotationCall {
fun deserializeAnnotation(proto: ProtoBuf.Annotation): FirAnnotationCall {
val classId = nameResolver.getClassId(proto.id)
val lookupTag = ConeClassLikeLookupTagImpl(classId)
val symbol = lookupTag.toSymbol(session)
@@ -126,12 +122,12 @@ class FirAnnotationDeserializer(
CLASS -> FirGetClassCallImpl(session, null).apply {
val classId = nameResolver.getClassId(value.classId)
val lookupTag = ConeClassLikeLookupTagImpl(classId)
val symbol = lookupTag.toSymbol(this@FirAnnotationDeserializer.session) ?: return null
val symbol = lookupTag.toSymbol(this@AbstractAnnotationDeserializer.session) ?: return null
val referencedType = symbol.constructType(emptyArray(), isNullable = false)
arguments += FirClassReferenceExpressionImpl(
this@FirAnnotationDeserializer.session, null,
this@AbstractAnnotationDeserializer.session, null,
FirResolvedTypeRefImpl(
this@FirAnnotationDeserializer.session, null, referencedType,
this@AbstractAnnotationDeserializer.session, null, referencedType,
isMarkedNullable = false, annotations = emptyList()
)
)
@@ -141,11 +137,11 @@ class FirAnnotationDeserializer(
val entryName = nameResolver.getName(value.enumValueId)
val entryClassId = classId.createNestedClassId(entryName)
val entryLookupTag = ConeClassLikeLookupTagImpl(entryClassId)
val entrySymbol = entryLookupTag.toSymbol(this@FirAnnotationDeserializer.session)
val entrySymbol = entryLookupTag.toSymbol(this@AbstractAnnotationDeserializer.session)
this.calleeReference = entrySymbol?.let {
FirResolvedCallableReferenceImpl(this@FirAnnotationDeserializer.session, null, entryName, it)
FirResolvedCallableReferenceImpl(this@AbstractAnnotationDeserializer.session, null, entryName, it)
} ?: FirErrorNamedReference(
this@FirAnnotationDeserializer.session, null,
this@AbstractAnnotationDeserializer.session, null,
errorReason = "Strange deserialized enum value: $classId.$entryName"
)
}
@@ -45,8 +45,9 @@ fun deserializeClassToSymbol(
val context =
parentContext?.childContext(classProto.typeParameterList, nameResolver, TypeTable(classProto.typeTable))
?: FirDeserializationContext
.createForClass(classId, classProto, nameResolver, session)
?: FirDeserializationContext.createForClass(
classId, classProto, nameResolver, session, FirBuiltinAnnotationDeserializer(session, nameResolver)
)
typeParameters += context.typeDeserializer.ownTypeParameters.map { it.firUnsafe() }
annotations += context.annotationDeserializer.loadClassAnnotations(classProto)
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.deserialization
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
class FirBuiltinAnnotationDeserializer(
session: FirSession, nameResolver: NameResolver
) : AbstractAnnotationDeserializer(session, nameResolver) {
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(typeProto.flags)) return emptyList()
val annotations = typeProto.getExtension(protocol.typeAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it) }
}
}
@@ -37,6 +37,7 @@ class FirDeserializationContext(
val packageFqName: FqName,
val relativeClassName: FqName?,
val typeDeserializer: FirTypeDeserializer,
val annotationDeserializer: AbstractAnnotationDeserializer,
val components: FirDeserializationComponents
) {
fun childContext(
@@ -48,23 +49,23 @@ class FirDeserializationContext(
FirTypeDeserializer(
session, nameResolver, typeTable, typeParameterProtos, typeDeserializer
),
components
annotationDeserializer, components
)
val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
val annotationDeserializer: FirAnnotationDeserializer = FirAnnotationDeserializer(session, nameResolver)
companion object {
fun createForPackage(
fqName: FqName,
packageProto: ProtoBuf.Package,
nameResolver: NameResolver,
session: FirSession
session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer
) = createRootContext(
nameResolver,
TypeTable(packageProto.typeTable),
session,
annotationDeserializer,
fqName,
relativeClassName = null,
typeParameterProtos = emptyList()
@@ -74,11 +75,13 @@ class FirDeserializationContext(
classId: ClassId,
classProto: ProtoBuf.Class,
nameResolver: NameResolver,
session: FirSession
session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer
) = createRootContext(
nameResolver,
TypeTable(classProto.typeTable),
session,
annotationDeserializer,
classId.packageFqName,
classId.relativeClassName,
classProto.typeParameterList
@@ -88,6 +91,7 @@ class FirDeserializationContext(
nameResolver: NameResolver,
typeTable: TypeTable,
session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer,
packageFqName: FqName,
relativeClassName: FqName?,
typeParameterProtos: List<ProtoBuf.TypeParameter>
@@ -105,6 +109,7 @@ class FirDeserializationContext(
typeParameterProtos,
null
),
annotationDeserializer,
FirDeserializationComponents()
)
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirEnumEntryImpl
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
import org.jetbrains.kotlin.fir.resolve.*
@@ -65,7 +66,10 @@ class FirLibrarySymbolProviderImpl(val session: FirSession) : FirSymbolProvider
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
private val memberDeserializer by lazy {
FirDeserializationContext.createForPackage(fqName, packageProto.`package`, nameResolver, session).memberDeserializer
FirDeserializationContext.createForPackage(
fqName, packageProto.`package`, nameResolver, session,
FirBuiltinAnnotationDeserializer(session, nameResolver)
).memberDeserializer
}
val lookup = mutableMapOf<ClassId, FirClassSymbol>()
@@ -1,17 +1,17 @@
public final class A : R|kotlin/Any| {
public final fun arrays(s: R|kotlin/Array<kotlin/Int>|, t: R|kotlin/Array<kotlin/IntArray>|, u: R|kotlin/Array<kotlin/Array<kotlin/Int>>|, v: R|kotlin/Array<kotlin/Array<kotlin/Array<kotlin/String>>>|): R|kotlin/Unit|
public final fun arrays(s: @R|test/Ann|(klass = <getClass>(<getClass>(R|kotlin/Int|))) R|kotlin/Array<kotlin/Int>|, t: @R|test/Ann|(klass = <getClass>(<getClass>(R|kotlin/IntArray|))) R|kotlin/Array<kotlin/IntArray>|, u: @R|test/Ann|(klass = <getClass>(<getClass>(R|kotlin/Int|))) R|kotlin/Array<kotlin/Array<kotlin/Int>>|, v: @R|test/Ann|(klass = <getClass>(<getClass>(R|kotlin/String|))) R|kotlin/Array<kotlin/Array<kotlin/Array<kotlin/String>>>|): R|kotlin/Unit|
public final fun generic(s: R|kotlin/String|): R|kotlin/Unit|
public final fun generic(s: @R|test/Ann|(klass = <getClass>(<getClass>(R|test/Generic|))) R|kotlin/String|): R|kotlin/Unit|
public final fun innerGeneric(s: R|kotlin/String|): R|kotlin/Unit|
public final fun innerGeneric(s: @R|test/Ann|(klass = <getClass>(<getClass>(R|test/InnerGeneric.Inner|))) R|kotlin/String|): R|kotlin/Unit|
public final fun simple(s: R|kotlin/String|): R|kotlin/Unit|
public final fun simple(s: @R|test/Ann|(klass = <getClass>(<getClass>(R|test/Simple|))) R|kotlin/String|): R|kotlin/Unit|
public constructor(): R|test/A|
}
public final annotation class Ann : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = <implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.TYPE|())) public final annotation class Ann : R|kotlin/Annotation| {
public final val klass: R|kotlin/reflect/KClass<*>|
public get(): R|kotlin/reflect/KClass<*>|
@@ -1,6 +1,6 @@
public final fun R|kotlin/String|.foo(): R|kotlin/Unit|
public final fun @R|test/A|() R|kotlin/String|.foo(): R|kotlin/Unit|
public final annotation class A : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = <implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.TYPE|())) public final annotation class A : R|kotlin/Annotation| {
public constructor(): R|test/A|
}
@@ -1,10 +1,10 @@
public final annotation class A : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = <implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.TYPE|())) public final annotation class A : R|kotlin/Annotation| {
public constructor(): R|test/A|
}
public final class SimpleTypeAnnotation : R|kotlin/Any| {
public final fun foo(x: R|kotlin/ranges/IntRange|): R|kotlin/Int|
public final fun foo(x: @R|test/A|() R|kotlin/ranges/IntRange|): @R|test/A|() R|kotlin/Int|
public constructor(): R|test/SimpleTypeAnnotation|
@@ -10,7 +10,7 @@
}
public final class TypeAnnotationWithArguments : R|kotlin/Any| {
public final fun foo(param: R|kotlin/ranges/IntRange|): R|kotlin/Unit|
public final fun foo(param: @R|test/Ann|(x = String(param), y = Double(3.14)) R|kotlin/ranges/IntRange|): @R|test/Ann|(x = String(fun), y = Double(2.72)) R|kotlin/Unit|
public constructor(): R|test/TypeAnnotationWithArguments|
@@ -1,4 +1,4 @@
public final fun builder(c: R|class error: createSuspendFunctionType not supported|): R|kotlin/Unit|
public final fun builder(c: @R|kotlin/ExtensionFunctionType|() R|class error: createSuspendFunctionType not supported|): R|kotlin/Unit|
public final class Controller : R|kotlin/Any| {
public final suspend fun suspendFun(): R|kotlin/Unit|
@@ -1,5 +1,5 @@
public open class MethodWithFunctionTypes : R|kotlin/Any| {
public open fun foo(f: R|kotlin/Function1<kotlin/String, kotlin/String>|): R|kotlin/Function1<kotlin/String, kotlin/String>|?
public open fun foo(f: R|kotlin/Function1<kotlin/String, kotlin/String>|): @R|kotlin/ExtensionFunctionType|() R|kotlin/Function1<kotlin/String, kotlin/String>|?
public constructor(): R|test/MethodWithFunctionTypes|
@@ -1,6 +1,6 @@
public final fun test1(): R|class error: createSuspendFunctionType not supported|
public final fun test2(): R|class error: createSuspendFunctionType not supported|
public final fun test2(): @R|kotlin/ExtensionFunctionType|() R|class error: createSuspendFunctionType not supported|
public final fun test3(): R|kotlin/collections/List<class error: createSuspendFunctionType not supported>|
@@ -1,4 +1,4 @@
public final fun <P> foo(x: R|kotlin/Function1<test/Foo<P>, kotlin/Unit>|): R|kotlin/Unit|
public final fun <P> foo(x: @R|kotlin/ExtensionFunctionType|() R|kotlin/Function1<test/Foo<P>, kotlin/Unit>|): R|kotlin/Unit|
public final class Foo<T> : R|kotlin/Any| {
public constructor<T>(): R|test/Foo<T>|