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:
@@ -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}")
|
||||
|
||||
@@ -841,6 +841,14 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
||||
visitCall(getClassCall)
|
||||
}
|
||||
|
||||
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||
classReferenceExpression.annotations.renderAnnotations()
|
||||
print("<getClass>")
|
||||
print("(")
|
||||
classReferenceExpression.typeRef.accept(this)
|
||||
print(")")
|
||||
}
|
||||
|
||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
|
||||
arrayOfCall.annotations.renderAnnotations()
|
||||
print("<implicitArrayOf>")
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
interface FirClassReferenceExpression : FirExpression {
|
||||
val typeRef: FirTypeRef
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitClassReferenceExpression(this, data)
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.expressions.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
class FirClassReferenceExpressionImpl(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
override var typeRef: FirTypeRef
|
||||
) : FirAbstractExpression(session, psi), FirClassReferenceExpression {
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
typeRef = typeRef.transformSingle(transformer, data)
|
||||
return super<FirAbstractExpression>.transformChildren(transformer, data)
|
||||
}
|
||||
}
|
||||
+8
@@ -220,6 +220,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformOperatorCall(typeOperatorCall, data)
|
||||
}
|
||||
|
||||
open fun transformClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: D): CompositeTransformResult<FirStatement> {
|
||||
return transformExpression(classReferenceExpression, data)
|
||||
}
|
||||
|
||||
open fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: D): CompositeTransformResult<FirStatement> {
|
||||
return transformExpression(constExpression, data)
|
||||
}
|
||||
@@ -416,6 +420,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformClass(klass, data)
|
||||
}
|
||||
|
||||
final override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformClassReferenceExpression(classReferenceExpression, data)
|
||||
}
|
||||
|
||||
final override fun visitComponentCall(componentCall: FirComponentCall, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformComponentCall(componentCall, data)
|
||||
}
|
||||
|
||||
@@ -220,6 +220,10 @@ abstract class FirVisitor<out R, in D> {
|
||||
return visitOperatorCall(typeOperatorCall, data)
|
||||
}
|
||||
|
||||
open fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: D): R {
|
||||
return visitExpression(classReferenceExpression, data)
|
||||
}
|
||||
|
||||
open fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: D): R {
|
||||
return visitExpression(constExpression, data)
|
||||
}
|
||||
|
||||
+8
@@ -220,6 +220,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitOperatorCall(typeOperatorCall, null)
|
||||
}
|
||||
|
||||
open fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||
visitExpression(classReferenceExpression, null)
|
||||
}
|
||||
|
||||
open fun <T> visitConstExpression(constExpression: FirConstExpression<T>) {
|
||||
visitExpression(constExpression, null)
|
||||
}
|
||||
@@ -416,6 +420,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitClass(klass)
|
||||
}
|
||||
|
||||
final override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: Nothing?) {
|
||||
visitClassReferenceExpression(classReferenceExpression)
|
||||
}
|
||||
|
||||
final override fun visitComponentCall(componentCall: FirComponentCall, data: Nothing?) {
|
||||
visitComponentCall(componentCall)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user