JavaSymbolProvider: support different kinds of literals in annotations

Constants, enum entries, class references, arrays are covered here
Related to KT-29218
This commit is contained in:
Mikhail Glukhikh
2019-02-14 17:17:23 +03:00
parent f8e165dbe4
commit 74d89b1be2
7 changed files with 131 additions and 7 deletions
@@ -11,8 +11,11 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.service
@@ -61,23 +64,75 @@ class JavaSymbolProvider(
}
}
// TODO: use kind here
private fun <T> List<T>.createArrayOfCall(@Suppress("UNUSED_PARAMETER") kind: IrConstKind<T>): FirArrayOfCall {
return FirArrayOfCallImpl(session, null).apply {
for (element in this@createArrayOfCall) {
arguments += element.createConstant()
}
}
}
private fun Any?.createConstant(): FirExpression {
return when (this) {
is Byte -> FirConstExpressionImpl(session, null, IrConstKind.Byte, this)
is Short -> FirConstExpressionImpl(session, null, IrConstKind.Short, this)
is Int -> FirConstExpressionImpl(session, null, IrConstKind.Int, this)
is Long -> FirConstExpressionImpl(session, null, IrConstKind.Long, this)
is Char -> FirConstExpressionImpl(session, null, IrConstKind.Char, this)
is Float -> FirConstExpressionImpl(session, null, IrConstKind.Float, this)
is Double -> FirConstExpressionImpl(session, null, IrConstKind.Double, this)
is Boolean -> FirConstExpressionImpl(session, null, IrConstKind.Boolean, this)
is String -> FirConstExpressionImpl(session, null, IrConstKind.String, this)
null -> FirConstExpressionImpl(session, null, IrConstKind.Null, null)
else -> FirErrorExpressionImpl(session, null, "Unknown value in JavaLiteralAnnotationArgument: $this")
}
}
private fun JavaAnnotationArgument.toFirExpression(): FirExpression {
// TODO: this.name
return when (this) {
is JavaLiteralAnnotationArgument -> when (value) {
null -> FirConstExpressionImpl(session, null, IrConstKind.Null, null)
else -> FirErrorExpressionImpl(session, null, "Unknown value in JavaLiteralAnnotationArgument: $value")
is JavaLiteralAnnotationArgument -> {
val value = value
when (value) {
is ByteArray -> value.toList().createArrayOfCall(IrConstKind.Byte)
is ShortArray -> value.toList().createArrayOfCall(IrConstKind.Short)
is IntArray -> value.toList().createArrayOfCall(IrConstKind.Int)
is LongArray -> value.toList().createArrayOfCall(IrConstKind.Long)
is CharArray -> value.toList().createArrayOfCall(IrConstKind.Char)
is FloatArray -> value.toList().createArrayOfCall(IrConstKind.Float)
is DoubleArray -> value.toList().createArrayOfCall(IrConstKind.Double)
is BooleanArray -> value.toList().createArrayOfCall(IrConstKind.Boolean)
else -> value.createConstant()
}
}
is JavaArrayAnnotationArgument -> FirArrayOfCallImpl(session, null).apply {
for (element in getElements()) {
arguments += element.toFirExpression()
}
}
// TODO
//is JavaEnumValueAnnotationArgument -> {}
is JavaEnumValueAnnotationArgument -> {
FirFunctionCallImpl(session, null).apply {
val classId = this@toFirExpression.enumClassId
val entryName = this@toFirExpression.entryName
val calleeReference = if (classId != null && entryName != null) {
val callableSymbol = session.service<FirSymbolProvider>().getCallableSymbols(
CallableId(classId.packageFqName, classId.relativeClassName, entryName)
).firstOrNull()
callableSymbol?.let {
FirResolvedCallableReferenceImpl(session, null, entryName, it)
}
} else {
null
}
this.calleeReference = calleeReference
?: FirErrorNamedReference(session, null, "Strange Java enum value: ${this@toFirExpression}")
}
}
is JavaClassObjectAnnotationArgument -> FirGetClassCallImpl(session, null).apply {
// TODO
//arguments += getReferencedType().toFirType()
val referencedType = getReferencedType()
arguments += FirClassReferenceExpressionImpl(session, null, referencedType.toFirResolvedTypeRef())
}
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall()
else -> FirErrorExpressionImpl(session, null, "Unknown JavaAnnotationArgument: ${this::class.java}")