diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt index 4e1a052effd..333eaab56f0 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/descriptorBased/base/Kt1DescUtils.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.inference.CapturedType @@ -280,8 +281,16 @@ internal fun ConstantValue<*>.toKtConstantValue(): KtConstantValue { internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue { return when (this) { - is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, null) - is EnumValue -> KtEnumEntryAnnotationValue(CallableId(enumClassId, enumEntryName), null) + is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, sourcePsi = null) + is EnumValue -> KtEnumEntryAnnotationValue(CallableId(enumClassId, enumEntryName), sourcePsi = null) + is KClassValue -> when (val value = value) { + is KClassValue.Value.LocalClass -> { + val descriptor = value.type.constructor.declarationDescriptor as ClassDescriptor + KtLocalKClassAnnotationValue(descriptor.source.getPsi() as KtClassOrObject, sourcePsi = null) + } + is KClassValue.Value.NormalClass -> KtNonLocalKClassAnnotationValue(value.classId, sourcePsi = null) + } + is AnnotationValue -> { KtAnnotationApplicationValue( KtAnnotationApplication( @@ -292,7 +301,6 @@ internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue { ) ) } - is KClassValue -> KtKClassValue(cl) else -> { KtConstantAnnotationValue(toKtConstantValue()) } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/KtFe10TypeRenderer.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/KtFe10TypeRenderer.kt index ab8db247fe2..b999723577d 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/KtFe10TypeRenderer.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/utils/KtFe10TypeRenderer.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewCapturedType import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor import org.jetbrains.kotlin.types.typeUtil.builtIns +import kotlin.reflect.KClass internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, private val isDebugText: Boolean = false) { private companion object { @@ -118,6 +119,7 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr is KtEnumEntryAnnotationValue -> append(value.callableId) is KtConstantAnnotationValue -> append(value.constantValue.constantValueKind.asString).append("(").append(value.constantValue.value).append(")") KtUnsupportedAnnotationValue -> append(KtUnsupportedAnnotationValue::class.java.simpleName) + is KtKClassAnnotationValue -> append(value.render()) } } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/FirAnnotationValueConverter.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/FirAnnotationValueConverter.kt index 1957d8c6888..dc03c9e8b77 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/FirAnnotationValueConverter.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/evaluate/FirAnnotationValueConverter.kt @@ -78,6 +78,7 @@ internal object FirAnnotationValueConverter { private fun FirExpression.convertConstantExpression( session: FirSession, ): KtAnnotationValue? { + val sourcePsi = psi as? KtElement return when (this) { is FirConstExpression<*> -> convertConstantExpression() is FirNamedArgumentExpression -> { @@ -87,11 +88,11 @@ internal object FirAnnotationValueConverter { expression.convertConstantExpression(session) } is FirVarargArgumentsExpression -> { - arguments.convertConstantExpression(session).toArrayConstantValueIfNecessary(psi as? KtElement) + arguments.convertConstantExpression(session).toArrayConstantValueIfNecessary(sourcePsi) } is FirArrayOfCall -> { // Desugared collection literals. - KtArrayAnnotationValue(argumentList.arguments.convertConstantExpression(session), psi as? KtElement) + KtArrayAnnotationValue(argumentList.arguments.convertConstantExpression(session), sourcePsi) } is FirFunctionCall -> { val reference = calleeReference as? FirResolvedNamedReference ?: return null @@ -126,11 +127,19 @@ internal object FirAnnotationValueConverter { val reference = calleeReference as? FirResolvedNamedReference ?: return null when (val resolvedSymbol = reference.resolvedSymbol) { is FirEnumEntrySymbol -> { - KtEnumEntryAnnotationValue(resolvedSymbol.callableId, psi as? KtElement) + KtEnumEntryAnnotationValue(resolvedSymbol.callableId, sourcePsi) } else -> null } } + is FirGetClassCall -> { + val symbol = (argument as FirResolvedQualifier).symbol + when { + symbol == null -> KtErrorClassAnnotationValue(sourcePsi) + symbol.classId.isLocal -> KtLocalKClassAnnotationValue(symbol.fir.psi as KtClassOrObject, sourcePsi) + else -> KtNonLocalKClassAnnotationValue(symbol.classId, sourcePsi) + } + } else -> null } ?: FirCompileTimeConstantEvaluator.evaluate(this)?.convertConstantExpression() } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValue.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValue.kt index 0cfbd942d94..30fa488932d 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValue.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValue.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.annotations import org.jetbrains.kotlin.analysis.api.base.KtConstantValue import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtElement /** @@ -47,6 +48,22 @@ public class KtAnnotationApplicationValue( } +public sealed class KtKClassAnnotationValue : KtAnnotationValue() + +public class KtNonLocalKClassAnnotationValue( + public val classId: ClassId, + override val sourcePsi: KtElement?, +) : KtKClassAnnotationValue() + +public class KtLocalKClassAnnotationValue( + public val ktClass: KtClassOrObject, + override val sourcePsi: KtElement?, +) : KtKClassAnnotationValue() + +public class KtErrorClassAnnotationValue( + override val sourcePsi: KtElement?, +) : KtKClassAnnotationValue() + public class KtEnumEntryAnnotationValue( public val callableId: CallableId?, override val sourcePsi: KtElement?, diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValueRenderer.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValueRenderer.kt index 5208e1a6ec7..7fc3d406987 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValueRenderer.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/annotations/KtAnnotationValueRenderer.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.analysis.api.annotations +import org.jetbrains.kotlin.renderer.render + public object KtAnnotationValueRenderer { public fun render(value: KtAnnotationValue): String = buildString { renderConstantValue(value) @@ -25,11 +27,23 @@ public object KtAnnotationValueRenderer { renderConstantAnnotationValue(value) } KtUnsupportedAnnotationValue -> { - append("KtUnsupportedConstantValue") + append("error(\"non-annotation value\")") + } + is KtKClassAnnotationValue -> { + renderKClassAnnotationValue(value) } } } + private fun StringBuilder.renderKClassAnnotationValue(value: KtKClassAnnotationValue) { + when (value) { + is KtErrorClassAnnotationValue -> append("UNRESOLVED_CLASS") + is KtLocalKClassAnnotationValue -> append(value.ktClass.nameAsName?.render()) + is KtNonLocalKClassAnnotationValue -> append(value.classId.asSingleFqName().render()) + } + append("::class") + } + private fun StringBuilder.renderConstantAnnotationValue(value: KtConstantAnnotationValue) { append(KtConstantValueRenderer.render(value.constantValue)) } diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onClass.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onClass.txt index 693d4cdbbaf..19beb82127e 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onClass.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onClass.txt @@ -1,5 +1,5 @@ KtDeclaration: KtClass Foo annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onFunction.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onFunction.txt index 0eaf3f0b7a2..171ea88797c 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onFunction.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onFunction.txt @@ -1,5 +1,5 @@ KtDeclaration: KtNamedFunction foo annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onProperty.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onProperty.txt index ce1fe561f86..ac4e2d85b77 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onProperty.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onProperty.txt @@ -1,5 +1,5 @@ KtDeclaration: KtProperty foo annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onTypeAlias.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onTypeAlias.txt index 5503759d3be..41486e9e1d4 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onTypeAlias.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/direct/onTypeAlias.txt @@ -1,5 +1,5 @@ KtDeclaration: KtTypeAlias Foo annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onGetter.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onGetter.txt index ddad4930118..ad0fa1e8c31 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onGetter.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onGetter.txt @@ -1,5 +1,5 @@ KtDeclaration: KtPropertyAccessor null annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onParam.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onParam.txt index 46e850455af..3724cf13c8c 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onParam.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onParam.txt @@ -1,5 +1,5 @@ KtDeclaration: KtParameter bar annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onProperty.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onProperty.txt index ce1fe561f86..ac4e2d85b77 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onProperty.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onProperty.txt @@ -1,5 +1,5 @@ KtDeclaration: KtProperty foo annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onSetter.txt b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onSetter.txt index ddad4930118..ad0fa1e8c31 100644 --- a/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onSetter.txt +++ b/analysis/analysis-api/testData/annotations/annotationsOnDeclaration/useSite/onSetter.txt @@ -1,5 +1,5 @@ KtDeclaration: KtPropertyAccessor null annotations: [ - A(a = 1, c = KtUnsupportedConstantValue) + A(a = 1, c = kotlin.Int::class) psi: KtAnnotationEntry ] diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInit_UInt.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInit_UInt.txt index 17a56f94d1d..ab7bfd1b46b 100644 --- a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInit_UInt.txt +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInit_UInt.txt @@ -1,3 +1,3 @@ expression: 42u constant: 42 -constantValueKind: Long +constantValueKind: UInt diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/firLightUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/firLightUtils.kt index 0f98333d487..36d9b8c32c7 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/firLightUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/firLightUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.light.classes.symbol import com.intellij.psi.* +import com.intellij.psi.util.TypeConversionUtil import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightMember @@ -20,8 +21,10 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.* import org.jetbrains.kotlin.analysis.api.types.* +import org.jetbrains.kotlin.asJava.elements.psiType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.resolve.constants.KClassValue import java.util.* internal fun L.invalidAccess(): Nothing = @@ -199,6 +202,21 @@ internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiA FirPsiExpression(sourcePsi, parent, psiExpression) } KtUnsupportedAnnotationValue -> null + is KtErrorClassAnnotationValue -> null + is KtLocalKClassAnnotationValue -> null + is KtNonLocalKClassAnnotationValue -> toAnnotationMemberValue(parent) + } +} + +private fun KtNonLocalKClassAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiExpression? { + val fqName = classId.asSingleFqName() + val canonicalText = psiType( + fqName.asString(), 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 } } @@ -220,4 +238,5 @@ internal fun KtConstantValue.createPsiLiteral(parent: PsiElement): PsiExpression } } + internal fun BitSet.copy(): BitSet = clone() as BitSet diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt index 5f314f7def0..9465e8536a5 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt @@ -80,7 +80,7 @@ class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLi override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type) } -internal fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType { +fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType { if (!boxPrimitiveType) { when (kotlinFqName) { "kotlin.Int" -> return PsiType.INT