diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt index 9319abe0f3a..6afd7065a5e 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt @@ -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 accept(v: AnnotationValueVisitor, p: P) = v.visitArray(value, p) } diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt index d5a6cc20a0f..153eef1f9ed 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt @@ -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 diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/KotlinAnnotationProxyMaker.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/KotlinAnnotationProxyMaker.kt index 29384ab387e..be7f10752a8 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/KotlinAnnotationProxyMaker.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/KotlinAnnotationProxyMaker.kt @@ -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) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt index 2a80ba35d7b..02ed09d4c72 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/internalUtil.kt @@ -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 { } } +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)