KtLightAnnotationForSourceEntry: made more verbose with errors in arrays in params (KT-21335, EA-107118)

This commit is contained in:
Nicolay Mitropolsky
2017-11-21 16:58:35 +03:00
committed by xiexed
parent e43bf90b9c
commit 23344783a5
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.asJava.elements package org.jetbrains.kotlin.asJava.elements
import com.intellij.openapi.diagnostic.Attachment
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.* import com.intellij.psi.*
@@ -37,6 +39,8 @@ import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.asJava.elements.lightAnnotations")
abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: () -> PsiAnnotation) : abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: () -> PsiAnnotation) :
KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> { KtLightElementBase(parent), PsiAnnotation, KtLightElement<KtCallElement, PsiAnnotation> {
override val clsDelegate by lazyPub(computeDelegate) override val clsDelegate by lazyPub(computeDelegate)
@@ -181,13 +185,17 @@ class KtLightAnnotationForSourceEntry(
valueOrigin: AnnotationValueOrigin valueOrigin: AnnotationValueOrigin
) : LightElementValue<PsiArrayInitializerMemberValue>(delegate, parent, valueOrigin), PsiArrayInitializerMemberValue { ) : LightElementValue<PsiArrayInitializerMemberValue>(delegate, parent, valueOrigin), PsiArrayInitializerMemberValue {
private val _initializers by lazyPub { private val _initializers by lazyPub {
delegate.initializers.mapIndexed { i, it -> delegate.initializers.mapIndexed { i, memberValue ->
wrapAnnotationValue(it, this, { wrapAnnotationValue(memberValue, this, {
originalExpression.let { originalExpression.let { ktOrigin ->
when (it) { when (ktOrigin) {
is KtCallElement -> it.valueArguments[i].getArgumentExpression()!! is KtCallElement -> ktOrigin.valueArguments.getOrNull(i)?.getArgumentExpression()
is KtCollectionLiteralExpression -> it.getInnerExpressions()[i] is KtCollectionLiteralExpression -> ktOrigin.getInnerExpressions().getOrNull(i)
else -> throw UnsupportedOperationException("cant process $it of type ${it?.javaClass}") else -> null
}.also {
if (it == null)
LOG.error("error wrapping ${memberValue.javaClass} for ${ktOrigin?.javaClass} in ${ktOrigin?.containingFile}",
Attachment("source_fragments.txt", "origin: '${psiReport(ktOrigin)}', delegate: ${psiReport(delegate)}"))
} }
} }
}) })
@@ -197,22 +205,26 @@ class KtLightAnnotationForSourceEntry(
override fun getInitializers() = _initializers override fun getInitializers() = _initializers
} }
private fun wrapAnnotationValue(value: PsiAnnotationMemberValue, parent: PsiElement, ktOrigin: AnnotationValueOrigin): PsiAnnotationMemberValue { private fun wrapAnnotationValue(value: PsiAnnotationMemberValue, parent: PsiElement, ktOrigin: AnnotationValueOrigin): PsiAnnotationMemberValue =
return when { when {
value is PsiLiteralExpression && value.value is String -> LightStringLiteral(value, parent, ktOrigin) value is PsiLiteralExpression && value.value is String -> LightStringLiteral(value, parent, ktOrigin)
value is PsiClassObjectAccessExpression -> LightClassLiteral(value, parent, ktOrigin) value is PsiClassObjectAccessExpression -> LightClassLiteral(value, parent, ktOrigin)
value is PsiExpression -> LightExpressionValue(value, parent, ktOrigin) value is PsiExpression -> LightExpressionValue(value, parent, ktOrigin)
value is PsiArrayInitializerMemberValue -> LightArrayInitializerValue(value, parent, ktOrigin) value is PsiArrayInitializerMemberValue -> LightArrayInitializerValue(value, parent, ktOrigin)
value is PsiAnnotation -> KtLightAnnotationForSourceEntry( value is PsiAnnotation -> {
value.qualifiedName!!, val origin = ktOrigin()
ktOrigin().let { val ktCallElement = origin?.asKtCall()
it?.asKtCall() ?: throw UnsupportedOperationException("cant convert $it to KtCallElement") val qualifiedName = value.qualifiedName
}, if (qualifiedName != null && ktCallElement != null)
parent, { value } KtLightAnnotationForSourceEntry(qualifiedName, ktCallElement, parent, { value })
) else {
else -> LightElementValue(value, parent, ktOrigin) LOG.error("can't convert ${origin?.javaClass} to KtCallElement in ${origin?.containingFile} (value = ${value.javaClass})",
} Attachment("source_fragments.txt", "origin: '${psiReport(origin)}', value: '${psiReport(value)}'"))
} LightElementValue(value, parent, ktOrigin) // or maybe create a LightErrorAnnotationMemberValue instead?
}
}
else -> LightElementValue(value, parent, ktOrigin)
}
override fun isPhysical() = true override fun isPhysical() = true
@@ -302,4 +314,15 @@ private fun KtElement.getResolvedCall(): ResolvedCall<out CallableDescriptor>? {
return this.getResolvedCall(context) return this.getResolvedCall(context)
} }
private fun PsiElement.asKtCall(): KtCallElement? = (this as? KtElement)?.getResolvedCall()?.call?.callElement as? KtCallElement private fun PsiElement.asKtCall(): KtCallElement? = (this as? KtElement)?.getResolvedCall()?.call?.callElement as? KtCallElement
private fun psiReport(psiElement: PsiElement?): String {
if (psiElement == null) return "null"
val text = try {
psiElement.text
}
catch (e: Exception) {
"${e.javaClass.simpleName}:${e.message}"
}
return "${psiElement.javaClass.canonicalName}[$text]"
}