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.FirNamedFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.*
|
import org.jetbrains.kotlin.fir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
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.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.*
|
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.AbstractFirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.service
|
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 {
|
private fun JavaAnnotationArgument.toFirExpression(): FirExpression {
|
||||||
// TODO: this.name
|
// TODO: this.name
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JavaLiteralAnnotationArgument -> when (value) {
|
is JavaLiteralAnnotationArgument -> {
|
||||||
null -> FirConstExpressionImpl(session, null, IrConstKind.Null, null)
|
val value = value
|
||||||
else -> FirErrorExpressionImpl(session, null, "Unknown value in JavaLiteralAnnotationArgument: $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 {
|
is JavaArrayAnnotationArgument -> FirArrayOfCallImpl(session, null).apply {
|
||||||
for (element in getElements()) {
|
for (element in getElements()) {
|
||||||
arguments += element.toFirExpression()
|
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 {
|
is JavaClassObjectAnnotationArgument -> FirGetClassCallImpl(session, null).apply {
|
||||||
// TODO
|
val referencedType = getReferencedType()
|
||||||
//arguments += getReferencedType().toFirType()
|
arguments += FirClassReferenceExpressionImpl(session, null, referencedType.toFirResolvedTypeRef())
|
||||||
}
|
}
|
||||||
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall()
|
is JavaAnnotationAsAnnotationArgument -> getAnnotation().toFirAnnotationCall()
|
||||||
else -> FirErrorExpressionImpl(session, null, "Unknown JavaAnnotationArgument: ${this::class.java}")
|
else -> FirErrorExpressionImpl(session, null, "Unknown JavaAnnotationArgument: ${this::class.java}")
|
||||||
|
|||||||
@@ -841,6 +841,14 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
|||||||
visitCall(getClassCall)
|
visitCall(getClassCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||||
|
classReferenceExpression.annotations.renderAnnotations()
|
||||||
|
print("<getClass>")
|
||||||
|
print("(")
|
||||||
|
classReferenceExpression.typeRef.accept(this)
|
||||||
|
print(")")
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
|
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
|
||||||
arrayOfCall.annotations.renderAnnotations()
|
arrayOfCall.annotations.renderAnnotations()
|
||||||
print("<implicitArrayOf>")
|
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)
|
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> {
|
open fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: D): CompositeTransformResult<FirStatement> {
|
||||||
return transformExpression(constExpression, data)
|
return transformExpression(constExpression, data)
|
||||||
}
|
}
|
||||||
@@ -416,6 +420,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
|||||||
return transformClass(klass, data)
|
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> {
|
final override fun visitComponentCall(componentCall: FirComponentCall, data: D): CompositeTransformResult<FirElement> {
|
||||||
return transformComponentCall(componentCall, data)
|
return transformComponentCall(componentCall, data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,6 +220,10 @@ abstract class FirVisitor<out R, in D> {
|
|||||||
return visitOperatorCall(typeOperatorCall, data)
|
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 {
|
open fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: D): R {
|
||||||
return visitExpression(constExpression, data)
|
return visitExpression(constExpression, data)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -220,6 +220,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
|||||||
visitOperatorCall(typeOperatorCall, null)
|
visitOperatorCall(typeOperatorCall, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||||
|
visitExpression(classReferenceExpression, null)
|
||||||
|
}
|
||||||
|
|
||||||
open fun <T> visitConstExpression(constExpression: FirConstExpression<T>) {
|
open fun <T> visitConstExpression(constExpression: FirConstExpression<T>) {
|
||||||
visitExpression(constExpression, null)
|
visitExpression(constExpression, null)
|
||||||
}
|
}
|
||||||
@@ -416,6 +420,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
|||||||
visitClass(klass)
|
visitClass(klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: Nothing?) {
|
||||||
|
visitClassReferenceExpression(classReferenceExpression)
|
||||||
|
}
|
||||||
|
|
||||||
final override fun visitComponentCall(componentCall: FirComponentCall, data: Nothing?) {
|
final override fun visitComponentCall(componentCall: FirComponentCall, data: Nothing?) {
|
||||||
visitComponentCall(componentCall)
|
visitComponentCall(componentCall)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user