Analysis API: separate constant values from annotation values

This commit is contained in:
Ilya Kirillov
2021-11-23 20:44:39 +01:00
parent 47c1da2845
commit f722a54c78
53 changed files with 302 additions and 415 deletions
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.annotations.KtLiteralAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtConstantAnnotationValue
internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget)
@@ -31,7 +31,7 @@ internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget:
}
return annotation?.let {
(it.arguments.firstOrNull()?.expression as? KtLiteralAnnotationValue<*>)?.value as? String
(it.arguments.firstOrNull()?.expression as? KtConstantAnnotationValue)?.constantValue?.value as? String
}
}
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.analysis.api.isValid
import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.annotations.KtLiteralAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtConstantAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
@@ -113,7 +114,7 @@ internal class FirLightFieldForPropertySymbol(
if (!propertySymbol.isConst) return@lazyPub null
if (!propertySymbol.isVal) return@lazyPub null
val constInitializer = propertySymbol.initializer as? KtConstantInitializerValue ?: return@lazyPub null
(constInitializer.constant as? KtLiteralAnnotationValue<*>)?.createPsiLiteral(this)
(constInitializer.constant as? KtConstantValue)?.createPsiLiteral(this)
}
override fun getInitializer(): PsiExpression? = _initializer
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.components.DefaultTypeClassIds
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
@@ -184,36 +185,36 @@ internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiA
annotationValue.arguments,
annotationValue.psi
)
else ->
createPsiLiteral(parent)?.let {
is KtConstantAnnotationValue -> {
this.constantValue.createPsiLiteral(parent)?.let {
when (it) {
is PsiLiteral -> FirPsiLiteral(sourcePsi, parent, it)
else -> FirPsiExpression(sourcePsi, parent, it)
}
}
}
is KtEnumEntryAnnotationValue -> {
val fqName = this.callableId?.asSingleFqName()?.asString() ?: return null
val psiExpression = PsiElementFactory.getInstance(parent.project).createExpressionFromText(fqName, parent)
FirPsiExpression(sourcePsi, parent, psiExpression)
}
KtUnsupportedAnnotationValue -> null
}
}
private fun KtAnnotationValue.asStringForPsiLiteral(): String? =
when (this) {
is KtEnumEntryAnnotationValue ->
"${callableId?.classId?.asSingleFqName()?.asString() ?: ""}.${callableId?.callableName}"
is KtLiteralAnnotationValue<*> -> {
when (val value = this.value) {
is String -> "\"${escapeString(value)}\""
is Long -> "${value}L"
is Float -> "${value}f"
else -> value?.toString() ?: "null"
}
}
else -> null
private fun KtConstantValue.asStringForPsiLiteral(): String =
when (val value = value) {
is String -> "\"${escapeString(value)}\""
is Long -> "${value}L"
is Float -> "${value}f"
else -> value?.toString() ?: "null"
}
internal fun KtAnnotationValue.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral() ?: return null
val instance = PsiElementFactory.getInstance(parent.project)
internal fun KtConstantValue.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral()
return try {
instance.createExpressionFromText(asString, parent)
PsiElementFactory.getInstance(parent.project).createExpressionFromText(asString, parent)
} catch (_: IncorrectOperationException) {
null
}