[FIR] Add session parameter to all "element --> reference" utilities

`FirDeserializedEnumAccessExpression` requires session to build proper
  reference, so it's important to have it in all utilities, which may
  pass this element as input

^KT-64975
This commit is contained in:
Dmitriy Novozhilov
2024-01-17 16:56:31 +02:00
committed by Space Team
parent bd9cb2b7e0
commit 150ff1172e
34 changed files with 151 additions and 78 deletions
@@ -6,36 +6,106 @@
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.resolved
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
fun FirElement.toReference(): FirReference? {
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class UnsafeExpressionUtility
/**
* Returns the [FirReference] of this [FirElement], if available.
* The reference is resolved in the context of a use-site [session], which may be required to find a symbol for an ID-based expression.
*/
fun FirElement.toReference(session: FirSession): FirReference? {
return when (this) {
is FirExpression -> toReference()
is FirExpression -> toReferenceImpl(session)
is FirVariableAssignment -> calleeReference
is FirResolvable -> calleeReference
else -> null
}
}
fun FirExpression.toReference(): FirReference? {
/**
* Returns the [FirReference] of this [FirExpression], if available.
* The reference is resolved in the context of a use-site [session], which may be required to find a symbol for an ID-based expression.
*/
fun FirExpression.toReference(session: FirSession): FirReference? {
return toReferenceImpl(session)
}
/**
* This utility won't return proper reference for `FirEnumEntryDeserializedAccessExpression`,
* so use only if you are really sure that it be never called on this node
*
* In most cases it's better to use safe [toReference] methods with session parameter.
*/
@UnsafeExpressionUtility
fun FirExpression.toReferenceUnsafe(): FirReference? {
return toReferenceImpl(session = null)
}
private fun FirExpression.toReferenceImpl(session: FirSession?): FirReference? {
return when (this) {
is FirWrappedArgumentExpression -> expression.toResolvedCallableReference()
is FirSmartCastExpression -> originalExpression.toReference()
is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.toReference()
is FirWrappedArgumentExpression -> expression.toResolvedCallableReferenceImpl(session)
is FirSmartCastExpression -> originalExpression.toReferenceImpl(session)
is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.toReferenceImpl(session)
is FirResolvable -> calleeReference
else -> null
}
}
val FirVariableAssignment.calleeReference: FirReference? get() = lValue.toReference()
val FirVariableAssignment.calleeReference: FirReference?
get() {
// non-nullable session for `toReferenceImpl` is needed only for `FirEnumEntryDeserializedAccessExpression` value,
// which never can appear in the lhs of variable assignment
return lValue.toReferenceImpl(session = null)
}
fun FirExpression.toResolvedCallableReference(): FirResolvedNamedReference? {
return toReference()?.resolved
// --------------------------------------------------------------------------------------------------------
fun FirExpression.toResolvedCallableReference(session: FirSession): FirResolvedNamedReference? {
return toResolvedCallableReferenceImpl(session)
}
fun FirExpression.toResolvedCallableSymbol(): FirCallableSymbol<*>? {
return toResolvedCallableReference()?.resolvedSymbol as? FirCallableSymbol<*>?
fun FirResolvable.toResolvedCallableReference(): FirResolvedNamedReference? {
return calleeReference.resolved
}
/**
* This utility won't return proper reference for `FirEnumEntryDeserializedAccessExpression`,
* so use only if you are really sure that it be never called on this node
*
* In most cases it's better to use safe [toResolvedCallableReference] methods with session parameter
*/
@UnsafeExpressionUtility
fun FirExpression.toResolvedCallableReferenceUnsafe(): FirResolvedNamedReference? {
return toResolvedCallableReferenceImpl(session = null)
}
fun FirExpression.toResolvedCallableReferenceImpl(session: FirSession?): FirResolvedNamedReference? {
return toReferenceImpl(session)?.resolved
}
// --------------------------------------------------------------------------------------------------------
fun FirExpression.toResolvedCallableSymbol(session: FirSession): FirCallableSymbol<*>? {
return toResolvedCallableReference(session)?.resolvedSymbol as? FirCallableSymbol<*>?
}
fun FirResolvable.toResolvedCallableSymbol(): FirCallableSymbol<*>? {
return toResolvedCallableReference()?.resolvedSymbol as? FirCallableSymbol<*>
}
/**
* This utility won't return proper reference for `FirEnumEntryDeserializedAccessExpression`,
* so use only if you are really sure that it be never called on this node
*
* In most cases it's better to use safe [toResolvedCallableSymbol] methods with session parameter
*/
@UnsafeExpressionUtility
fun FirExpression.toResolvedCallableSymbolUnsafe(): FirCallableSymbol<*>? {
return toResolvedCallableReferenceUnsafe()?.resolvedSymbol as? FirCallableSymbol<*>?
}