FIR IDE: make constant values symbol-free

This commit is contained in:
Jinseong Jeon
2021-09-20 15:21:26 -07:00
committed by Ilya Kirillov
parent f94dad7005
commit ffd0a5ed14
22 changed files with 44 additions and 59 deletions
@@ -109,7 +109,7 @@ internal class KtSymbolByFirBuilder private constructor(
fun buildEnumEntrySymbol(fir: FirEnumEntry) = symbolsCache.cache(fir) { KtFirEnumEntrySymbol(fir, resolveState, token, this) }
fun buildFileSymbol(fir: FirFile) = filesCache.cache(fir) { KtFirFileSymbol(fir, resolveState, token, this) }
fun buildFileSymbol(fir: FirFile) = filesCache.cache(fir) { KtFirFileSymbol(fir, resolveState, token) }
private val packageProvider = project.createPackageProvider(GlobalSearchScope.allScope(project))//todo scope
@@ -26,7 +26,7 @@ internal class KtFirCompileTimeConstantProvider(
when (val fir = expression.getOrBuildFir(firResolveState)) {
is FirExpression -> {
FirCompileTimeConstantEvaluator().evaluate(fir)?.let { KtFirConstantValueConverter.toConstantValue(it) }
?: KtFirConstantValueConverter.toConstantValue(fir, firResolveState.rootModuleSession, firSymbolBuilder)
?: KtFirConstantValueConverter.toConstantValue(fir, firResolveState.rootModuleSession)
}
else -> throwUnexpectedFirElementError(fir, expression)
}
@@ -5,9 +5,6 @@
package org.jetbrains.kotlin.analysis.api.fir.evaluate
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.analysis.api.fir.buildSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
@@ -28,12 +25,11 @@ internal object KtFirConstantValueConverter {
fun toNamedConstantValue(
argumentMapping: Map<String, FirExpression>,
session: FirSession,
firSymbolBuilder: KtSymbolByFirBuilder
): List<KtNamedConstantValue> =
argumentMapping.map { (name, expression) ->
KtNamedConstantValue(
name,
expression.convertConstantExpression(session, firSymbolBuilder) ?: KtUnsupportedConstantValue
expression.convertConstantExpression(session) ?: KtUnsupportedConstantValue
)
}
@@ -47,9 +43,8 @@ internal object KtFirConstantValueConverter {
private fun Collection<FirExpression>.convertConstantExpression(
session: FirSession,
firSymbolBuilder: KtSymbolByFirBuilder
): Collection<KtConstantValue> =
mapNotNull { it.convertConstantExpression(session, firSymbolBuilder) }
mapNotNull { it.convertConstantExpression(session) }
private fun Collection<KtConstantValue>.toArrayConstantValueIfNecessary(kotlinOrigin: KtElement?): KtConstantValue {
return if (size == 1)
@@ -61,25 +56,23 @@ internal object KtFirConstantValueConverter {
fun toConstantValue(
firExpression: FirExpression,
session: FirSession,
firSymbolBuilder: KtSymbolByFirBuilder
): KtConstantValue? =
firExpression.convertConstantExpression(session, firSymbolBuilder)
firExpression.convertConstantExpression(session)
private fun FirExpression.convertConstantExpression(
session: FirSession,
firSymbolBuilder: KtSymbolByFirBuilder
): KtConstantValue? {
return when (this) {
is FirConstExpression<*> -> convertConstantExpression()
is FirNamedArgumentExpression -> {
expression.convertConstantExpression(session, firSymbolBuilder)
expression.convertConstantExpression(session)
}
is FirVarargArgumentsExpression -> {
arguments.convertConstantExpression(session, firSymbolBuilder)
arguments.convertConstantExpression(session)
.toArrayConstantValueIfNecessary(realPsi as? KtElement)
}
is FirArrayOfCall -> {
argumentList.arguments.convertConstantExpression(session, firSymbolBuilder)
argumentList.arguments.convertConstantExpression(session)
.toArrayConstantValueIfNecessary(realPsi as? KtElement)
}
is FirFunctionCall -> {
@@ -93,15 +86,15 @@ internal object KtFirConstantValueConverter {
resultMap[param.name.asString()] = arg
}
KtAnnotationConstantValue(
resolvedSymbol.callableId.className?.asString(),
toNamedConstantValue(resultMap, session, firSymbolBuilder),
resolvedSymbol.callableId.classId,
toNamedConstantValue(resultMap, session),
this.realPsi as? KtCallElement
)
} else null
}
is FirNamedFunctionSymbol -> {
if (resolvedSymbol.callableId.asSingleFqName() in ArrayFqNames.ARRAY_CALL_FQ_NAMES)
argumentList.arguments.convertConstantExpression(session, firSymbolBuilder)
argumentList.arguments.convertConstantExpression(session)
.toArrayConstantValueIfNecessary(realPsi as? KtElement)
else null
}
@@ -112,10 +105,7 @@ internal object KtFirConstantValueConverter {
val reference = calleeReference as? FirResolvedNamedReference ?: return null
when (val resolvedSymbol = reference.resolvedSymbol) {
is FirEnumEntrySymbol -> {
KtEnumEntryConstantValue(
resolvedSymbol.fir.buildSymbol(firSymbolBuilder) as KtEnumEntrySymbol,
realPsi as? KtElement
)
KtEnumEntryConstantValue(resolvedSymbol.callableId, realPsi as? KtElement)
}
else -> null
}
@@ -35,7 +35,7 @@ internal class KtFirAnonymousObjectSymbol(
override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.moduleData.session) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -59,7 +59,7 @@ internal class KtFirConstructorSymbol(
override val visibility: Visibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -27,7 +27,6 @@ internal class KtFirFileSymbol(
fir: FirFile,
resolveState: FirModuleResolveState,
override val token: ValidityToken,
_builder: KtSymbolByFirBuilder,
) : KtFileSymbol(), KtSymbolWithDeclarations, KtFirSymbol<FirFile> {
override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.moduleData.session) }
@@ -37,7 +36,7 @@ internal class KtFirFileSymbol(
TODO("Creating pointers for files from library is not supported yet")
}
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -64,7 +64,7 @@ internal class KtFirFunctionSymbol(
override val hasStableParameterNames: Boolean = firRef.withFir { it.getHasStableParameterNames(it.moduleData.session) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -72,7 +72,7 @@ internal class KtFirKotlinPropertySymbol(
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir ->
fir.initializer?.let { KtFirConstantValueConverter.toConstantValue(it, resolveState.rootModuleSession, _builder) }
fir.initializer?.let { KtFirConstantValueConverter.toConstantValue(it, resolveState.rootModuleSession) }
}
override val symbolKind: KtSymbolKind
get() = firRef.withFir { fir ->
@@ -85,7 +85,7 @@ internal class KtFirKotlinPropertySymbol(
override val visibility: Visibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -69,7 +69,7 @@ internal class KtFirNamedClassOrObjectSymbol(
else -> possiblyRawVisibility
}
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -59,7 +59,7 @@ internal class KtFirPropertyGetterSymbol(
}
override val modality: Modality get() = getModality()
override val visibility: Visibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -57,7 +57,7 @@ internal class KtFirPropertySetterSymbol(
override val modality: Modality get() = getModality()
override val visibility: Visibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -60,13 +60,13 @@ internal class KtFirSyntheticJavaPropertySymbol(
}
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir ->
fir.initializer?.let { KtFirConstantValueConverter.toConstantValue(it, resolveState.rootModuleSession, _builder) }
fir.initializer?.let { KtFirConstantValueConverter.toConstantValue(it, resolveState.rootModuleSession) }
}
override val modality: Modality get() = getModality()
override val visibility: Visibility get() = getVisibility()
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -37,7 +37,7 @@ internal class KtFirTypeAndAnnotations<T : FirDeclaration>(
override val annotations: List<KtAnnotationCall> by containingDeclaration.withFirAndCache { fir ->
typeRef(fir).annotations.map {
KtFirAnnotationCall(containingDeclaration, it, _builder)
KtFirAnnotationCall(containingDeclaration, it)
}
}
}
@@ -79,7 +79,7 @@ private fun List<FirTypeRef>.mapToTypeAndAnnotations(
builder: KtSymbolByFirBuilder,
) = map { typeRef ->
val annotations = typeRef.annotations.map { annotation ->
KtFirAnnotationCall(containingDeclaration, annotation, builder)
KtFirAnnotationCall(containingDeclaration, annotation)
}
KtSimpleFirTypeAndAnnotations(typeRef.coneType, annotations, builder, containingDeclaration.token)
}
@@ -45,7 +45,7 @@ internal class KtFirValueParameterSymbol(
override val annotatedType: KtTypeAndAnnotations by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
if (fir.isVararg) {
val annotations = fir.returnTypeRef.annotations.map { annotation ->
KtFirAnnotationCall(firRef, annotation, _builder)
KtFirAnnotationCall(firRef, annotation)
}
// There SHOULD always be an array element type (even if it is an error type, e.g., unresolved).
val arrayElementType = fir.returnTypeRef.coneType.arrayElementType()
@@ -58,7 +58,7 @@ internal class KtFirValueParameterSymbol(
override val hasDefaultValue: Boolean get() = firRef.withFir { it.defaultValue != null }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList(_builder) }
override val annotations: List<KtAnnotationCall> by cached { firRef.toAnnotationsList() }
override fun containsAnnotation(classId: ClassId): Boolean = firRef.containsAnnotation(classId)
override val annotationClassIds: Collection<ClassId> by cached { firRef.getAnnotationClassIds() }
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.psi.KtCallElement
internal class KtFirAnnotationCall(
private val containingDeclaration: FirRefWithValidityCheck<FirDeclaration>,
annotation: FirAnnotation,
_builder: KtSymbolByFirBuilder,
) : KtAnnotationCall() {
private val annotationCallRef by weakRef(annotation)
@@ -45,7 +44,6 @@ internal class KtFirAnnotationCall(
KtFirConstantValueConverter.toNamedConstantValue(
mapAnnotationParameters(annotationCallRef, fir.moduleData.session),
fir.moduleData.session,
_builder
)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.analysis.api.fir.symbols.annotations
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.analysis.api.fir.utils.FirRefWithValidityCheck
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveType
import org.jetbrains.kotlin.fir.FirSession
@@ -24,10 +23,8 @@ import org.jetbrains.kotlin.name.ClassId
internal fun FirAnnotation.getClassId(session: FirSession): ClassId? =
coneClassLikeType?.fullyExpandedType(session)?.classId
internal fun FirRefWithValidityCheck<FirAnnotatedDeclaration>.toAnnotationsList(
builder: KtSymbolByFirBuilder
) = withFir { fir ->
fir.annotations.map { KtFirAnnotationCall(this, it, builder) }
internal fun FirRefWithValidityCheck<FirAnnotatedDeclaration>.toAnnotationsList() = withFir { fir ->
fir.annotations.map { KtFirAnnotationCall(this, it) }
}
internal fun FirRefWithValidityCheck<FirAnnotatedDeclaration>.containsAnnotation(classId: ClassId): Boolean =
@@ -45,7 +45,7 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractHLApiSingleFil
}
is KtAnnotationConstantValue -> buildString {
append("KtAnnotationConstantValue(")
append(fqName)
append(classId?.relativeClassName)
append(", ")
arguments.joinTo(this, separator = ", ", prefix = "(", postfix = ")") {
"${it.name} = ${it.expression.stringRepresentation()}"
@@ -54,7 +54,7 @@ abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractHLApiSingleFil
}
is KtEnumEntryConstantValue -> buildString {
append("KtEnumEntryConstantValue(")
append(enumEntrySymbol.callableIdIfNonLocal ?: enumEntrySymbol.name)
append("$callableId")
append(")")
}
is KtLiteralConstantValue<*> -> buildString {
@@ -96,7 +96,7 @@ public object DebugSymbolRenderer {
"${value::class.simpleName!!}($symbolTag)"
}
is KtLiteralConstantValue<*> -> renderValue(value.value)
is KtEnumEntryConstantValue -> "KtEnumEntryConstantValue(${renderValue(value.enumEntrySymbol)})"
is KtEnumEntryConstantValue -> "KtEnumEntryConstantValue(${renderValue(value.callableId)})"
is KtNamedConstantValue -> "${renderValue(value.name)} = ${renderValue(value.expression)}"
is KtAnnotationCall -> buildString {
append(renderValue(value.classId))
@@ -5,7 +5,8 @@
package org.jetbrains.kotlin.analysis.api.symbols.markers
import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.types.ConstantValueKind
@@ -36,13 +37,13 @@ public class KtArrayConstantValue(
) : KtConstantValue()
public class KtAnnotationConstantValue(
public val fqName: String?,
public val classId: ClassId?,
public val arguments: List<KtNamedConstantValue>,
override val kotlinOrigin: KtCallElement?,
) : KtConstantValue()
public class KtEnumEntryConstantValue(
public val enumEntrySymbol: KtEnumEntrySymbol,
public val callableId: CallableId?,
override val kotlinOrigin: KtElement?,
) : KtConstantValue()
@@ -296,7 +296,7 @@ KtFirKotlinPropertySymbol:
kotlin/Deprecated
]
annotations: [
kotlin/Deprecated(level = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/DeprecationLevel.ERROR)), message = don't use j)
kotlin/Deprecated(level = KtEnumEntryConstantValue(kotlin/DeprecationLevel.ERROR), message = don't use j)
psi: KtAnnotationEntry
]
callableIdIfNonLocal: /j
@@ -332,7 +332,7 @@ KtFirKotlinPropertySymbol:
kotlin/Deprecated
]
annotations: [
kotlin/Deprecated(level = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/DeprecationLevel.HIDDEN)), message = don't use j2)
kotlin/Deprecated(level = KtEnumEntryConstantValue(kotlin/DeprecationLevel.HIDDEN), message = don't use j2)
psi: KtAnnotationEntry
]
callableIdIfNonLocal: /j2
@@ -3,7 +3,7 @@ KtFirNamedClassOrObjectSymbol:
kotlin/annotation/Target
]
annotations: [
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/annotation/AnnotationTarget.TYPE)))
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(kotlin/annotation/AnnotationTarget.TYPE))
psi: KtAnnotationEntry
]
classIdIfNonLocal: Anno1
@@ -30,7 +30,7 @@ KtFirNamedClassOrObjectSymbol:
kotlin/annotation/Target
]
annotations: [
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/annotation/AnnotationTarget.TYPE)))
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(kotlin/annotation/AnnotationTarget.TYPE))
psi: KtAnnotationEntry
]
classIdIfNonLocal: Anno2
@@ -57,7 +57,7 @@ KtFirNamedClassOrObjectSymbol:
kotlin/annotation/Target
]
annotations: [
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/annotation/AnnotationTarget.TYPE)))
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(kotlin/annotation/AnnotationTarget.TYPE))
psi: KtAnnotationEntry
]
classIdIfNonLocal: Anno3
@@ -84,7 +84,7 @@ KtFirNamedClassOrObjectSymbol:
kotlin/annotation/Target
]
annotations: [
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(KtFirEnumEntrySymbol(kotlin/annotation/AnnotationTarget.TYPE)))
kotlin/annotation/Target(allowedTargets = KtEnumEntryConstantValue(kotlin/annotation/AnnotationTarget.TYPE))
psi: KtAnnotationEntry
]
classIdIfNonLocal: Anno4
@@ -186,7 +186,7 @@ internal fun KtConstantValue.toAnnotationMemberValue(parent: PsiElement): PsiAnn
values.mapNotNull { element -> element.toAnnotationMemberValue(arrayLiteralParent) }
}
is KtAnnotationConstantValue ->
FirLightSimpleAnnotation(fqName, parent, arguments, kotlinOrigin)
FirLightSimpleAnnotation(classId?.relativeClassName?.asString(), parent, arguments, kotlinOrigin)
else ->
createPsiLiteral(parent)?.let {
when (it) {
@@ -200,7 +200,7 @@ internal fun KtConstantValue.toAnnotationMemberValue(parent: PsiElement): PsiAnn
private fun KtConstantValue.asStringForPsiLiteral(): String? =
when (this) {
is KtEnumEntryConstantValue ->
"${enumEntrySymbol.containingEnumClassIdIfNonLocal?.asSingleFqName()?.asString() ?: ""}.${enumEntrySymbol.name}"
"${callableId?.classId?.asSingleFqName()?.asString() ?: ""}.${callableId?.callableName}"
is KtLiteralConstantValue<*> -> {
when (val value = this.value) {
is String -> "\"${escapeString(value)}\""