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( PackagePartsCacheData(
packageProto, 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) return loadAnnotation(annotationClassId, result)
} }
private fun findAndDeserializeClass( private fun findAndDeserializeClass(
classId: ClassId, classId: ClassId,
parentContext: FirDeserializationContext? = null parentContext: FirDeserializationContext? = null
@@ -299,7 +301,11 @@ class KotlinDeserializedJvmSymbolsProvider(
val symbol = FirClassSymbol(classId) val symbol = FirClassSymbol(classId)
deserializeClassToSymbol( deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session, parentContext, classId, classProto, symbol, nameResolver, session,
parentContext ?: FirDeserializationContext.createForClass(
classId, classProto, nameResolver, session,
JvmBinaryAnnotationDeserializer(session, nameResolver)
),
this::findAndDeserializeClass this::findAndDeserializeClass
) )
val annotations = mutableListOf<FirAnnotationCall>() 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.getClassId
import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.serialization.deserialization.getName
class FirAnnotationDeserializer( abstract class AbstractAnnotationDeserializer(
private val session: FirSession, private val session: FirSession,
private val nameResolver: NameResolver private val nameResolver: NameResolver
) { ) {
private val protocol = BuiltInSerializerProtocol protected val protocol = BuiltInSerializerProtocol
fun loadClassAnnotations(classProto: ProtoBuf.Class): List<FirAnnotationCall> { fun loadClassAnnotations(classProto: ProtoBuf.Class): List<FirAnnotationCall> {
if (!Flags.HAS_ANNOTATIONS.get(classProto.flags)) return emptyList() if (!Flags.HAS_ANNOTATIONS.get(classProto.flags)) return emptyList()
@@ -65,13 +65,9 @@ class FirAnnotationDeserializer(
return annotations.map { deserializeAnnotation(it) } return annotations.map { deserializeAnnotation(it) }
} }
fun loadTypeAnnotations(typeProto: ProtoBuf.Type): List<FirAnnotationCall> { abstract 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) }
}
private fun deserializeAnnotation(proto: ProtoBuf.Annotation): FirAnnotationCall { fun deserializeAnnotation(proto: ProtoBuf.Annotation): FirAnnotationCall {
val classId = nameResolver.getClassId(proto.id) val classId = nameResolver.getClassId(proto.id)
val lookupTag = ConeClassLikeLookupTagImpl(classId) val lookupTag = ConeClassLikeLookupTagImpl(classId)
val symbol = lookupTag.toSymbol(session) val symbol = lookupTag.toSymbol(session)
@@ -126,12 +122,12 @@ class FirAnnotationDeserializer(
CLASS -> FirGetClassCallImpl(session, null).apply { CLASS -> FirGetClassCallImpl(session, null).apply {
val classId = nameResolver.getClassId(value.classId) val classId = nameResolver.getClassId(value.classId)
val lookupTag = ConeClassLikeLookupTagImpl(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) val referencedType = symbol.constructType(emptyArray(), isNullable = false)
arguments += FirClassReferenceExpressionImpl( arguments += FirClassReferenceExpressionImpl(
this@FirAnnotationDeserializer.session, null, this@AbstractAnnotationDeserializer.session, null,
FirResolvedTypeRefImpl( FirResolvedTypeRefImpl(
this@FirAnnotationDeserializer.session, null, referencedType, this@AbstractAnnotationDeserializer.session, null, referencedType,
isMarkedNullable = false, annotations = emptyList() isMarkedNullable = false, annotations = emptyList()
) )
) )
@@ -141,11 +137,11 @@ class FirAnnotationDeserializer(
val entryName = nameResolver.getName(value.enumValueId) val entryName = nameResolver.getName(value.enumValueId)
val entryClassId = classId.createNestedClassId(entryName) val entryClassId = classId.createNestedClassId(entryName)
val entryLookupTag = ConeClassLikeLookupTagImpl(entryClassId) val entryLookupTag = ConeClassLikeLookupTagImpl(entryClassId)
val entrySymbol = entryLookupTag.toSymbol(this@FirAnnotationDeserializer.session) val entrySymbol = entryLookupTag.toSymbol(this@AbstractAnnotationDeserializer.session)
this.calleeReference = entrySymbol?.let { this.calleeReference = entrySymbol?.let {
FirResolvedCallableReferenceImpl(this@FirAnnotationDeserializer.session, null, entryName, it) FirResolvedCallableReferenceImpl(this@AbstractAnnotationDeserializer.session, null, entryName, it)
} ?: FirErrorNamedReference( } ?: FirErrorNamedReference(
this@FirAnnotationDeserializer.session, null, this@AbstractAnnotationDeserializer.session, null,
errorReason = "Strange deserialized enum value: $classId.$entryName" errorReason = "Strange deserialized enum value: $classId.$entryName"
) )
} }
@@ -45,8 +45,9 @@ fun deserializeClassToSymbol(
val context = val context =
parentContext?.childContext(classProto.typeParameterList, nameResolver, TypeTable(classProto.typeTable)) parentContext?.childContext(classProto.typeParameterList, nameResolver, TypeTable(classProto.typeTable))
?: FirDeserializationContext ?: FirDeserializationContext.createForClass(
.createForClass(classId, classProto, nameResolver, session) classId, classProto, nameResolver, session, FirBuiltinAnnotationDeserializer(session, nameResolver)
)
typeParameters += context.typeDeserializer.ownTypeParameters.map { it.firUnsafe() } typeParameters += context.typeDeserializer.ownTypeParameters.map { it.firUnsafe() }
annotations += context.annotationDeserializer.loadClassAnnotations(classProto) 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 packageFqName: FqName,
val relativeClassName: FqName?, val relativeClassName: FqName?,
val typeDeserializer: FirTypeDeserializer, val typeDeserializer: FirTypeDeserializer,
val annotationDeserializer: AbstractAnnotationDeserializer,
val components: FirDeserializationComponents val components: FirDeserializationComponents
) { ) {
fun childContext( fun childContext(
@@ -48,23 +49,23 @@ class FirDeserializationContext(
FirTypeDeserializer( FirTypeDeserializer(
session, nameResolver, typeTable, typeParameterProtos, typeDeserializer session, nameResolver, typeTable, typeParameterProtos, typeDeserializer
), ),
components annotationDeserializer, components
) )
val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this) val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
val annotationDeserializer: FirAnnotationDeserializer = FirAnnotationDeserializer(session, nameResolver)
companion object { companion object {
fun createForPackage( fun createForPackage(
fqName: FqName, fqName: FqName,
packageProto: ProtoBuf.Package, packageProto: ProtoBuf.Package,
nameResolver: NameResolver, nameResolver: NameResolver,
session: FirSession session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer
) = createRootContext( ) = createRootContext(
nameResolver, nameResolver,
TypeTable(packageProto.typeTable), TypeTable(packageProto.typeTable),
session, session,
annotationDeserializer,
fqName, fqName,
relativeClassName = null, relativeClassName = null,
typeParameterProtos = emptyList() typeParameterProtos = emptyList()
@@ -74,11 +75,13 @@ class FirDeserializationContext(
classId: ClassId, classId: ClassId,
classProto: ProtoBuf.Class, classProto: ProtoBuf.Class,
nameResolver: NameResolver, nameResolver: NameResolver,
session: FirSession session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer
) = createRootContext( ) = createRootContext(
nameResolver, nameResolver,
TypeTable(classProto.typeTable), TypeTable(classProto.typeTable),
session, session,
annotationDeserializer,
classId.packageFqName, classId.packageFqName,
classId.relativeClassName, classId.relativeClassName,
classProto.typeParameterList classProto.typeParameterList
@@ -88,6 +91,7 @@ class FirDeserializationContext(
nameResolver: NameResolver, nameResolver: NameResolver,
typeTable: TypeTable, typeTable: TypeTable,
session: FirSession, session: FirSession,
annotationDeserializer: AbstractAnnotationDeserializer,
packageFqName: FqName, packageFqName: FqName,
relativeClassName: FqName?, relativeClassName: FqName?,
typeParameterProtos: List<ProtoBuf.TypeParameter> typeParameterProtos: List<ProtoBuf.TypeParameter>
@@ -105,6 +109,7 @@ class FirDeserializationContext(
typeParameterProtos, typeParameterProtos,
null null
), ),
annotationDeserializer,
FirDeserializationComponents() 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.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirEnumEntryImpl 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.FirDeserializationContext
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
import org.jetbrains.kotlin.fir.resolve.* 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 } val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
private val memberDeserializer by lazy { 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>() val lookup = mutableMapOf<ClassId, FirClassSymbol>()
@@ -1,17 +1,17 @@
public final class A : R|kotlin/Any| { 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 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 final val klass: R|kotlin/reflect/KClass<*>|
public get(): 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| 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 constructor(): R|test/A|
} }
public final class SimpleTypeAnnotation : R|kotlin/Any| { 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| public constructor(): R|test/SimpleTypeAnnotation|
@@ -10,7 +10,7 @@
} }
public final class TypeAnnotationWithArguments : R|kotlin/Any| { 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| 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 class Controller : R|kotlin/Any| {
public final suspend fun suspendFun(): R|kotlin/Unit| public final suspend fun suspendFun(): R|kotlin/Unit|
@@ -1,5 +1,5 @@
public open class MethodWithFunctionTypes : R|kotlin/Any| { 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| public constructor(): R|test/MethodWithFunctionTypes|
@@ -1,6 +1,6 @@
public final fun test1(): R|class error: createSuspendFunctionType not supported| 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>| 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 final class Foo<T> : R|kotlin/Any| {
public constructor<T>(): R|test/Foo<T>| public constructor<T>(): R|test/Foo<T>|