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 package org.jetbrains.kotlin.java.model.elements
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.AnnotationValue import javax.lang.model.element.AnnotationValue
import javax.lang.model.element.AnnotationValueVisitor import javax.lang.model.element.AnnotationValueVisitor
fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue = when (psi) { fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue {
is PsiLiteral -> JeLiteralAnnotationValue(psi) val original = psi.originalElement
is PsiAnnotation -> JeAnnotationAnnotationValue(psi) val annotationValue = when (original) {
is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(psi) is PsiLiteral -> JeLiteralAnnotationValue(original)
is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(psi) is PsiAnnotation -> JeAnnotationAnnotationValue(original)
is PsiReferenceExpression -> { is PsiArrayInitializerMemberValue -> JeArrayAnnotationValue(original)
// TODO check static final field -> primitive, reference to enum value is PsiClassObjectAccessExpression -> JeTypeAnnotationValue(original)
val element = psi.resolve() is PsiReferenceExpression -> {
if (element is PsiEnumConstant) { val element = original.resolve()
JeEnumValueAnnotationValue(element) if (element is PsiEnumConstant) {
} JeEnumValueAnnotationValue(element)
else { }
JeErrorAnnotationValue(psi) 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) return annotationValue
else -> throw AssertionError("Unsupported annotation element value: $psi")
} }
internal class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : 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() { 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 { 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) 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.*
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.java.model.* import org.jetbrains.kotlin.java.model.*
import org.jetbrains.kotlin.java.model.internal.calcConstantValue
import org.jetbrains.kotlin.java.model.types.toJeType import org.jetbrains.kotlin.java.model.types.toJeType
import javax.lang.model.element.Element import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementKind
@@ -37,11 +38,7 @@ class JeVariableElement(override val psi: PsiVariable) : JeElement(), VariableEl
return containingClass?.let { JeTypeElement(it) } return containingClass?.let { JeTypeElement(it) }
} }
override fun getConstantValue(): Any? { override fun getConstantValue() = psi.initializer?.calcConstantValue()
val initializer = psi.initializer ?: return null
val evaluationHelper = JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper
return evaluationHelper.computeConstantExpression(initializer)
}
override fun getKind() = when (psi) { override fun getKind() = when (psi) {
is PsiField -> ElementKind.FIELD is PsiField -> ElementKind.FIELD
@@ -74,7 +74,7 @@ private fun getConstantValue(
when { when {
returnType == PsiType.NULL || returnType == PsiType.VOID -> unexpectedType("void") 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 -> { jReturnType == Class::class.java -> {
val type = getObjectType(psiValue).toJeType(manager) val type = getObjectType(psiValue).toJeType(manager)
return MirroredTypeExceptionProxy(type) return MirroredTypeExceptionProxy(type)
@@ -105,7 +105,7 @@ private fun getConstantValue(
?: error("$psiValue can not be resolved to enum constant") ?: error("$psiValue can not be resolved to enum constant")
return AnnotationUtil.createEnumValue(jReturnType, enumConstant.name) 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 floatValue(value: Any?): Float = (value as? Number)?.toFloat() ?: 0f
private fun doubleValue(value: Any?): Double = (value as? Number)?.toDouble() ?: 0.0 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: String): Nothing = error("Unexpected type: $type")
private fun unexpectedType(type: PsiType): Nothing = unexpectedType(type.presentableText) private fun unexpectedType(type: PsiType): Nothing = unexpectedType(type.presentableText)
@@ -16,10 +16,9 @@
package org.jetbrains.kotlin.java.model.internal 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.PsiModifier.*
import com.intellij.psi.PsiModifierList import org.jetbrains.kotlin.asJava.elements.KtLightAnnotation
import com.intellij.psi.PsiModifierListOwner
import javax.lang.model.element.Modifier import javax.lang.model.element.Modifier
private val HAS_DEFAULT by lazy { 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 internal val PsiModifierListOwner.isStatic: Boolean
get() = hasModifierProperty(PsiModifier.STATIC) get() = hasModifierProperty(PsiModifier.STATIC)