diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt index 6bd4e194b45..ad99aef226e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt @@ -173,7 +173,7 @@ internal class SymbolLightFieldForProperty private constructor( } private val _initializer by lazyPub { - _initializerValue?.createPsiLiteral(this) + _initializerValue?.createPsiExpression(this) } override fun getInitializer(): PsiExpression? = _initializer diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt index 2b5f892c0b5..d729edc2e77 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt @@ -319,7 +319,7 @@ internal class SymbolLightAccessorMethod private constructor( containingPropertySymbolPointer.withSymbol(ktModule) { propertySymbol -> when (val initializer = propertySymbol.initializer) { - is KtConstantInitializerValue -> initializer.constant.createPsiLiteral(this@SymbolLightAccessorMethod) + is KtConstantInitializerValue -> initializer.constant.createPsiExpression(this@SymbolLightAccessorMethod) is KtConstantValueForAnnotation -> initializer.annotationValue.toAnnotationMemberValue(this@SymbolLightAccessorMethod) is KtNonConstantInitializerValue -> null null -> null diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt index bd89668fb72..26c66066d63 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.light.classes.symbol +import com.intellij.openapi.project.Project import com.intellij.psi.* import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager @@ -164,44 +165,39 @@ private fun escapeString(str: String): String = buildString { } } -internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiAnnotationMemberValue? { - return when (this) { - is KtArrayAnnotationValue -> - SymbolPsiArrayInitializerMemberValue(sourcePsi, parent) { arrayLiteralParent -> - values.mapNotNull { element -> element.toAnnotationMemberValue(arrayLiteralParent) } - } - - is KtAnnotationApplicationValue -> - SymbolLightSimpleAnnotation( - annotationValue.classId?.relativeClassName?.asString(), - parent, - annotationValue.arguments, - annotationValue.psi - ) - - is KtConstantAnnotationValue -> { - this.constantValue.createPsiLiteral(parent)?.let { - when (it) { - is PsiLiteral -> SymbolPsiLiteral(sourcePsi, parent, it) - else -> SymbolPsiExpression(sourcePsi, parent, it) - } - } +internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiAnnotationMemberValue? = when (this) { + is KtArrayAnnotationValue -> + SymbolPsiArrayInitializerMemberValue(sourcePsi, parent) { arrayLiteralParent -> + values.mapNotNull { element -> element.toAnnotationMemberValue(arrayLiteralParent) } } - is KtEnumEntryAnnotationValue -> asPsiReferenceExpression(parent) - KtUnsupportedAnnotationValue -> null - is KtKClassAnnotationValue -> toAnnotationMemberValue(parent) + is KtAnnotationApplicationValue -> + SymbolLightSimpleAnnotation( + fqName = annotationValue.classId?.relativeClassName?.asString(), + parent = parent, + arguments = annotationValue.arguments, + kotlinOrigin = annotationValue.psi, + ) + + is KtConstantAnnotationValue -> { + this.constantValue.createPsiExpression(parent)?.let { + if (it is PsiLiteral) + SymbolPsiLiteral(sourcePsi, parent, it) + else + SymbolPsiExpression(sourcePsi, parent, it) + } } + + is KtEnumEntryAnnotationValue -> asPsiReferenceExpression(parent) + is KtKClassAnnotationValue -> toAnnotationMemberValue(parent) + KtUnsupportedAnnotationValue -> null } private fun KtEnumEntryAnnotationValue.asPsiReferenceExpression(parent: PsiElement): SymbolPsiReference? { val fqName = this.callableId?.asSingleFqName()?.asString() ?: return null - val elementFactory = PsiElementFactory.getInstance(parent.project) - val psiReference = try { - elementFactory.createReferenceFromText(fqName, parent) - } catch (_: IncorrectOperationException) { - return null - } + val psiReference = parent.project.withElementFactorySafe { + createReferenceFromText(fqName, parent) + } ?: return null return SymbolPsiReference(sourcePsi, parent, psiReference) } @@ -212,36 +208,43 @@ private fun KtKClassAnnotationValue.toAnnotationMemberValue(parent: PsiElement): is KtKClassAnnotationValue.KtLocalKClassAnnotationValue -> null is KtKClassAnnotationValue.KtErrorClassAnnotationValue -> unresolvedQualifierName } ?: return null + val canonicalText = psiType( - typeString, parent, boxPrimitiveType = false, /* TODO value.arrayNestedness > 0*/ + kotlinFqName = typeString, + context = parent, + boxPrimitiveType = false, /* TODO value.arrayNestedness > 0*/ ).let(TypeConversionUtil::erasure).getCanonicalText(false) - return try { - PsiElementFactory.getInstance(parent.project).createExpressionFromText("$canonicalText.class", parent) - } catch (_: IncorrectOperationException) { - null + + return parent.project.withElementFactorySafe { + createExpressionFromText("$canonicalText.class", parent) } } -private fun KtConstantValue.asStringForPsiLiteral(): String = - when (val value = value) { - is Char -> "'$value'" - is String -> "\"${escapeString(value)}\"" - is Long -> "${value}L" - is Float -> "${value}f" - else -> value?.toString() ?: "null" - } +private fun KtConstantValue.asStringForPsiLiteral(): String = when (val value = value) { + is Char -> "'$value'" + is String -> "\"${escapeString(value)}\"" + is Long -> "${value}L" + is Float -> "${value}f" + null -> "null" + else -> value.toString() +} - -internal fun KtConstantValue.createPsiLiteral(parent: PsiElement): PsiExpression? { +internal fun KtConstantValue.createPsiExpression(parent: PsiElement): PsiExpression? { val asString = asStringForPsiLiteral() + return parent.project.withElementFactorySafe { + createExpressionFromText(asString, parent) + } +} + +private inline fun Project.withElementFactorySafe(crossinline action: PsiElementFactory.() -> T): T? { + val instance = PsiElementFactory.getInstance(this) return try { - PsiElementFactory.getInstance(parent.project).createExpressionFromText(asString, parent) + instance.action() } catch (_: IncorrectOperationException) { null } } - internal fun BitSet.copy(): BitSet = clone() as BitSet context(KtAnalysisSession)