Kapt: Calculate constant values in the similar way.

Always use originalElement in JeAnnotationValue factory.
(cherry picked from commit 0ff9584)
This commit is contained in:
Yan Zhulanow
2016-08-03 20:04:14 +03:00
committed by Yan Zhulanow
parent 4710fab49f
commit 462c7d91d2
4 changed files with 41 additions and 34 deletions
@@ -17,27 +17,34 @@
package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.AnnotationValueVisitor
fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue = when (psi) {
is PsiLiteral -> JeLiteralAnnotationValue(psi)
is PsiAnnotation -> JeAnnotationAnnotationValue(psi)
is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(psi)
is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(psi)
is PsiReferenceExpression -> {
// TODO check static final field -> primitive, reference to enum value
val element = psi.resolve()
if (element is PsiEnumConstant) {
JeEnumValueAnnotationValue(element)
}
else {
JeErrorAnnotationValue(psi)
fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue {
val original = psi.originalElement
val annotationValue = when (original) {
is PsiLiteral -> JeLiteralAnnotationValue(original)
is PsiAnnotation -> JeAnnotationAnnotationValue(original)
is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(original)
is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(original)
is PsiReferenceExpression -> {
val element = original.resolve()
if (element is PsiEnumConstant) {
JeEnumValueAnnotationValue(element)
}
else if (element is PsiField && element.hasInitializer()) {
JeAnnotationValue(element.initializer ?: error("Field should have an initializer"))
}
else {
JeErrorAnnotationValue(psi)
}
}
is PsiExpression -> JeExpressionAnnotationValue(original)
else -> throw AssertionError("Unsupported annotation element value: $psi (original = $original)")
}
is PsiExpression -> JeExpressionAnnotationValue(psi)
else -> throw AssertionError("Unsupported annotation element value: $psi")
return annotationValue
}
internal class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : AnnotationValue {
@@ -78,11 +85,11 @@ internal class JeLiteralAnnotationValue(val psi: PsiLiteral) : JePrimitiveAnnota
}
internal class JeExpressionAnnotationValue(val psi: PsiExpression) : JePrimitiveAnnotationValue() {
override fun getValue() = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper.computeConstantExpression(psi)
override fun getValue() = psi.calcConstantValue()
}
internal class JeArrayAnnotationValue(val psi: PsiArrayInitializerMemberValue) : AnnotationValue {
override fun getValue() = psi.initializers.map { JeAnnotationValue(it) }
override fun getValue() = psi.initializers.map(::JeAnnotationValue)
override fun <R : Any?, P : Any?> accept(v: AnnotationValueVisitor<R, P>, p: P) = v.visitArray(value, p)
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.*
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
@@ -37,11 +38,7 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
return containingClass?.let { JeTypeElement(it) }
}
override fun getConstantValue(): Any? {
val initializer = psi.initializer ?: return null
val evaluationHelper = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper
return evaluationHelper.computeConstantExpression(initializer)
}
override fun getConstantValue() = psi.initializer?.calcConstantValue()
override fun getKind() = when (psi) {
is PsiField -> ElementKind.FIELD
@@ -74,7 +74,7 @@ private fun getConstantValue(
when {
returnType == PsiType.NULL || returnType == PsiType.VOID -> unexpectedType("void")
jReturnType == String::class.java -> return calculateConstantValue(psiValue, evaluator)
jReturnType == String::class.java -> return (psiValue as? PsiExpression)?.calcConstantValue(evaluator)
jReturnType == Class::class.java -> {
val type = getObjectType(psiValue).toJeType(manager)
return MirroredTypeExceptionProxy(type)
@@ -105,7 +105,7 @@ private fun getConstantValue(
?: error("$psiValue can not be resolved to enum constant")
return AnnotationUtil.createEnumValue(jReturnType, enumConstant.name)
}
else -> return castPrimitiveValue(returnType, calculateConstantValue(psiValue, evaluator))
else -> return castPrimitiveValue(returnType, (psiValue as? PsiExpression)?.calcConstantValue(evaluator))
}
}
@@ -148,13 +148,6 @@ private fun longValue(value: Any?): Long = (value as? Number)?.toLong() ?: 0
private fun floatValue(value: Any?): Float = (value as? Number)?.toFloat() ?: 0f
private fun doubleValue(value: Any?): Double = (value as? Number)?.toDouble() ?: 0.0
private fun calculateConstantValue(value: PsiAnnotationMemberValue?, evaluator: PsiConstantEvaluationHelper) = when (value) {
is PsiLiteral -> value.value
is KtLightAnnotation.LightExpressionValue<*> -> value.getConstantValue()
is PsiExpression -> evaluator.computeConstantExpression(value)
else -> null
}
private fun unexpectedType(type: String): Nothing = error("Unexpected type: $type")
private fun unexpectedType(type: PsiType): Nothing = unexpectedType(type.presentableText)
@@ -16,10 +16,9 @@
package org.jetbrains.kotlin.java.model.internal
import com.intellij.psi.PsiModifier
import com.intellij.psi.*
import com.intellij.psi.PsiModifier.*
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation
import javax.lang.model.element.Modifier
private val HAS_DEFAULT by lazy {
@@ -50,6 +49,17 @@ private fun PsiModifierList.getJavaModifiers(): Set<Modifier> {
}
}
internal fun PsiExpression.calcConstantValue(evaluator: PsiConstantEvaluationHelper? = null): Any? {
return when (this) {
is PsiLiteral -> value
is KtLightAnnotation.LightExpressionValue<*> -> getConstantValue()
is PsiExpression -> (evaluator ?: getConstantEvaluator(this)).computeConstantExpression(this)
else -> null
}
}
private fun getConstantEvaluator(expression: PsiExpression) = JavaPsiFacade.getInstance(expression.project).constantEvaluationHelper
internal val PsiModifierListOwner.isStatic: Boolean
get() = hasModifierProperty(PsiModifier.STATIC)