[FIR LC] KT-58330 Introduce SymbolPsiClassObjectAccessExpression
A PSI expression created with `createExpressionFromText` has dummy parent, which might break some inspections (for example, it breaks `JamAttributeElement` class in Spring Framework Plugin in intellij) Modify `AbstractSymbolLightClassesParentingTestBase` to check values of annotations in light classes; implement `accept` in some of them ^KT-58330 Fixed Merge-request: KT-MR-9903 Merged-by: Roman Golyshev <roman.golyshev@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
957d8ee3d2
commit
0dbf218f0b
+15
-1
@@ -6,8 +6,8 @@
|
||||
package org.jetbrains.kotlin.light.classes.symbol.annotations
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.light.LightTypeElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -63,6 +63,20 @@ internal class SymbolPsiExpression(
|
||||
override fun getText(): String = psiExpression.text
|
||||
}
|
||||
|
||||
internal class SymbolPsiClassObjectAccessExpression(
|
||||
override val kotlinOrigin: KtElement?,
|
||||
lightParent: PsiElement,
|
||||
private val psiType: PsiType,
|
||||
) : SymbolPsiAnnotationMemberValue(kotlinOrigin, lightParent), PsiClassObjectAccessExpression {
|
||||
override fun getType(): PsiType = psiType
|
||||
override fun getOperand(): PsiTypeElement = LightTypeElementWithParent(this, type)
|
||||
override fun getText(): String = type.getCanonicalText(false) + ".class"
|
||||
}
|
||||
|
||||
private class LightTypeElementWithParent(private val lightParent: PsiElement, type: PsiType) : LightTypeElement(lightParent.manager, type) {
|
||||
override fun getParent(): PsiElement = lightParent
|
||||
}
|
||||
|
||||
internal class SymbolPsiReference(
|
||||
override val kotlinOrigin: KtElement?,
|
||||
lightParent: PsiElement,
|
||||
|
||||
+10
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.light.classes.symbol.annotations
|
||||
|
||||
import com.intellij.psi.JavaElementVisitor
|
||||
import com.intellij.psi.PsiAnnotationParameterList
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||
@@ -15,6 +17,14 @@ internal sealed class SymbolLightAbstractAnnotationParameterList(
|
||||
parent: SymbolLightAbstractAnnotation,
|
||||
) : KtLightElementBase(parent), PsiAnnotationParameterList {
|
||||
override val kotlinOrigin: KtElement? get() = (parent as SymbolLightAbstractAnnotation).kotlinOrigin?.valueArgumentList
|
||||
|
||||
override fun accept(visitor: PsiElementVisitor) {
|
||||
if (visitor is JavaElementVisitor) {
|
||||
visitor.visitAnnotationParameterList(this)
|
||||
} else {
|
||||
visitor.visitElement(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
+8
@@ -38,4 +38,12 @@ internal class SymbolNameValuePairForAnnotationArgument(
|
||||
override fun getLiteralValue(): String? = (value as? PsiLiteralExpression)?.value?.toString()
|
||||
|
||||
override fun getName(): String = constantValue.name.asString()
|
||||
|
||||
override fun accept(visitor: PsiElementVisitor) {
|
||||
if (visitor is JavaElementVisitor) {
|
||||
visitor.visitNameValuePair(this)
|
||||
} else {
|
||||
visitor.visitElement(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -205,22 +205,20 @@ private fun KtEnumEntryAnnotationValue.asPsiReferenceExpression(parent: PsiEleme
|
||||
return SymbolPsiReference(sourcePsi, parent, psiReference)
|
||||
}
|
||||
|
||||
private fun KtKClassAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiExpression? {
|
||||
private fun KtKClassAnnotationValue.toAnnotationMemberValue(parent: PsiElement): SymbolPsiClassObjectAccessExpression? {
|
||||
val typeString = when (this) {
|
||||
is KtKClassAnnotationValue.KtNonLocalKClassAnnotationValue -> classId.asSingleFqName().asString()
|
||||
is KtKClassAnnotationValue.KtLocalKClassAnnotationValue -> null
|
||||
is KtKClassAnnotationValue.KtErrorClassAnnotationValue -> unresolvedQualifierName
|
||||
} ?: return null
|
||||
|
||||
val canonicalText = psiType(
|
||||
val psiType = psiType(
|
||||
kotlinFqName = typeString,
|
||||
context = parent,
|
||||
boxPrimitiveType = false, /* TODO value.arrayNestedness > 0*/
|
||||
).let(TypeConversionUtil::erasure).getCanonicalText(false)
|
||||
).let(TypeConversionUtil::erasure)
|
||||
|
||||
return parent.project.withElementFactorySafe {
|
||||
createExpressionFromText("$canonicalText.class", parent)
|
||||
}
|
||||
return SymbolPsiClassObjectAccessExpression(sourcePsi, parent, psiType)
|
||||
}
|
||||
|
||||
private fun KtConstantValue.asStringForPsiExpression(): String =
|
||||
|
||||
+28
@@ -165,6 +165,30 @@ open class AbstractSymbolLightClassesParentingTestBase(
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitNameValuePair(pair: PsiNameValuePair) {
|
||||
checkParentAndVisitChildren(pair) {
|
||||
value?.let(::checkAnnotationMemberValue)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnnotationParameterList(list: PsiAnnotationParameterList) {
|
||||
checkParentAndVisitChildren(list) { visitor ->
|
||||
attributes.forEach { it.accept(visitor) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAnnotationMemberValue(memberValue: PsiAnnotationMemberValue) {
|
||||
checkParentAndVisitChildren(memberValue) {
|
||||
if (this is PsiClassObjectAccessExpression) {
|
||||
checkDeclarationParent(this.operand)
|
||||
}
|
||||
|
||||
if (this is PsiArrayInitializerMemberValue) {
|
||||
this.initializers.forEach(::checkAnnotationMemberValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDeclarationParent(declaration: PsiElement) {
|
||||
val expectedParent = declarationStack.lastOrNull() ?: return
|
||||
val parent = declaration.parent
|
||||
@@ -217,6 +241,10 @@ open class AbstractSymbolLightClassesParentingTestBase(
|
||||
assertions.assertTrue(modifierList.annotations.any { it == annotation }) {
|
||||
"$annotation is not found in ${modifierList.annotations}"
|
||||
}
|
||||
|
||||
checkParentAndVisitChildren(annotation, notCheckItself = true) { visitor ->
|
||||
parameterList.accept(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -23,6 +23,8 @@ abstract class AbstractSymbolLightClassesParentingTestByFqName(
|
||||
val ktFile = ktFiles.first()
|
||||
val lightClass = findLightClass(fqName, ktFile.project) ?: return
|
||||
|
||||
lightClass.accept(createLightElementsVisitor(module.directives, testServices.assertions))
|
||||
ignoreExceptionIfIgnoreDirectivePresent(module) {
|
||||
lightClass.accept(createLightElementsVisitor(module.directives, testServices.assertions))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ abstract class AbstractSymbolLightClassesTestBase(
|
||||
project: Project
|
||||
): String
|
||||
|
||||
private inline fun ignoreExceptionIfIgnoreDirectivePresent(module: TestModule, action: () -> Unit) {
|
||||
protected fun ignoreExceptionIfIgnoreDirectivePresent(module: TestModule, action: () -> Unit) {
|
||||
try {
|
||||
action()
|
||||
} catch (e: Throwable) {
|
||||
|
||||
Reference in New Issue
Block a user