Analysis API: introduce annotation value for KClass
This commit is contained in:
+11
-3
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.CallableId
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||||
@@ -280,8 +281,16 @@ internal fun ConstantValue<*>.toKtConstantValue(): KtConstantValue {
|
|||||||
|
|
||||||
internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
|
internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, null)
|
is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, sourcePsi = null)
|
||||||
is EnumValue -> KtEnumEntryAnnotationValue(CallableId(enumClassId, enumEntryName), 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 -> {
|
is AnnotationValue -> {
|
||||||
KtAnnotationApplicationValue(
|
KtAnnotationApplicationValue(
|
||||||
KtAnnotationApplication(
|
KtAnnotationApplication(
|
||||||
@@ -292,7 +301,6 @@ internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is KClassValue -> KtKClassValue(cl)
|
|
||||||
else -> {
|
else -> {
|
||||||
KtConstantAnnotationValue(toKtConstantValue())
|
KtConstantAnnotationValue(toKtConstantValue())
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.*
|
|||||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||||
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, private val isDebugText: Boolean = false) {
|
internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, private val isDebugText: Boolean = false) {
|
||||||
private companion object {
|
private companion object {
|
||||||
@@ -118,6 +119,7 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
|||||||
is KtEnumEntryAnnotationValue -> append(value.callableId)
|
is KtEnumEntryAnnotationValue -> append(value.callableId)
|
||||||
is KtConstantAnnotationValue -> append(value.constantValue.constantValueKind.asString).append("(").append(value.constantValue.value).append(")")
|
is KtConstantAnnotationValue -> append(value.constantValue.constantValueKind.asString).append("(").append(value.constantValue.value).append(")")
|
||||||
KtUnsupportedAnnotationValue -> append(KtUnsupportedAnnotationValue::class.java.simpleName)
|
KtUnsupportedAnnotationValue -> append(KtUnsupportedAnnotationValue::class.java.simpleName)
|
||||||
|
is KtKClassAnnotationValue -> append(value.render())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-3
@@ -78,6 +78,7 @@ internal object FirAnnotationValueConverter {
|
|||||||
private fun FirExpression.convertConstantExpression(
|
private fun FirExpression.convertConstantExpression(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
): KtAnnotationValue? {
|
): KtAnnotationValue? {
|
||||||
|
val sourcePsi = psi as? KtElement
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is FirConstExpression<*> -> convertConstantExpression()
|
is FirConstExpression<*> -> convertConstantExpression()
|
||||||
is FirNamedArgumentExpression -> {
|
is FirNamedArgumentExpression -> {
|
||||||
@@ -87,11 +88,11 @@ internal object FirAnnotationValueConverter {
|
|||||||
expression.convertConstantExpression(session)
|
expression.convertConstantExpression(session)
|
||||||
}
|
}
|
||||||
is FirVarargArgumentsExpression -> {
|
is FirVarargArgumentsExpression -> {
|
||||||
arguments.convertConstantExpression(session).toArrayConstantValueIfNecessary(psi as? KtElement)
|
arguments.convertConstantExpression(session).toArrayConstantValueIfNecessary(sourcePsi)
|
||||||
}
|
}
|
||||||
is FirArrayOfCall -> {
|
is FirArrayOfCall -> {
|
||||||
// Desugared collection literals.
|
// Desugared collection literals.
|
||||||
KtArrayAnnotationValue(argumentList.arguments.convertConstantExpression(session), psi as? KtElement)
|
KtArrayAnnotationValue(argumentList.arguments.convertConstantExpression(session), sourcePsi)
|
||||||
}
|
}
|
||||||
is FirFunctionCall -> {
|
is FirFunctionCall -> {
|
||||||
val reference = calleeReference as? FirResolvedNamedReference ?: return null
|
val reference = calleeReference as? FirResolvedNamedReference ?: return null
|
||||||
@@ -126,11 +127,19 @@ internal object FirAnnotationValueConverter {
|
|||||||
val reference = calleeReference as? FirResolvedNamedReference ?: return null
|
val reference = calleeReference as? FirResolvedNamedReference ?: return null
|
||||||
when (val resolvedSymbol = reference.resolvedSymbol) {
|
when (val resolvedSymbol = reference.resolvedSymbol) {
|
||||||
is FirEnumEntrySymbol -> {
|
is FirEnumEntrySymbol -> {
|
||||||
KtEnumEntryAnnotationValue(resolvedSymbol.callableId, psi as? KtElement)
|
KtEnumEntryAnnotationValue(resolvedSymbol.callableId, sourcePsi)
|
||||||
}
|
}
|
||||||
else -> null
|
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
|
else -> null
|
||||||
} ?: FirCompileTimeConstantEvaluator.evaluate(this)?.convertConstantExpression()
|
} ?: FirCompileTimeConstantEvaluator.evaluate(this)?.convertConstantExpression()
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.annotations
|
|||||||
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
|
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
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 class KtEnumEntryAnnotationValue(
|
||||||
public val callableId: CallableId?,
|
public val callableId: CallableId?,
|
||||||
override val sourcePsi: KtElement?,
|
override val sourcePsi: KtElement?,
|
||||||
|
|||||||
+15
-1
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.api.annotations
|
package org.jetbrains.kotlin.analysis.api.annotations
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.renderer.render
|
||||||
|
|
||||||
public object KtAnnotationValueRenderer {
|
public object KtAnnotationValueRenderer {
|
||||||
public fun render(value: KtAnnotationValue): String = buildString {
|
public fun render(value: KtAnnotationValue): String = buildString {
|
||||||
renderConstantValue(value)
|
renderConstantValue(value)
|
||||||
@@ -25,11 +27,23 @@ public object KtAnnotationValueRenderer {
|
|||||||
renderConstantAnnotationValue(value)
|
renderConstantAnnotationValue(value)
|
||||||
}
|
}
|
||||||
KtUnsupportedAnnotationValue -> {
|
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) {
|
private fun StringBuilder.renderConstantAnnotationValue(value: KtConstantAnnotationValue) {
|
||||||
append(KtConstantValueRenderer.render(value.constantValue))
|
append(KtConstantValueRenderer.render(value.constantValue))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtClass Foo
|
KtDeclaration: KtClass Foo
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtNamedFunction foo
|
KtDeclaration: KtNamedFunction foo
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtProperty foo
|
KtDeclaration: KtProperty foo
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtTypeAlias Foo
|
KtDeclaration: KtTypeAlias Foo
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtPropertyAccessor null
|
KtDeclaration: KtPropertyAccessor null
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtParameter bar
|
KtDeclaration: KtParameter bar
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtProperty foo
|
KtDeclaration: KtProperty foo
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
KtDeclaration: KtPropertyAccessor null
|
KtDeclaration: KtPropertyAccessor null
|
||||||
annotations: [
|
annotations: [
|
||||||
A(a = 1, c = KtUnsupportedConstantValue)
|
A(a = 1, c = kotlin.Int::class)
|
||||||
psi: KtAnnotationEntry
|
psi: KtAnnotationEntry
|
||||||
]
|
]
|
||||||
|
|||||||
analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInit_UInt.txt
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
expression: 42u
|
expression: 42u
|
||||||
constant: 42
|
constant: 42
|
||||||
constantValueKind: Long
|
constantValueKind: UInt
|
||||||
|
|||||||
+19
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.light.classes.symbol
|
package org.jetbrains.kotlin.light.classes.symbol
|
||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.util.TypeConversionUtil
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMember
|
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.KtFunctionSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
|
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
|
||||||
import org.jetbrains.kotlin.analysis.api.types.*
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal fun <L : Any> L.invalidAccess(): Nothing =
|
internal fun <L : Any> L.invalidAccess(): Nothing =
|
||||||
@@ -199,6 +202,21 @@ internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiA
|
|||||||
FirPsiExpression(sourcePsi, parent, psiExpression)
|
FirPsiExpression(sourcePsi, parent, psiExpression)
|
||||||
}
|
}
|
||||||
KtUnsupportedAnnotationValue -> null
|
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
|
internal fun BitSet.copy(): BitSet = clone() as BitSet
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLi
|
|||||||
override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type)
|
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) {
|
if (!boxPrimitiveType) {
|
||||||
when (kotlinFqName) {
|
when (kotlinFqName) {
|
||||||
"kotlin.Int" -> return PsiType.INT
|
"kotlin.Int" -> return PsiType.INT
|
||||||
|
|||||||
Reference in New Issue
Block a user