[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
@@ -35,7 +35,8 @@ internal fun mapAnnotationParameters(annotation: FirAnnotation): Map<Name, FirEx
withClassEntry("annotationTypeRef", annotation.annotationTypeRef)
@OptIn(UnresolvedExpressionTypeAccess::class)
withClassEntry("coneTypeOrNull", annotation.coneTypeOrNull)
annotation.toReference()?.let { withClassEntry("calleeReference", it) }
@OptIn(UnsafeExpressionUtility::class)
annotation.toReferenceUnsafe()?.let { withClassEntry("calleeReference", it) }
}
return annotation.argumentMapping.mapping.mapKeys { (name, _) -> name }
@@ -220,7 +220,7 @@ internal class KtFirCallResolver(
return when (this) {
is FirResolvable, is FirVariableAssignment -> {
when (val calleeReference = toReference()) {
when (val calleeReference = toReference(analysisSession.useSiteSession)) {
is FirResolvedErrorReference -> transformErrorReference(this, calleeReference)
is FirResolvedNamedReference -> when (calleeReference.resolvedSymbol) {
// `calleeReference.resolvedSymbol` isn't guaranteed to be callable. For example, function type parameters used in
@@ -794,7 +794,10 @@ internal class KtFirCallResolver(
@OptIn(SymbolInternals::class)
private fun getInitializerOfReferencedLocalVariable(variableReference: FirExpression): FirFunctionCall? {
return variableReference.toReference()?.toResolvedVariableSymbol()?.fir?.initializer as? FirFunctionCall
return variableReference.toReference(firResolveSession.useSiteFirSession)
?.toResolvedVariableSymbol()
?.fir
?.initializer as? FirFunctionCall
}
private fun getOperationPartiallyAppliedSymbolsForCompoundVariableAccess(
@@ -222,7 +222,7 @@ internal class KtFirExpressionTypeProvider(
val (ktCallElement, argumentExpression) = expression.getFunctionCallAsWithThisAsParameter() ?: return null
val firCall = ktCallElement.getOrBuildFir(firResolveSession)?.unwrapSafeCall() as? FirCall ?: return null
val callee = (firCall.toReference() as? FirResolvedNamedReference)?.resolvedSymbol
val callee = (firCall.toReference(firResolveSession.useSiteFirSession) as? FirResolvedNamedReference)?.resolvedSymbol
if (callee?.fir?.origin == FirDeclarationOrigin.SamConstructor) {
val substitutor = (firCall as? FirQualifiedAccessExpression)
?.createConeSubstitutorFromTypeArguments(discardErrorTypes = true)
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression
import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
@@ -98,7 +98,7 @@ private class CodeFragmentCapturedValueVisitor(
override fun visitElement(element: FirElement) {
processElement(element)
val lhs = (element as? FirVariableAssignment)?.lValue?.toResolvedCallableSymbol()
val lhs = (element as? FirVariableAssignment)?.lValue?.toResolvedCallableSymbol(session)
if (lhs != null) {
assignmentLhs.add(lhs)
}
@@ -138,7 +138,7 @@ class AllCandidatesResolver(private val firSession: FirSession) {
*/
private fun OverloadCandidate.preserveCalleeInapplicability() {
val callSite = candidate.callInfo.callSite
val calleeReference = callSite.toReference() as? FirDiagnosticHolder ?: return
val calleeReference = callSite.toReference(firSession) as? FirDiagnosticHolder ?: return
val diagnostic = calleeReference.diagnostic as? ConeInapplicableCandidateError ?: return
if (diagnostic.applicability != CandidateApplicability.INAPPLICABLE) return
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.JsStandardClassIds
object FirJsDefinedExternallyCallChecker : FirBasicExpressionChecker(MppCheckerKind.Common) {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val symbol = expression.toReference()?.toResolvedCallableSymbol() ?: return
val symbol = expression.toReference(context.session)?.toResolvedCallableSymbol() ?: return
if (symbol.callableId !in JsStandardClassIds.Callables.definedExternallyPropertyNames) {
return
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
@@ -42,7 +43,7 @@ object FirJsDynamicCallChecker : FirQualifiedAccessExpressionChecker(MppCheckerK
?: error("Resolved call callee without a callable symbol")
when {
expression is FirCall && expression.isArrayAccessWithMultipleIndices -> reporter.reportOn(
expression is FirCall && expression.isArrayAccessWithMultipleIndices(context.session) -> reporter.reportOn(
expression.source, FirJsErrors.WRONG_OPERATION_WITH_DYNAMIC, "indexed access with more than one index", context
)
expression is FirFunctionCall && expression.isInOperator -> reporter.reportOn(
@@ -62,22 +63,21 @@ object FirJsDynamicCallChecker : FirQualifiedAccessExpressionChecker(MppCheckerK
}
}
private val FirCall.isArrayAccessWithMultipleIndices: Boolean
get() {
val callee = toReference() as? FirNamedReference
?: return false
private fun FirCall.isArrayAccessWithMultipleIndices(session: FirSession): Boolean {
val callee = toReference(session) as? FirNamedReference
?: return false
if (callee.source?.kind != KtFakeSourceElementKind.ArrayAccessNameReference) {
return false
}
val arguments = (arguments.singleOrNull() as? FirVarargArgumentsExpression)?.arguments
?: return false
return callee.name == OperatorNameConventions.GET && arguments.size >= 2
|| callee.name == OperatorNameConventions.SET && arguments.size >= 3
if (callee.source?.kind != KtFakeSourceElementKind.ArrayAccessNameReference) {
return false
}
val arguments = (arguments.singleOrNull() as? FirVarargArgumentsExpression)?.arguments
?: return false
return callee.name == OperatorNameConventions.GET && arguments.size >= 2
|| callee.name == OperatorNameConventions.SET && arguments.size >= 3
}
private val FirFunctionCall.isInOperator
get() = calleeReference.resolved?.name == OperatorNameConventions.CONTAINS && origin == FirFunctionCallOrigin.Operator
@@ -39,7 +39,7 @@ object FirJvmProtectedInSuperClassCompanionCallChecker : FirBasicExpressionCheck
} ?: return
val dispatchClassSymbol = dispatchReceiver.resolvedType.toRegularClassSymbol(context.session) ?: return
val calleeReference = expression.toReference()
val calleeReference = expression.toReference(context.session)
val resolvedSymbol = calleeReference?.toResolvedCallableSymbol() ?: return
val visibility = if (resolvedSymbol is FirPropertySymbol) {
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.name.WebCommonStandardClassIds
object FirWasmDefinedExternallyCallChecker : FirBasicExpressionChecker(MppCheckerKind.Common) {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val symbol = expression.toReference()?.toResolvedCallableSymbol() ?: return
val symbol = expression.toReference(context.session)?.toResolvedCallableSymbol() ?: return
if (symbol.callableId != WebCommonStandardClassIds.Callables.JsDefinedExternally) {
return
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isConst
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
@@ -194,7 +193,7 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
override fun visitPropertyAccessExpression(
propertyAccessExpression: FirPropertyAccessExpression, data: Nothing?
): ConstantArgumentKind {
val propertySymbol = propertyAccessExpression.toReference()?.toResolvedCallableSymbol(discardErrorReference = true)
val propertySymbol = propertyAccessExpression.toReference(session)?.toResolvedCallableSymbol(discardErrorReference = true)
when (propertySymbol) {
// Null symbol means some error occurred.
// We use the same logic as in `visitErrorExpression`.
@@ -364,4 +363,4 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
?.coneTypeSafe<ConeLookupTagBasedType>()
?.lookupTag
?.toSymbol(session)
}
}
@@ -27,7 +27,7 @@ object FirDelegateFieldTypeMismatchChecker : FirRegularClassChecker(MppCheckerKi
val supertype = declaration.superTypeRefs[it]
val field = declaration.delegateFieldsMap?.get(it)?.fir ?: continue
val initializer = field.initializer ?: continue
val isReportedByErrorNodeDiagnosticCollector = initializer is FirCall && initializer.toReference()?.isError() == true
val isReportedByErrorNodeDiagnosticCollector = initializer is FirCall && initializer.toReference(context.session)?.isError() == true
if (
!isReportedByErrorNodeDiagnosticCollector &&
@@ -97,7 +97,7 @@ object FirEnumCompanionInEnumConstructorCallChecker : FirClassChecker(MppChecker
is FirResolvedQualifier -> {
this.resolvedType.toRegularClassSymbol(session)
}
else -> (this.toReference() as? FirThisReference)?.boundSymbol
else -> (this.toReference(session) as? FirThisReference)?.boundSymbol
} as? FirRegularClassSymbol
}
}
@@ -133,7 +133,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker(MppCheckerKind.Common) {
val argumentMapping = functionCall.resolvedArgumentMapping ?: return
for ((wrappedArgument, valueParameter) in argumentMapping) {
val argument = wrappedArgument.unwrapArgument()
val resolvedArgumentSymbol = argument.toResolvedCallableSymbol() as? FirVariableSymbol<*> ?: continue
val resolvedArgumentSymbol = argument.toResolvedCallableSymbol(session) as? FirVariableSymbol<*> ?: continue
val valueParameterOfOriginalInlineFunction = inlinableParameters.firstOrNull { it == resolvedArgumentSymbol }
if (valueParameterOfOriginalInlineFunction != null) {
@@ -163,7 +163,7 @@ object FirInlineDeclarationChecker : FirFunctionChecker(MppCheckerKind.Common) {
reporter: DiagnosticReporter,
) {
if (receiverExpression == null) return
val receiverSymbol = receiverExpression.toResolvedCallableSymbol() as? FirValueParameterSymbol ?: return
val receiverSymbol = receiverExpression.toResolvedCallableSymbol(session) as? FirValueParameterSymbol ?: return
if (receiverSymbol in inlinableParameters) {
if (!isInvokeOrInlineExtension(targetSymbol)) {
reporter.reportOn(
@@ -129,7 +129,7 @@ sealed class FirValueClassDeclarationChecker(mppKind: MppCheckerKind) : FirRegul
is FirField -> {
if (innerDeclaration.isSynthetic) {
val symbol = innerDeclaration.initializer?.toResolvedCallableSymbol()
val symbol = innerDeclaration.initializer?.toResolvedCallableSymbol(context.session)
if (context.languageVersionSettings.supportsFeature(LanguageFeature.InlineClassImplementationByDelegation) &&
symbol != null && symbol in primaryConstructorParametersSymbolsSet
) {
@@ -40,7 +40,7 @@ abstract class AbstractFirReflectionApiCallChecker : FirBasicExpressionChecker(M
// Do not report the diagnostic on kotlin-reflect sources.
if (isReflectionSource(context)) return
val resolvedReference = expression.toReference()?.resolved ?: return
val resolvedReference = expression.toReference(context.session)?.resolved ?: return
val referencedSymbol = resolvedReference.resolvedSymbol as? FirCallableSymbol ?: return
val containingClassId = (expression as? FirQualifiedAccessExpression)?.dispatchReceiver?.resolvedType?.fullyExpandedClassId(context.session)
@@ -49,7 +49,7 @@ object FirDeprecationChecker : FirBasicExpressionChecker(MppCheckerKind.Common)
if (expression is FirAnnotation) return // checked by FirDeprecatedTypeChecker
if (expression.isLhsOfAssignment(context)) return
val calleeReference = expression.toReference() ?: return
val calleeReference = expression.toReference(context.session) ?: return
val resolvedReference = calleeReference.resolved ?: return
val referencedSymbol = resolvedReference.resolvedSymbol
@@ -28,7 +28,7 @@ object FirOptInUsageAccessChecker : FirBasicExpressionChecker(MppCheckerKind.Com
if (expression.isLhsOfAssignment(context)) return
val resolvedSymbol = expression.toReference()?.toResolvedBaseSymbol() ?: return
val resolvedSymbol = expression.toReference(context.session)?.toResolvedBaseSymbol() ?: return
with(FirOptInUsageBaseChecker) {
when {
@@ -53,7 +53,7 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker(MppChecke
return when (expression.operation) {
FirOperation.AS, FirOperation.SAFE_AS -> {
if (arg is FirFunctionCall) {
val functionSymbol = arg.toResolvedCallableSymbol() as? FirFunctionSymbol<*>
val functionSymbol = arg.toResolvedCallableSymbol(context.session) as? FirFunctionSymbol<*>
if (functionSymbol != null && functionSymbol.isFunctionForExpectTypeFromCastFeature()) return false
}
@@ -60,7 +60,7 @@ class ErrorNodeDiagnosticCollectorComponent(
var source = reference.source
val callOrAssignment = context.callsOrAssignments.lastOrNull()?.takeIf {
// Use the source of the enclosing FirQualifiedAccess if it is exactly the call to the erroneous callee.
it.toReference() == reference
it.toReference(session) == reference
}
// Don't report duplicated unresolved reference on annotation entry (already reported on its type)
if (source?.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return
@@ -14,9 +14,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.toReference
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.FirThisReference
@@ -84,7 +82,8 @@ object FirDiagnosticRenderers {
}
val CALLEE_NAME = Renderer { element: FirExpression ->
when (val reference = element.unwrapSmartcastExpression().toReference()) {
@OptIn(UnsafeExpressionUtility::class)
when (val reference = element.unwrapSmartcastExpression().toReferenceUnsafe()) {
is FirNamedReference -> reference.name.asString()
is FirThisReference -> "this"
is FirSuperReference -> "super"
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCall
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
@@ -108,7 +107,7 @@ internal object FirToConstantValueTransformer : FirDefaultVisitor<ConstantValue<
val mapping = annotation.argumentMapping.mapping.convertToConstantValues(
data.session,
data.constValueProvider
).addEmptyVarargValuesFor(annotation.toReference()?.toResolvedFunctionSymbol())
).addEmptyVarargValuesFor(annotation.toReference(data.session)?.toResolvedFunctionSymbol())
return AnnotationValue.create(annotation.annotationTypeRef.coneType, mapping)
}
@@ -776,7 +776,7 @@ class CallAndReferenceGenerator(
)
}
val firConstructorSymbol = annotation.toResolvedCallableSymbol() as? FirConstructorSymbol
val firConstructorSymbol = annotation.toResolvedCallableSymbol(session) as? FirConstructorSymbol
?: run {
// Fallback for FirReferencePlaceholderForResolvedAnnotations from jar
val fir = coneType.lookupTag.toSymbol(session)?.fir as? FirClass
@@ -1021,7 +1021,7 @@ class CallAndReferenceGenerator(
putValueArgument(valueParameters.indexOf(parameter) + contextReceiverCount, irArgument)
}
if (visitor.annotationMode) {
val function = call.toReference()?.toResolvedCallableSymbol()?.fir as? FirFunction
val function = call.toReference(session)?.toResolvedCallableSymbol()?.fir as? FirFunction
for ((index, parameter) in valueParameters.withIndex()) {
if (parameter.isVararg && !argumentMapping.containsValue(parameter)) {
val value = if (function?.itOrExpectHasDefaultParameterValue(index) == true) {
@@ -1132,7 +1132,7 @@ class CallAndReferenceGenerator(
irConversionFunction: IrSimpleFunctionSymbol,
): IrExpression {
return if (argument.isIntegerLiteralOrOperatorCall() ||
argument.toReference()?.toResolvedCallableSymbol()?.let {
argument.toReference(session)?.toResolvedCallableSymbol()?.let {
it.resolvedStatus.isConst && it.isMarkedWithImplicitIntegerCoercion
} == true
) {
@@ -51,7 +51,7 @@ class FirAnnotationTypeQualifierResolver(
is FirArrayLiteral -> arguments.flatMap { it.toEnumNames() }
is FirVarargArgumentsExpression -> arguments.flatMap { it.toEnumNames() }
else -> {
val name = when (val reference = toReference()) {
val name = when (val reference = toReference(session)) {
is FirResolvedNamedReference ->
(reference.resolvedSymbol as? FirCallableSymbol<*>)?.callableId?.callableName?.asString()
is FirFromMissingDependenciesNamedReference -> reference.name.asString()
@@ -114,7 +114,7 @@ class FirCallResolver(
val resultFunctionCall = if (candidate != null && candidate.callInfo != result.info) {
// This branch support case for the call of the type `a.invoke()`
// 1. Handle candidate for `a`
(resolvedReceiver?.toReference() as? FirNamedReferenceWithCandidate)?.candidate?.updateSourcesOfReceivers()
(resolvedReceiver?.toReference(session) as? FirNamedReferenceWithCandidate)?.candidate?.updateSourcesOfReceivers()
// 2. Handle candidate for `invoke`
candidate.updateSourcesOfReceivers()
functionCall.copyAsImplicitInvokeCall {
@@ -533,7 +533,7 @@ private fun getExpectedTypeWithImplicitIntegerCoercion(
if (argument.isIntegerLiteralOrOperatorCall()) {
argument.resolvedType
} else {
argument.toReference()?.toResolvedCallableSymbol()?.takeIf {
argument.toReference(session)?.toResolvedCallableSymbol()?.takeIf {
it.rawStatus.isConst && it.isMarkedWithImplicitIntegerCoercion
}?.resolvedReturnType
}
@@ -320,7 +320,7 @@ object CheckDslScopeViolation : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
fun checkReceiver(receiver: FirExpression?) {
val thisReference = receiver?.toReference() as? FirThisReference ?: return
val thisReference = receiver?.toReference(context.session) as? FirThisReference ?: return
if (thisReference.isImplicit) {
checkImpl(
candidate,
@@ -755,7 +755,7 @@ internal object CheckHiddenDeclaration : ResolutionStage() {
/** Actual declarations are checked by [FirDeprecationChecker] */
if (symbol.isActual) return
val deprecation = symbol.getDeprecation(context.session, callInfo.callSite)
if (deprecation?.deprecationLevel == DeprecationLevelValue.HIDDEN || isHiddenForThisCallSite(symbol, callInfo, candidate)) {
if (deprecation?.deprecationLevel == DeprecationLevelValue.HIDDEN || isHiddenForThisCallSite(symbol, callInfo, candidate, context.session)) {
sink.yieldDiagnostic(HiddenCandidate)
}
}
@@ -764,8 +764,9 @@ internal object CheckHiddenDeclaration : ResolutionStage() {
symbol: FirCallableSymbol<*>,
callInfo: CallInfo,
candidate: Candidate,
session: FirSession
): Boolean {
val isSuperCall = callInfo.callSite.isSuperCall()
val isSuperCall = callInfo.callSite.isSuperCall(session)
if (symbol.fir.dispatchReceiverType == null || symbol !is FirNamedFunctionSymbol) return false
if (symbol.isHidden(isSuperCall)) return true
@@ -784,8 +785,8 @@ internal object CheckHiddenDeclaration : ResolutionStage() {
return result
}
private fun FirElement.isSuperCall(): Boolean =
this is FirQualifiedAccessExpression && explicitReceiver?.toReference() is FirSuperReference
private fun FirElement.isSuperCall(session: FirSession): Boolean =
this is FirQualifiedAccessExpression && explicitReceiver?.toReference(session) is FirSuperReference
private fun FirCallableSymbol<*>.isHidden(isSuperCall: Boolean): Boolean {
val fir = fir
@@ -166,7 +166,8 @@ private fun FirMemberDeclaration.getBackingFieldIfApplicable(): FirBackingField?
private fun isExplicitReceiverExpression(receiverExpression: FirExpression?): Boolean {
if (receiverExpression == null) return false
// Only FirThisReference may be a reference in implicit receiver
val thisReference = receiverExpression.toReference() as? FirThisReference ?: return true
@OptIn(UnsafeExpressionUtility::class)
val thisReference = receiverExpression.toReferenceUnsafe() as? FirThisReference ?: return true
return !thisReference.isImplicit
}
@@ -306,7 +306,9 @@ private object WhenOnEnumExhaustivenessChecker : WhenExhaustivenessChecker() {
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: MutableSet<FirEnumEntry>) {
if (!equalityOperatorCall.operation.let { it == FirOperation.EQ || it == FirOperation.IDENTITY }) return
val argument = equalityOperatorCall.arguments[1]
val symbol = argument.toResolvedCallableReference()?.resolvedSymbol as? FirVariableSymbol<*> ?: return
@OptIn(UnsafeExpressionUtility::class)
val symbol = argument.toResolvedCallableReferenceUnsafe()?.resolvedSymbol as? FirVariableSymbol<*> ?: return
val checkedEnumEntry = symbol.fir as? FirEnumEntry ?: return
data.add(checkedEnumEntry)
}
@@ -360,7 +362,8 @@ private object WhenOnSealedClassExhaustivenessChecker : WhenExhaustivenessChecke
}
}
else -> {
argument.toResolvedCallableSymbol()?.takeIf { it.fir is FirEnumEntry }
@OptIn(UnsafeExpressionUtility::class)
argument.toResolvedCallableSymbolUnsafe()?.takeIf { it.fir is FirEnumEntry }
}
} ?: return
processBranch(symbol, isNegated, data)
@@ -591,7 +591,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
val generator = GeneratorOfPlusAssignCalls(
assignmentOperatorStatement,
assignmentOperatorStatement.toReference()?.source,
assignmentOperatorStatement.toReference(session)?.source,
operation,
leftArgument,
rightArgument
@@ -623,7 +623,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
// following `!!` is safe since `operatorIsSuccessful = true` implies `operatorCallReference != null`
val operatorReturnTypeMatches = operatorIsSuccessful && operatorReturnTypeMatches(operatorCallReference!!.candidate)
val lhsReference = leftArgument.toReference()
val lhsReference = leftArgument.toReference(session)
val lhsSymbol = lhsReference?.toResolvedVariableSymbol()
val lhsVariable = lhsSymbol?.fir
val lhsIsVar = lhsVariable?.isVar == true
@@ -235,7 +235,7 @@ class ConeEffectExtractor(
private fun FirExpression.parseInvocationKind(): EventOccurrencesRange? {
if (this !is FirQualifiedAccessExpression) return null
val resolvedId = toResolvedCallableSymbol()?.callableId ?: return null
val resolvedId = toResolvedCallableSymbol(session)?.callableId ?: return null
return when (resolvedId) {
FirContractsDslNames.EXACTLY_ONCE_KIND -> EventOccurrencesRange.EXACTLY_ONCE
FirContractsDslNames.AT_LEAST_ONCE_KIND -> EventOccurrencesRange.AT_LEAST_ONCE
@@ -213,7 +213,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
// If fully qualified, check that given package name matches the resolved one.
val segments = generateSequence(receiver.explicitReceiver) { (it as? FirQualifiedAccessExpression)?.explicitReceiver }
.mapNotNull { (it.toReference() as? FirSimpleNamedReference)?.name?.identifier }
.mapNotNull { (it.toReference(session) as? FirSimpleNamedReference)?.name?.identifier }
.toList()
if (segments.isNotEmpty() && FqName.fromSegments(segments.asReversed()) != symbol.classId.packageFqName) {
@@ -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<*>?
}
@@ -8,11 +8,7 @@ package org.jetbrains.kotlin.lombok.k2.config
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
import org.jetbrains.kotlin.fir.declarations.getStringArgument
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol
import org.jetbrains.kotlin.lombok.config.AccessLevel
import org.jetbrains.kotlin.lombok.utils.trimToNull
@@ -27,8 +23,10 @@ private fun FirAnnotation.getArgumentAsString(field: Name): String? {
val argument = findArgumentByName(field) ?: return null
return when (argument) {
is FirConstExpression<*> -> argument.value as? String
is FirEnumEntryDeserializedAccessExpression -> argument.enumEntryName.identifier
is FirQualifiedAccessExpression -> {
val symbol = argument.toResolvedCallableSymbol()
@OptIn(UnsafeExpressionUtility::class)
val symbol = argument.toResolvedCallableSymbolUnsafe()
if (symbol is FirEnumEntrySymbol) {
symbol.callableId.callableName.identifier
} else {