FIR: Make LHS of FirVariableAssignment a FirExpression

This way references can even be resolved for erroneous assignments
(e.g. function call, if expression, ... on LHS)

^KT-54648 Fixed
This commit is contained in:
Kirill Rakhman
2023-01-16 09:54:31 +01:00
committed by Space Team
parent e9b8d6db80
commit ace47c06a5
128 changed files with 950 additions and 935 deletions
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.* import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -306,7 +306,7 @@ internal object FirToKtConversionCreator {
KtSymbol::class.createType(), KtSymbol::class.createType(),
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration") importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration")
), ),
FirQualifiedAccess::class to HLFunctionCallConversion( FirQualifiedAccessExpression::class to HLFunctionCallConversion(
"{0}.source!!.psi as KtExpression", "{0}.source!!.psi as KtExpression",
KtExpression::class.createType(), KtExpression::class.createType(),
importsToAdd = listOf( importsToAdd = listOf(
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
@@ -79,20 +79,20 @@ internal interface KtFirAnalysisSessionComponent {
) )
} }
fun FirQualifiedAccess.createSubstitutorFromTypeArguments(): KtSubstitutor? { fun FirQualifiedAccessExpression.createSubstitutorFromTypeArguments(): KtSubstitutor? {
return createConeSubstitutorFromTypeArguments()?.toKtSubstitutor() return createConeSubstitutorFromTypeArguments()?.toKtSubstitutor()
} }
fun FirQualifiedAccess.createSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): KtSubstitutor { fun FirQualifiedAccessExpression.createSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): KtSubstitutor {
return createConeSubstitutorFromTypeArguments(callableSymbol).toKtSubstitutor() return createConeSubstitutorFromTypeArguments(callableSymbol).toKtSubstitutor()
} }
fun FirQualifiedAccess.createConeSubstitutorFromTypeArguments(): ConeSubstitutor? { fun FirQualifiedAccessExpression.createConeSubstitutorFromTypeArguments(): ConeSubstitutor? {
val symbol = calleeReference.toResolvedCallableSymbol() ?: return null val symbol = calleeReference.toResolvedCallableSymbol() ?: return null
return createConeSubstitutorFromTypeArguments(symbol) return createConeSubstitutorFromTypeArguments(symbol)
} }
fun FirQualifiedAccess.createConeSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): ConeSubstitutor { fun FirQualifiedAccessExpression.createConeSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): ConeSubstitutor {
val typeArgumentMap = buildMap { val typeArgumentMap = buildMap {
// Type arguments are ignored defensively if `callableSymbol` can't provide enough type parameters (and vice versa). For // Type arguments are ignored defensively if `callableSymbol` can't provide enough type parameters (and vice versa). For
// example, when call candidates are collected, the candidate's `callableSymbol` might have fewer type parameters than the // example, when call candidates are collected, the candidate's `callableSymbol` might have fewer type parameters than the
@@ -124,9 +124,9 @@ internal class KtFirCallResolver(
val containingBinaryExpressionForLhs = psi.getContainingBinaryExpressionForIncompleteLhs() val containingBinaryExpressionForLhs = psi.getContainingBinaryExpressionForIncompleteLhs()
val containingUnaryExpressionForIncOrDec = psi.getContainingUnaryIncOrDecExpression() val containingUnaryExpressionForIncOrDec = psi.getContainingUnaryIncOrDecExpression()
val psiToResolve = containingCallExpressionForCalleeExpression val psiToResolve = containingCallExpressionForCalleeExpression
?: psi.getContainingDotQualifiedExpressionForSelectorExpression()
?: containingBinaryExpressionForLhs ?: containingBinaryExpressionForLhs
?: containingUnaryExpressionForIncOrDec ?: containingUnaryExpressionForIncOrDec
?: psi.getContainingDotQualifiedExpressionForSelectorExpression()
?: psi ?: psi
val fir = psiToResolve.getOrBuildFir(analysisSession.firResolveSession) ?: return emptyList() val fir = psiToResolve.getOrBuildFir(analysisSession.firResolveSession) ?: return emptyList()
if (fir is FirDiagnosticHolder) { if (fir is FirDiagnosticHolder) {
@@ -189,7 +189,7 @@ internal class KtFirCallResolver(
} }
} }
fun <T> transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder { fun <T> transformErrorReference(call: FirElement, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
val diagnostic = calleeReference.diagnostic val diagnostic = calleeReference.diagnostic
val ktDiagnostic = calleeReference.createKtDiagnostic(psi) val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
@@ -199,16 +199,16 @@ internal class KtFirCallResolver(
val candidateCalls = mutableListOf<KtCall>() val candidateCalls = mutableListOf<KtCall>()
if (diagnostic is ConeDiagnosticWithCandidates) { if (diagnostic is ConeDiagnosticWithCandidates) {
diagnostic.candidates.mapNotNullTo(candidateCalls) { diagnostic.candidates.mapNotNullTo(candidateCalls) {
createKtCall(psi, call, it, resolveFragmentOfCall) createKtCall(psi, call, calleeReference, it, resolveFragmentOfCall)
} }
} else { } else {
candidateCalls.addIfNotNull(createKtCall(psi, call, null, resolveFragmentOfCall)) candidateCalls.addIfNotNull(createKtCall(psi, call, calleeReference, null, resolveFragmentOfCall))
} }
return KtErrorCallInfo(candidateCalls, ktDiagnostic, token) return KtErrorCallInfo(candidateCalls, ktDiagnostic, token)
} }
return when (this) { return when (this) {
is FirResolvable -> { is FirResolvable, is FirVariableAssignment -> {
when (val calleeReference = calleeReference) { when (val calleeReference = calleeReference) {
is FirResolvedErrorReference -> transformErrorReference(this, calleeReference) is FirResolvedErrorReference -> transformErrorReference(this, calleeReference)
is FirResolvedNamedReference -> when (calleeReference.resolvedSymbol) { is FirResolvedNamedReference -> when (calleeReference.resolvedSymbol) {
@@ -216,7 +216,7 @@ internal class KtFirCallResolver(
// expression positions (e.g. `T` in `println(T)`) are parsed as `KtSimpleNameExpression` and built into // expression positions (e.g. `T` in `println(T)`) are parsed as `KtSimpleNameExpression` and built into
// `FirPropertyAccessExpression` (which is `FirResolvable`). // `FirPropertyAccessExpression` (which is `FirResolvable`).
is FirCallableSymbol<*> -> { is FirCallableSymbol<*> -> {
val call = createKtCall(psi, this, null, resolveFragmentOfCall) val call = createKtCall(psi, this, calleeReference, null, resolveFragmentOfCall)
?: errorWithFirSpecificEntries( ?: errorWithFirSpecificEntries(
"expect `createKtCall` to succeed for resolvable case with callable symbol", "expect `createKtCall` to succeed for resolvable case with callable symbol",
fir = this, fir = this,
@@ -307,7 +307,9 @@ internal class KtFirCallResolver(
if (this !is KtExpression) return null if (this !is KtExpression) return null
val lhs = deparenthesize(this) val lhs = deparenthesize(this)
val binaryExpression = parentOfType<KtBinaryExpression>() ?: return null val binaryExpression = parentOfType<KtBinaryExpression>() ?: return null
if (deparenthesize(binaryExpression.left) != lhs || binaryExpression.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null if (binaryExpression.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
val leftOfBinary = deparenthesize(binaryExpression.left)
if (leftOfBinary != lhs && !(leftOfBinary is KtDotQualifiedExpression && leftOfBinary.selectorExpression == lhs)) return null
val firBinaryExpression = binaryExpression.getOrBuildFir(analysisSession.firResolveSession) val firBinaryExpression = binaryExpression.getOrBuildFir(analysisSession.firResolveSession)
if (firBinaryExpression is FirFunctionCall) { if (firBinaryExpression is FirFunctionCall) {
if (firBinaryExpression.origin == FirFunctionCallOrigin.Operator && if (firBinaryExpression.origin == FirFunctionCallOrigin.Operator &&
@@ -349,9 +351,19 @@ internal class KtFirCallResolver(
fir: FirResolvable, fir: FirResolvable,
candidate: AbstractCandidate?, candidate: AbstractCandidate?,
resolveFragmentOfCall: Boolean resolveFragmentOfCall: Boolean
): KtCall? {
return createKtCall(psi, fir, fir.calleeReference, candidate, resolveFragmentOfCall)
}
private fun createKtCall(
psi: KtElement,
fir: FirElement,
calleeReference: FirReference,
candidate: AbstractCandidate?,
resolveFragmentOfCall: Boolean
): KtCall? { ): KtCall? {
val targetSymbol = candidate?.symbol val targetSymbol = candidate?.symbol
?: fir.calleeReference.toResolvedBaseSymbol() ?: calleeReference.toResolvedBaseSymbol()
?: return null ?: return null
if (targetSymbol !is FirCallableSymbol<*>) return null if (targetSymbol !is FirCallableSymbol<*>) return null
if (targetSymbol is FirErrorFunctionSymbol || targetSymbol is FirErrorPropertySymbol) return null if (targetSymbol is FirErrorFunctionSymbol || targetSymbol is FirErrorPropertySymbol) return null
@@ -365,8 +377,11 @@ internal class KtFirCallResolver(
// TODO: Ideally, we should get the substitutor from the candidate. But it seems there is no way to get the substitutor from the // TODO: Ideally, we should get the substitutor from the candidate. But it seems there is no way to get the substitutor from the
// candidate, `Candidate.substitutor` is not complete. maybe we can carry over the final substitutor if it's available from // candidate, `Candidate.substitutor` is not complete. maybe we can carry over the final substitutor if it's available from
// body resolve phase? // body resolve phase?
val substitutor = val substitutor = when (fir) {
(fir as? FirQualifiedAccess)?.createSubstitutorFromTypeArguments(targetSymbol) ?: KtSubstitutor.Empty(token) is FirQualifiedAccessExpression -> fir.createSubstitutorFromTypeArguments(targetSymbol)
is FirVariableAssignment -> fir.unwrapLValue()?.createSubstitutorFromTypeArguments(targetSymbol)
else -> null
} ?: KtSubstitutor.Empty(token)
fun createKtPartiallyAppliedSymbolForImplicitInvoke( fun createKtPartiallyAppliedSymbolForImplicitInvoke(
dispatchReceiver: FirExpression, dispatchReceiver: FirExpression,
@@ -393,7 +408,8 @@ internal class KtFirCallResolver(
val dispatchReceiverValue: KtReceiverValue? val dispatchReceiverValue: KtReceiverValue?
val extensionReceiverValue: KtReceiverValue? val extensionReceiverValue: KtReceiverValue?
if (explicitReceiverKind == ExplicitReceiverKind.DISPATCH_RECEIVER) { if (explicitReceiverKind == ExplicitReceiverKind.DISPATCH_RECEIVER) {
dispatchReceiverValue = KtExplicitReceiverValue(explicitReceiverPsi, dispatchReceiver.typeRef.coneType.asKtType(), false, token) dispatchReceiverValue =
KtExplicitReceiverValue(explicitReceiverPsi, dispatchReceiver.typeRef.coneType.asKtType(), false, token)
if (firstArgIsExtensionReceiver) { if (firstArgIsExtensionReceiver) {
extensionReceiverValue = (fir as FirFunctionCall).arguments.first().toKtReceiverValue() extensionReceiverValue = (fir as FirFunctionCall).arguments.first().toKtReceiverValue()
} else { } else {
@@ -401,7 +417,8 @@ internal class KtFirCallResolver(
} }
} else { } else {
dispatchReceiverValue = dispatchReceiver.toKtReceiverValue() dispatchReceiverValue = dispatchReceiver.toKtReceiverValue()
extensionReceiverValue = KtExplicitReceiverValue(explicitReceiverPsi, extensionReceiver.typeRef.coneType.asKtType(), false, token) extensionReceiverValue =
KtExplicitReceiverValue(explicitReceiverPsi, extensionReceiver.typeRef.coneType.asKtType(), false, token)
} }
return KtPartiallyAppliedSymbol( return KtPartiallyAppliedSymbol(
with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) }, with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) },
@@ -412,7 +429,7 @@ internal class KtFirCallResolver(
val partiallyAppliedSymbol = if (candidate != null) { val partiallyAppliedSymbol = if (candidate != null) {
if (fir is FirImplicitInvokeCall || if (fir is FirImplicitInvokeCall ||
(fir.calleeOrCandidateName != OperatorNameConventions.INVOKE && targetSymbol.isInvokeFunction()) (calleeReference.calleeOrCandidateName != OperatorNameConventions.INVOKE && targetSymbol.isInvokeFunction())
) { ) {
// Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`). // Implicit invoke (e.g., `x()`) will have a different callee symbol (e.g., `x`) than the candidate (e.g., `invoke`).
createKtPartiallyAppliedSymbolForImplicitInvoke( createKtPartiallyAppliedSymbolForImplicitInvoke(
@@ -427,21 +444,25 @@ internal class KtFirCallResolver(
candidate.chosenExtensionReceiverValue?.receiverExpression?.toKtReceiverValue(), candidate.chosenExtensionReceiverValue?.receiverExpression?.toKtReceiverValue(),
) )
} }
} else if (fir is FirQualifiedAccess) { } else if (fir is FirImplicitInvokeCall) {
if (fir is FirImplicitInvokeCall) { val explicitReceiverKind = if (fir.explicitReceiver == fir.dispatchReceiver) {
val explicitReceiverKind = if (fir.explicitReceiver == fir.dispatchReceiver) { ExplicitReceiverKind.DISPATCH_RECEIVER
ExplicitReceiverKind.DISPATCH_RECEIVER
} else {
ExplicitReceiverKind.EXTENSION_RECEIVER
}
createKtPartiallyAppliedSymbolForImplicitInvoke(fir.dispatchReceiver, fir.extensionReceiver, explicitReceiverKind)
} else { } else {
KtPartiallyAppliedSymbol( ExplicitReceiverKind.EXTENSION_RECEIVER
with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) },
fir.dispatchReceiver.toKtReceiverValue(),
fir.extensionReceiver.toKtReceiverValue()
)
} }
createKtPartiallyAppliedSymbolForImplicitInvoke(fir.dispatchReceiver, fir.extensionReceiver, explicitReceiverKind)
} else if (fir is FirQualifiedAccessExpression) {
KtPartiallyAppliedSymbol(
with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) },
fir.dispatchReceiver.toKtReceiverValue(),
fir.extensionReceiver.toKtReceiverValue()
)
} else if (fir is FirVariableAssignment) {
KtPartiallyAppliedSymbol(
with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) },
fir.dispatchReceiver.toKtReceiverValue(),
fir.extensionReceiver.toKtReceiverValue()
)
} else { } else {
KtPartiallyAppliedSymbol(unsubstitutedKtSignature, _dispatchReceiver = null, _extensionReceiver = null) KtPartiallyAppliedSymbol(unsubstitutedKtSignature, _dispatchReceiver = null, _extensionReceiver = null)
} }
@@ -470,7 +491,7 @@ internal class KtFirCallResolver(
@Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol @Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol
KtSimpleVariableAccessCall( KtSimpleVariableAccessCall(
partiallyAppliedSymbol as KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>, partiallyAppliedSymbol as KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>,
fir.toTypeArgumentsMapping(partiallyAppliedSymbol), fir.unwrapLValue()?.toTypeArgumentsMapping(partiallyAppliedSymbol) ?: emptyMap(),
KtSimpleVariableAccess.Write(rhs) KtSimpleVariableAccess.Write(rhs)
) )
} }
@@ -519,12 +540,19 @@ internal class KtFirCallResolver(
isImplicitInvoke isImplicitInvoke
) )
} }
is FirSmartCastExpression -> (fir.originalExpression as? FirResolvable)?.let { createKtCall(psi, it, candidate, resolveFragmentOfCall) } is FirSmartCastExpression -> (fir.originalExpression as? FirResolvable)?.let {
createKtCall(
psi,
it,
candidate,
resolveFragmentOfCall
)
}
else -> null else -> null
} }
} }
private fun handleCompoundAccessCall(psi: KtElement, fir: FirResolvable, resolveFragmentOfCall: Boolean): KtCall? { private fun handleCompoundAccessCall(psi: KtElement, fir: FirElement, resolveFragmentOfCall: Boolean): KtCall? {
if (psi is KtBinaryExpression && psi.operationToken in KtTokens.AUGMENTED_ASSIGNMENTS) { if (psi is KtBinaryExpression && psi.operationToken in KtTokens.AUGMENTED_ASSIGNMENTS) {
val rightOperandPsi = deparenthesize(psi.right) ?: return null val rightOperandPsi = deparenthesize(psi.right) ?: return null
val leftOperandPsi = deparenthesize(psi.left) ?: return null val leftOperandPsi = deparenthesize(psi.left) ?: return null
@@ -566,13 +594,13 @@ internal class KtFirCallResolver(
return if (resolveFragmentOfCall) { return if (resolveFragmentOfCall) {
KtSimpleVariableAccessCall( KtSimpleVariableAccessCall(
variablePartiallyAppliedSymbol, variablePartiallyAppliedSymbol,
fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(),
KtSimpleVariableAccess.Read KtSimpleVariableAccess.Read
) )
} else { } else {
KtCompoundVariableAccessCall( KtCompoundVariableAccessCall(
variablePartiallyAppliedSymbol, variablePartiallyAppliedSymbol,
fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(),
KtCompoundAccess.CompoundAssign(operationPartiallyAppliedSymbol, compoundAssignKind, rightOperandPsi), KtCompoundAccess.CompoundAssign(operationPartiallyAppliedSymbol, compoundAssignKind, rightOperandPsi),
) )
} }
@@ -620,13 +648,13 @@ internal class KtFirCallResolver(
return if (resolveFragmentOfCall) { return if (resolveFragmentOfCall) {
KtSimpleVariableAccessCall( KtSimpleVariableAccessCall(
variablePartiallyAppliedSymbol, variablePartiallyAppliedSymbol,
fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(),
KtSimpleVariableAccess.Read KtSimpleVariableAccess.Read
) )
} else { } else {
KtCompoundVariableAccessCall( KtCompoundVariableAccessCall(
variablePartiallyAppliedSymbol, variablePartiallyAppliedSymbol,
fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(),
KtCompoundAccess.IncOrDecOperation(operationPartiallyAppliedSymbol, incOrDecOperationKind, incDecPrecedence), KtCompoundAccess.IncOrDecOperation(operationPartiallyAppliedSymbol, incOrDecOperationKind, incDecPrecedence),
) )
} }
@@ -707,10 +735,7 @@ internal class KtFirCallResolver(
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
private fun getInitializerOfReferencedLocalVariable(variableReference: FirExpression): FirFunctionCall? { private fun getInitializerOfReferencedLocalVariable(variableReference: FirExpression): FirFunctionCall? {
val qualifiedAccess = variableReference as? FirQualifiedAccess return variableReference.toReference()?.toResolvedVariableSymbol()?.fir?.initializer as? FirFunctionCall
val resolvedNamedReference = qualifiedAccess?.calleeReference as? FirResolvedNamedReference
val unaryResult = resolvedNamedReference?.resolvedSymbol as? FirVariableSymbol<*>
return unaryResult?.fir?.initializer as? FirFunctionCall
} }
private fun getOperationPartiallyAppliedSymbolsForCompoundVariableAccess( private fun getOperationPartiallyAppliedSymbolsForCompoundVariableAccess(
@@ -718,14 +743,14 @@ internal class KtFirCallResolver(
leftOperandPsi: KtExpression leftOperandPsi: KtExpression
): KtPartiallyAppliedFunctionSymbol<KtFunctionSymbol>? { ): KtPartiallyAppliedFunctionSymbol<KtFunctionSymbol>? {
// The new value is a call to the appropriate operator function. // The new value is a call to the appropriate operator function.
val operationCall = fir.rValue as? FirFunctionCall ?: return null val operationCall = fir.rValue as? FirFunctionCall ?: getInitializerOfReferencedLocalVariable(fir.rValue) ?: return null
return operationCall.toPartiallyAppliedSymbol(leftOperandPsi) return operationCall.toPartiallyAppliedSymbol(leftOperandPsi)
} }
private fun FirVariableAssignment.toPartiallyAppliedSymbol(): KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>? { private fun FirVariableAssignment.toPartiallyAppliedSymbol(): KtPartiallyAppliedVariableSymbol<KtVariableLikeSymbol>? {
val variableRef = calleeReference as? FirResolvedNamedReference ?: return null val variableRef = calleeReference as? FirResolvedNamedReference ?: return null
val variableSymbol = variableRef.resolvedSymbol as? FirVariableSymbol<*> ?: return null val variableSymbol = variableRef.resolvedSymbol as? FirVariableSymbol<*> ?: return null
val substitutor = createConeSubstitutorFromTypeArguments() ?: return null val substitutor = unwrapLValue()?.createConeSubstitutorFromTypeArguments() ?: return null
val ktSignature = variableSymbol.toKtSignature() val ktSignature = variableSymbol.toKtSignature()
return KtPartiallyAppliedSymbol( return KtPartiallyAppliedSymbol(
with(analysisSession) { ktSignature.substitute(substitutor.toKtSubstitutor()) }, with(analysisSession) { ktSignature.substitute(substitutor.toKtSubstitutor()) },
@@ -801,7 +826,7 @@ internal class KtFirCallResolver(
private fun FirVariableSymbol<*>.toKtSignature(): KtVariableLikeSignature<KtVariableLikeSymbol> = private fun FirVariableSymbol<*>.toKtSignature(): KtVariableLikeSignature<KtVariableLikeSymbol> =
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSignature(this) firSymbolBuilder.variableLikeBuilder.buildVariableLikeSignature(this)
private fun FirQualifiedAccess.toTypeArgumentsMapping( private fun FirQualifiedAccessExpression.toTypeArgumentsMapping(
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *> partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
): Map<KtTypeParameterSymbol, KtType> { ): Map<KtTypeParameterSymbol, KtType> {
return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol) return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol)
@@ -1048,9 +1073,11 @@ internal class KtFirCallResolver(
} }
private val FirResolvable.calleeOrCandidateName: Name? private val FirResolvable.calleeOrCandidateName: Name?
get() = this.calleeReference.calleeOrCandidateName
private val FirReference.calleeOrCandidateName: Name?
get() { get() {
val calleeReference = calleeReference if (this !is FirNamedReference) return null
if (calleeReference !is FirNamedReference) return null
// In most cases, we can get the callee name from the callee's candidate symbols. However, there is at least one case where we // In most cases, we can get the callee name from the callee's candidate symbols. However, there is at least one case where we
// cannot do so: // cannot do so:
@@ -1064,13 +1091,13 @@ internal class KtFirCallResolver(
// ``` // ```
// The candidates for the call will both be `invoke`. We can keep it simple by getting the name from the callee reference's PSI // The candidates for the call will both be `invoke`. We can keep it simple by getting the name from the callee reference's PSI
// element (`x` in the above example) if possible. // element (`x` in the above example) if possible.
return when (val psi = calleeReference.psi) { return when (val psi = psi) {
is KtNameReferenceExpression -> psi.getReferencedNameAsName() is KtNameReferenceExpression -> psi.getReferencedNameAsName()
else -> { else -> {
// This could be KtArrayAccessExpression or KtOperationReferenceExpression. // This could be KtArrayAccessExpression or KtOperationReferenceExpression.
// Note: All candidate symbols should have the same name. We go by the symbol because `calleeReference.name` will include // Note: All candidate symbols should have the same name. We go by the symbol because `calleeReference.name` will include
// the applicability if not successful. // the applicability if not successful.
calleeReference.getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name
} }
} }
} }
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.constructFunctionalType
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
@@ -58,7 +59,9 @@ internal class KtFirExpressionTypeProvider(
} }
} }
is FirVariableAssignment -> { is FirVariableAssignment -> {
if (expression is KtUnaryExpression && expression.operationToken in KtTokens.INCREMENT_AND_DECREMENT) { if (fir.lValue.source?.psi == expression) {
fir.lValue.typeRef.coneType.asKtType()
} else if (expression is KtUnaryExpression && expression.operationToken in KtTokens.INCREMENT_AND_DECREMENT) {
fir.rValue.typeRef.coneType.asKtType() fir.rValue.typeRef.coneType.asKtType()
} else { } else {
analysisSession.builtinTypes.UNIT analysisSession.builtinTypes.UNIT
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -71,7 +71,7 @@ private fun convertArgument(argument: Any?, firSymbolBuilder: KtSymbolByFirBuild
is FirCallableDeclaration -> convertArgument(argument, firSymbolBuilder) is FirCallableDeclaration -> convertArgument(argument, firSymbolBuilder)
is FirMemberDeclaration -> convertArgument(argument, firSymbolBuilder) is FirMemberDeclaration -> convertArgument(argument, firSymbolBuilder)
is FirDeclaration -> convertArgument(argument, firSymbolBuilder) is FirDeclaration -> convertArgument(argument, firSymbolBuilder)
is FirQualifiedAccess -> convertArgument(argument, firSymbolBuilder) is FirQualifiedAccessExpression -> convertArgument(argument, firSymbolBuilder)
is FirExpression -> convertArgument(argument, firSymbolBuilder) is FirExpression -> convertArgument(argument, firSymbolBuilder)
is ConeKotlinType -> convertArgument(argument, firSymbolBuilder) is ConeKotlinType -> convertArgument(argument, firSymbolBuilder)
is FirTypeRef -> convertArgument(argument, firSymbolBuilder) is FirTypeRef -> convertArgument(argument, firSymbolBuilder)
@@ -163,7 +163,7 @@ private fun convertArgument(argument: FirDeclaration, firSymbolBuilder: KtSymbol
return firSymbolBuilder.buildSymbol(argument) return firSymbolBuilder.buildSymbol(argument)
} }
private fun convertArgument(argument: FirQualifiedAccess, firSymbolBuilder: KtSymbolByFirBuilder): Any? { private fun convertArgument(argument: FirQualifiedAccessExpression, firSymbolBuilder: KtSymbolByFirBuilder): Any? {
return argument.source!!.psi as KtExpression return argument.source!!.psi as KtExpression
} }
@@ -309,7 +309,7 @@ internal object FirReferenceResolveHelper {
symbolBuilder: KtSymbolByFirBuilder, symbolBuilder: KtSymbolByFirBuilder,
): Collection<KtSymbol> { ): Collection<KtSymbol> {
if (expression is KtNameReferenceExpression) { if (expression is KtNameReferenceExpression) {
return fir.calleeReference.toTargetSymbol(session, symbolBuilder) return fir.calleeReference?.toTargetSymbol(session, symbolBuilder) ?: emptyList()
} }
val assignmentRValue = fir.rValue val assignmentRValue = fir.rValue
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLoc
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -226,7 +227,12 @@ internal class NonReanalyzableDeclarationStructureElement(
} }
} }
internal class DanglingTopLevelModifierListStructureElement(firFile: FirFile, val fir: FirDeclaration, moduleComponents: LLFirModuleResolveComponents, override val psi: KtAnnotated) : internal class DanglingTopLevelModifierListStructureElement(
firFile: FirFile,
val fir: FirDeclaration,
moduleComponents: LLFirModuleResolveComponents,
override val psi: KtAnnotated
) :
FileStructureElement(firFile, moduleComponents) { FileStructureElement(firFile, moduleComponents) {
override val mappings = KtToFirMapping(fir, FirElementsRecorder()) override val mappings = KtToFirMapping(fir, FirElementsRecorder())
@@ -252,4 +258,4 @@ internal class RootStructureElement(
} }
} }
} }
} }
@@ -63,7 +63,8 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
} }
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MutableMap<KtElement, FirElement>) { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MutableMap<KtElement, FirElement>) {
cacheElement(variableAssignment.lValue, data) // FirReference is not cached by default // For the LHS of the assignment, record the assignment itself
(variableAssignment.lValue.source?.psi as? KtElement)?.let { cache(it, variableAssignment, data) }
visitElement(variableAssignment, data) visitElement(variableAssignment, data)
} }
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableCandidate import org.jetbrains.kotlin.fir.resolve.calls.InapplicableCandidate
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
@@ -120,7 +120,7 @@ class AllCandidatesResolver(private val firSession: FirSession) {
* resulting candidate is *not* marked as inapplicable and needs to be post-processed. * resulting candidate is *not* marked as inapplicable and needs to be post-processed.
*/ */
private fun OverloadCandidate.preserveCalleeInapplicability() { private fun OverloadCandidate.preserveCalleeInapplicability() {
val callSite = candidate.callInfo.callSite as? FirQualifiedAccess ?: return val callSite = candidate.callInfo.callSite
val calleeReference = callSite.calleeReference as? FirDiagnosticHolder ?: return val calleeReference = callSite.calleeReference as? FirDiagnosticHolder ?: return
val diagnostic = calleeReference.diagnostic as? ConeInapplicableCandidateError ?: return val diagnostic = calleeReference.diagnostic as? ConeInapplicableCandidateError ?: return
if (diagnostic.applicability != CandidateApplicability.INAPPLICABLE) return if (diagnostic.applicability != CandidateApplicability.INAPPLICABLE) return
@@ -31,7 +31,6 @@ fun main(args: Array<String>) {
val expressionPackage = "$basePackage.checkers.expression" val expressionPackage = "$basePackage.checkers.expression"
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") { generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
alias<FirStatement>("BasicExpressionChecker") alias<FirStatement>("BasicExpressionChecker")
alias<FirQualifiedAccess>("QualifiedAccessChecker")
alias<FirQualifiedAccessExpression>("QualifiedAccessExpressionChecker") alias<FirQualifiedAccessExpression>("QualifiedAccessExpressionChecker")
alias<FirCall>("CallChecker") alias<FirCall>("CallChecker")
alias<FirFunctionCall>("FunctionCallChecker") alias<FirFunctionCall>("FunctionCallChecker")
@@ -64,7 +64,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error<PsiElement>() val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error<PsiElement>()
val NOT_A_LOOP_LABEL by error<PsiElement>() val NOT_A_LOOP_LABEL by error<PsiElement>()
val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error<KtExpressionWithLabel>() val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error<KtExpressionWithLabel>()
val VARIABLE_EXPECTED by error<PsiElement>(PositioningStrategy.ASSIGNMENT_LHS) val VARIABLE_EXPECTED by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
val DELEGATION_IN_INTERFACE by error<PsiElement>() val DELEGATION_IN_INTERFACE by error<PsiElement>()
val DELEGATION_NOT_TO_INTERFACE by error<PsiElement>() val DELEGATION_NOT_TO_INTERFACE by error<PsiElement>()
val NESTED_CLASS_NOT_ALLOWED by error<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) { val NESTED_CLASS_NOT_ALLOWED by error<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
@@ -91,7 +91,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error<KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE) { val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error<KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE) {
parameter<KtKeywordToken>("valOrVar") parameter<KtKeywordToken>("valOrVar")
} }
val INVISIBLE_SETTER by error<PsiElement>(PositioningStrategy.ASSIGNMENT_LHS) { val INVISIBLE_SETTER by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirPropertySymbol>("property") parameter<FirPropertySymbol>("property")
parameter<Visibility>("visibility") parameter<Visibility>("visibility")
parameter<CallableId>("callableId") parameter<CallableId>("callableId")
@@ -1135,10 +1135,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNINITIALIZED_ENUM_COMPANION by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) { val UNINITIALIZED_ENUM_COMPANION by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<FirRegularClassSymbol>("enumClass") parameter<FirRegularClassSymbol>("enumClass")
} }
val VAL_REASSIGNMENT by error<KtExpression> { val VAL_REASSIGNMENT by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirVariableSymbol<*>>("variable") parameter<FirVariableSymbol<*>>("variable")
} }
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError<KtExpression>(LanguageFeature.RestrictionOfValReassignmentViaBackingField) { val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError<KtExpression>(LanguageFeature.RestrictionOfValReassignmentViaBackingField, PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirBackingFieldSymbol>("property") parameter<FirBackingFieldSymbol>("property")
} }
val CAPTURED_VAL_INITIALIZATION by error<KtExpression> { val CAPTURED_VAL_INITIALIZATION by error<KtExpression> {
@@ -1147,7 +1147,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val CAPTURED_MEMBER_VAL_INITIALIZATION by error<KtExpression> { val CAPTURED_MEMBER_VAL_INITIALIZATION by error<KtExpression> {
parameter<FirPropertySymbol>("property") parameter<FirPropertySymbol>("property")
} }
val SETTER_PROJECTED_OUT by error<KtBinaryExpression>(PositioningStrategy.ASSIGNMENT_LHS) { val SETTER_PROJECTED_OUT by error<KtBinaryExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirPropertySymbol>("property") parameter<FirPropertySymbol>("property")
} }
val WRONG_INVOCATION_KIND by warning<PsiElement> { val WRONG_INVOCATION_KIND by warning<PsiElement> {
@@ -90,7 +90,6 @@ enum class PositioningStrategy(private val strategy: String? = null) {
NAME_IDENTIFIER, NAME_IDENTIFIER,
QUESTION_MARK_BY_TYPE, QUESTION_MARK_BY_TYPE,
ANNOTATION_USE_SITE, ANNOTATION_USE_SITE,
ASSIGNMENT_LHS,
IMPORT_LAST_NAME, IMPORT_LAST_NAME,
DATA_MODIFIER, DATA_MODIFIER,
SPREAD_OPERATOR, SPREAD_OPERATOR,
@@ -14,8 +14,8 @@ object JsExpressionCheckers : ExpressionCheckers() {
FirJsQualifierChecker, FirJsQualifierChecker,
) )
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf( get() = setOf(
FirJsDefinedExternallyCallChecker, FirJsDefinedExternallyCallChecker
) )
} }
@@ -9,17 +9,20 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.closestNonLocal import org.jetbrains.kotlin.fir.analysis.checkers.closestNonLocal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeObject import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeObject
import org.jetbrains.kotlin.fir.analysis.js.checkers.isPredefinedObject import org.jetbrains.kotlin.fir.analysis.js.checkers.isPredefinedObject
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.name.JsStandardClassIds import org.jetbrains.kotlin.name.JsStandardClassIds
object FirJsDefinedExternallyCallChecker : FirQualifiedAccessChecker() { object FirJsDefinedExternallyCallChecker : FirBasicExpressionChecker() {
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val symbol = expression.calleeReference.toResolvedCallableSymbol() ?: return val symbol = expression.calleeReference?.toResolvedCallableSymbol() ?: return
if (symbol.callableId !in JsStandardClassIds.Callables.definedExternallyPropertyNames) { if (symbol.callableId !in JsStandardClassIds.Callables.definedExternallyPropertyNames) {
return return
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.* import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.*
object JvmExpressionCheckers : ExpressionCheckers() { object JvmExpressionCheckers : ExpressionCheckers() {
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf( get() = setOf(
FirJvmProtectedInSuperClassCompanionCallChecker FirJvmProtectedInSuperClassCompanionCallChecker
) )
@@ -6,20 +6,19 @@
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.defaultType
@@ -29,12 +28,18 @@ import org.jetbrains.kotlin.fir.types.typeContext
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_CLASS_ID
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
object FirJvmProtectedInSuperClassCompanionCallChecker : FirQualifiedAccessChecker() { object FirJvmProtectedInSuperClassCompanionCallChecker : FirBasicExpressionChecker() {
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val dispatchReceiver = expression.dispatchReceiver val dispatchReceiver = when (expression) {
is FirQualifiedAccessExpression -> expression.dispatchReceiver
is FirVariableAssignment -> expression.dispatchReceiver
else -> null
} ?: return
if (dispatchReceiver is FirNoReceiverExpression) return if (dispatchReceiver is FirNoReceiverExpression) return
val dispatchClassSymbol = dispatchReceiver.typeRef.toRegularClassSymbol(context.session) ?: return val dispatchClassSymbol = dispatchReceiver.typeRef.toRegularClassSymbol(context.session) ?: return
val resolvedSymbol = expression.calleeReference.toResolvedCallableSymbol() ?: return val calleeReference = expression.calleeReference
val resolvedSymbol = calleeReference?.toResolvedCallableSymbol() ?: return
val visibility = if (resolvedSymbol is FirPropertySymbol) { val visibility = if (resolvedSymbol is FirPropertySymbol) {
if (expression is FirVariableAssignment) if (expression is FirVariableAssignment)
@@ -64,7 +69,7 @@ object FirJvmProtectedInSuperClassCompanionCallChecker : FirQualifiedAccessCheck
it.symbol == dispatchClassSymbol || it.symbol == companionContainingClassSymbol it.symbol == dispatchClassSymbol || it.symbol == companionContainingClassSymbol
} == null } == null
) { ) {
reporter.reportOn(expression.calleeReference.source, FirJvmErrors.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC, context) reporter.reportOn(calleeReference.source, FirJvmErrors.SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC, context)
} }
} }
} }
@@ -28,7 +28,7 @@ object FirJvmSuspensionPointInsideMutexLockChecker : FirFunctionCallChecker() {
if (!symbol.isSuspend) return if (!symbol.isSuspend) return
val closestAnonymousFunction = context.findClosest<FirAnonymousFunction>() ?: return val closestAnonymousFunction = context.findClosest<FirAnonymousFunction>() ?: return
for (call in context.qualifiedAccessOrAnnotationCalls.asReversed()) { for (call in context.qualifiedAccessOrAssignmentsOrAnnotationCalls.asReversed()) {
if (call is FirFunctionCall) { if (call is FirFunctionCall) {
val callableSymbol = call.calleeReference.toResolvedCallableSymbol() ?: continue val callableSymbol = call.calleeReference.toResolvedCallableSymbol() ?: continue
if (callableSymbol.callableId == synchronizedCallableId) { if (callableSymbol.callableId == synchronizedCallableId) {
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
class ComposedExpressionCheckers : ExpressionCheckers() { class ComposedExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker> override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = _basicExpressionCheckers get() = _basicExpressionCheckers
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = _qualifiedAccessCheckers
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker>
get() = _qualifiedAccessExpressionCheckers get() = _qualifiedAccessExpressionCheckers
override val callCheckers: Set<FirCallChecker> override val callCheckers: Set<FirCallChecker>
@@ -81,7 +79,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _classReferenceExpressionCheckers get() = _classReferenceExpressionCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf() private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
private val _qualifiedAccessExpressionCheckers: MutableSet<FirQualifiedAccessExpressionChecker> = mutableSetOf() private val _qualifiedAccessExpressionCheckers: MutableSet<FirQualifiedAccessExpressionChecker> = mutableSetOf()
private val _callCheckers: MutableSet<FirCallChecker> = mutableSetOf() private val _callCheckers: MutableSet<FirCallChecker> = mutableSetOf()
private val _functionCallCheckers: MutableSet<FirFunctionCallChecker> = mutableSetOf() private val _functionCallCheckers: MutableSet<FirFunctionCallChecker> = mutableSetOf()
@@ -117,7 +114,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
@CheckersComponentInternal @CheckersComponentInternal
fun register(checkers: ExpressionCheckers) { fun register(checkers: ExpressionCheckers) {
_basicExpressionCheckers += checkers.basicExpressionCheckers _basicExpressionCheckers += checkers.basicExpressionCheckers
_qualifiedAccessCheckers += checkers.qualifiedAccessCheckers
_qualifiedAccessExpressionCheckers += checkers.qualifiedAccessExpressionCheckers _qualifiedAccessExpressionCheckers += checkers.qualifiedAccessExpressionCheckers
_callCheckers += checkers.callCheckers _callCheckers += checkers.callCheckers
_functionCallCheckers += checkers.functionCallCheckers _functionCallCheckers += checkers.functionCallCheckers
@@ -18,7 +18,6 @@ abstract class ExpressionCheckers {
} }
open val basicExpressionCheckers: Set<FirBasicExpressionChecker> = emptySet() open val basicExpressionCheckers: Set<FirBasicExpressionChecker> = emptySet()
open val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = emptySet()
open val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> = emptySet() open val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> = emptySet()
open val callCheckers: Set<FirCallChecker> = emptySet() open val callCheckers: Set<FirCallChecker> = emptySet()
open val functionCallCheckers: Set<FirFunctionCallChecker> = emptySet() open val functionCallCheckers: Set<FirFunctionCallChecker> = emptySet()
@@ -52,13 +51,12 @@ abstract class ExpressionCheckers {
open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = emptySet() open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> by lazy { basicExpressionCheckers } @CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> by lazy { basicExpressionCheckers }
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> by lazy { qualifiedAccessCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allCallCheckers: Set<FirCallChecker> by lazy { callCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allCallCheckers: Set<FirCallChecker> by lazy { callCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers } @CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker> by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } @CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker> by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set<FirIntegerLiteralOperatorCallChecker> by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers } @CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set<FirIntegerLiteralOperatorCallChecker> by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> by lazy { variableAssignmentCheckers + qualifiedAccessCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> by lazy { variableAssignmentCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> by lazy { tryExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> by lazy { tryExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> by lazy { whenExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> by lazy { whenExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allLoopExpressionCheckers: Set<FirLoopExpressionChecker> by lazy { loopExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allLoopExpressionCheckers: Set<FirLoopExpressionChecker> by lazy { loopExpressionCheckers + basicExpressionCheckers }
@@ -77,8 +75,8 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allTypeOperatorCallCheckers: Set<FirTypeOperatorCallChecker> by lazy { typeOperatorCallCheckers + basicExpressionCheckers + callCheckers } @CheckersComponentInternal internal val allTypeOperatorCallCheckers: Set<FirTypeOperatorCallChecker> by lazy { typeOperatorCallCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allResolvedQualifierCheckers: Set<FirResolvedQualifierChecker> by lazy { resolvedQualifierCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allResolvedQualifierCheckers: Set<FirResolvedQualifierChecker> by lazy { resolvedQualifierCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allConstExpressionCheckers: Set<FirConstExpressionChecker> by lazy { constExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allConstExpressionCheckers: Set<FirConstExpressionChecker> by lazy { constExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } @CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } @CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allWhileLoopCheckers: Set<FirWhileLoopChecker> by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allWhileLoopCheckers: Set<FirWhileLoopChecker> by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allThrowExpressionCheckers: Set<FirThrowExpressionChecker> by lazy { throwExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allThrowExpressionCheckers: Set<FirThrowExpressionChecker> by lazy { throwExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirLoop import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.FirLoopJump import org.jetbrains.kotlin.fir.expressions.FirLoopJump
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
@@ -45,7 +44,6 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
typealias FirBasicExpressionChecker = FirExpressionChecker<FirStatement> typealias FirBasicExpressionChecker = FirExpressionChecker<FirStatement>
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccess>
typealias FirQualifiedAccessExpressionChecker = FirExpressionChecker<FirQualifiedAccessExpression> typealias FirQualifiedAccessExpressionChecker = FirExpressionChecker<FirQualifiedAccessExpression>
typealias FirCallChecker = FirExpressionChecker<FirCall> typealias FirCallChecker = FirExpressionChecker<FirCall>
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall> typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
@@ -123,7 +123,7 @@ object FirErrors {
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<PsiElement>() val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<PsiElement>()
val NOT_A_LOOP_LABEL by error0<PsiElement>() val NOT_A_LOOP_LABEL by error0<PsiElement>()
val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error0<KtExpressionWithLabel>() val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error0<KtExpressionWithLabel>()
val VARIABLE_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.ASSIGNMENT_LHS) val VARIABLE_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val DELEGATION_IN_INTERFACE by error0<PsiElement>() val DELEGATION_IN_INTERFACE by error0<PsiElement>()
val DELEGATION_NOT_TO_INTERFACE by error0<PsiElement>() val DELEGATION_NOT_TO_INTERFACE by error0<PsiElement>()
val NESTED_CLASS_NOT_ALLOWED by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.DECLARATION_NAME) val NESTED_CLASS_NOT_ALLOWED by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -140,7 +140,7 @@ object FirErrors {
val VAL_OR_VAR_ON_FUN_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_FUN_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val VAL_OR_VAR_ON_CATCH_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_CATCH_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.ASSIGNMENT_LHS) val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Unresolved // Unresolved
val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -607,11 +607,11 @@ object FirErrors {
val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirValueParameterSymbol>() val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirValueParameterSymbol>()
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirEnumEntrySymbol>() val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirEnumEntrySymbol>()
val UNINITIALIZED_ENUM_COMPANION by error1<KtExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val UNINITIALIZED_ENUM_COMPANION by error1<KtExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>() val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField) val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField, SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val CAPTURED_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>() val CAPTURED_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
val CAPTURED_MEMBER_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>() val CAPTURED_MEMBER_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
val SETTER_PROJECTED_OUT by error1<KtBinaryExpression, FirPropertySymbol>(SourceElementPositioningStrategies.ASSIGNMENT_LHS) val SETTER_PROJECTED_OUT by error1<KtBinaryExpression, FirPropertySymbol>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val WRONG_INVOCATION_KIND by warning3<PsiElement, FirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>() val WRONG_INVOCATION_KIND by warning3<PsiElement, FirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
val LEAKED_IN_PLACE_LAMBDA by warning1<PsiElement, FirBasedSymbol<*>>() val LEAKED_IN_PLACE_LAMBDA by warning1<PsiElement, FirBasedSymbol<*>>()
val WRONG_IMPLIES_CONDITION by warning0<PsiElement>() val WRONG_IMPLIES_CONDITION by warning0<PsiElement>()
@@ -22,11 +22,8 @@ import org.jetbrains.kotlin.fir.contracts.effects
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirThisReference import org.jetbrains.kotlin.fir.references.FirThisReference
@@ -309,7 +306,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
return this is FirAnonymousFunction && this.isLambda && this.invocationKind != null return this is FirAnonymousFunction && this.isLambda && this.invocationKind != null
} }
private fun FirExpression?.toQualifiedReference(): FirReference? = (this as? FirQualifiedAccess)?.calleeReference private fun FirExpression?.toQualifiedReference(): FirReference? = (this as? FirQualifiedAccessExpression)?.calleeReference
private fun referenceToSymbol(reference: FirReference?): FirBasedSymbol<*>? = when (reference) { private fun referenceToSymbol(reference: FirReference?): FirBasedSymbol<*>? = when (reference) {
is FirResolvedNamedReference -> reference.resolvedSymbol is FirResolvedNamedReference -> reference.resolvedSymbol
@@ -18,8 +18,10 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isLateInit import org.jetbrains.kotlin.fir.declarations.utils.isLateInit
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.expressions.unwrapLValue
import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.isCatchParameter
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
@@ -65,7 +67,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses(
scope: FirDeclaration?, scope: FirDeclaration?,
scopes: MutableMap<FirPropertySymbol, FirDeclaration?>, scopes: MutableMap<FirPropertySymbol, FirDeclaration?>,
) { ) {
fun FirQualifiedAccess.hasCorrectReceiver() = fun FirQualifiedAccessExpression.hasCorrectReceiver() =
(dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver (dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver
for (node in graph.nodes) { for (node in graph.nodes) {
@@ -83,17 +85,17 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses(
} }
node is VariableAssignmentNode -> { node is VariableAssignmentNode -> {
val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: continue val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: continue
if (!symbol.fir.isVal || !node.fir.hasCorrectReceiver() || symbol !in properties) continue if (!symbol.fir.isVal || node.fir.unwrapLValue()?.hasCorrectReceiver() != true || symbol !in properties) continue
if (scope != scopes[symbol]) { if (getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) {
reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context)
} else if (scope != scopes[symbol]) {
val error = if (receiver != null) val error = if (receiver != null)
FirErrors.CAPTURED_MEMBER_VAL_INITIALIZATION FirErrors.CAPTURED_MEMBER_VAL_INITIALIZATION
else else
FirErrors.CAPTURED_VAL_INITIALIZATION FirErrors.CAPTURED_VAL_INITIALIZATION
reporter.reportOn(node.fir.lValue.source, error, symbol, context) reporter.reportOn(node.fir.lValue.source, error, symbol, context)
} else if (getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) {
reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context)
} }
} }
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.cfa.util
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.expressions.dispatchReceiver
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -51,7 +53,7 @@ class PropertyInitializationInfoCollector(
val dataForNode = visitNode(node, data) val dataForNode = visitNode(node, data)
val receiver = (node.fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol val receiver = (node.fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol
if (receiver != expectedReceiver) return dataForNode if (receiver != expectedReceiver) return dataForNode
val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: return dataForNode val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode
if (symbol !in localProperties) return dataForNode if (symbol !in localProperties) return dataForNode
return addRange(dataForNode, symbol, EventOccurrencesRange.EXACTLY_ONCE) return addRange(dataForNode, symbol, EventOccurrencesRange.EXACTLY_ONCE)
} }
@@ -22,7 +22,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirUnderscoreChecker, FirUnderscoreChecker,
FirExpressionAnnotationChecker, FirExpressionAnnotationChecker,
FirDeprecationChecker, FirDeprecationChecker,
FirRecursiveProblemChecker FirRecursiveProblemChecker,
FirOptInUsageAccessChecker,
) )
override val throwExpressionCheckers: Set<FirThrowExpressionChecker> override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
@@ -30,11 +31,6 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirThrowExpressionTypeChecker, FirThrowExpressionTypeChecker,
) )
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = setOf(
FirOptInUsageAccessChecker,
)
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker>
get() = setOf( get() = setOf(
FirCallableReferenceChecker, FirCallableReferenceChecker,
@@ -83,7 +79,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
get() = setOf( get() = setOf(
FirReassignmentAndInvisibleSetterChecker, FirReassignmentAndInvisibleSetterChecker,
FirAssignmentTypeMismatchChecker FirAssignmentTypeMismatchChecker,
) )
override val whenExpressionCheckers: Set<FirWhenExpressionChecker> override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
@@ -655,7 +655,7 @@ fun getActualTargetList(annotated: FirDeclaration): AnnotationTargetList {
private typealias TargetLists = AnnotationTargetLists private typealias TargetLists = AnnotationTargetLists
fun FirQualifiedAccess.explicitReceiverIsNotSuperReference(): Boolean { fun FirQualifiedAccessExpression.explicitReceiverIsNotSuperReference(): Boolean {
return (this.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference !is FirSuperReference return (this.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference !is FirSuperReference
} }
@@ -728,3 +728,9 @@ fun FirBasedSymbol<*>.getAnnotationStringParameter(classId: ClassId, session: Fi
val expression = annotation?.argumentMapping?.mapping?.values?.firstOrNull() as? FirConstExpression<*> val expression = annotation?.argumentMapping?.mapping?.values?.firstOrNull() as? FirConstExpression<*>
return expression?.value as? String return expression?.value as? String
} }
fun FirElement.isLhsOfAssignment(context: CheckerContext): Boolean {
if (this !is FirQualifiedAccessExpression) return false
val lastQualified = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull { it != this } ?: return false
return lastQualified is FirVariableAssignment && lastQualified.lValue == this
}
@@ -31,7 +31,7 @@ abstract class CheckerContext : MutableDiagnosticContext() {
// Context // Context
abstract val implicitReceiverStack: ImplicitReceiverStack abstract val implicitReceiverStack: ImplicitReceiverStack
abstract val containingDeclarations: List<FirDeclaration> abstract val containingDeclarations: List<FirDeclaration>
abstract val qualifiedAccessOrAnnotationCalls: List<FirStatement> abstract val qualifiedAccessOrAssignmentsOrAnnotationCalls: List<FirStatement>
abstract val getClassCalls: List<FirGetClassCall> abstract val getClassCalls: List<FirGetClassCall>
abstract val annotationContainers: List<FirAnnotationContainer> abstract val annotationContainers: List<FirAnnotationContainer>
abstract val isContractBody: Boolean abstract val isContractBody: Boolean
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.name.Name
class MutableCheckerContext private constructor( class MutableCheckerContext private constructor(
override val implicitReceiverStack: PersistentImplicitReceiverStack, override val implicitReceiverStack: PersistentImplicitReceiverStack,
override val containingDeclarations: MutableList<FirDeclaration>, override val containingDeclarations: MutableList<FirDeclaration>,
override val qualifiedAccessOrAnnotationCalls: MutableList<FirStatement>, override val qualifiedAccessOrAssignmentsOrAnnotationCalls: MutableList<FirStatement>,
override val getClassCalls: MutableList<FirGetClassCall>, override val getClassCalls: MutableList<FirGetClassCall>,
override val annotationContainers: MutableList<FirAnnotationContainer>, override val annotationContainers: MutableList<FirAnnotationContainer>,
override var isContractBody: Boolean, override var isContractBody: Boolean,
@@ -50,7 +50,7 @@ class MutableCheckerContext private constructor(
return MutableCheckerContext( return MutableCheckerContext(
implicitReceiverStack.add(name, value), implicitReceiverStack.add(name, value),
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -73,12 +73,12 @@ class MutableCheckerContext private constructor(
} }
override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): MutableCheckerContext { override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): MutableCheckerContext {
qualifiedAccessOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall) qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall)
return this return this
} }
override fun dropQualifiedAccessOrAnnotationCall() { override fun dropQualifiedAccessOrAnnotationCall() {
qualifiedAccessOrAnnotationCalls.removeAt(qualifiedAccessOrAnnotationCalls.size - 1) qualifiedAccessOrAssignmentsOrAnnotationCalls.removeAt(qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 1)
} }
override fun addGetClassCall(getClassCall: FirGetClassCall): MutableCheckerContext { override fun addGetClassCall(getClassCall: FirGetClassCall): MutableCheckerContext {
@@ -109,7 +109,7 @@ class MutableCheckerContext private constructor(
return MutableCheckerContext( return MutableCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.Name
class PersistentCheckerContext private constructor( class PersistentCheckerContext private constructor(
override val implicitReceiverStack: PersistentImplicitReceiverStack, override val implicitReceiverStack: PersistentImplicitReceiverStack,
override val containingDeclarations: PersistentList<FirDeclaration>, override val containingDeclarations: PersistentList<FirDeclaration>,
override val qualifiedAccessOrAnnotationCalls: PersistentList<FirStatement>, override val qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement>,
override val getClassCalls: PersistentList<FirGetClassCall>, override val getClassCalls: PersistentList<FirGetClassCall>,
override val annotationContainers: PersistentList<FirAnnotationContainer>, override val annotationContainers: PersistentList<FirAnnotationContainer>,
override val isContractBody: Boolean, override val isContractBody: Boolean,
@@ -52,7 +52,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack.add(name, value), implicitReceiverStack.add(name, value),
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -69,7 +69,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations.add(declaration), containingDeclarations.add(declaration),
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -89,7 +89,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
this.qualifiedAccessOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall), this.qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall),
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -109,7 +109,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls.add(getClassCall), getClassCalls.add(getClassCall),
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -129,7 +129,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers.add(annotationContainer), annotationContainers.add(annotationContainer),
isContractBody, isContractBody,
@@ -155,7 +155,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody, isContractBody,
@@ -174,7 +174,7 @@ class PersistentCheckerContext private constructor(
return PersistentCheckerContext( return PersistentCheckerContext(
implicitReceiverStack, implicitReceiverStack,
containingDeclarations, containingDeclarations,
qualifiedAccessOrAnnotationCalls, qualifiedAccessOrAssignmentsOrAnnotationCalls,
getClassCalls, getClassCalls,
annotationContainers, annotationContainers,
isContractBody = newValue, isContractBody = newValue,
@@ -182,7 +182,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
} }
private val FirExpression.explicitReceiverOfQualifiedAccess: FirQualifiedAccessExpression? private val FirExpression.explicitReceiverOfQualifiedAccess: FirQualifiedAccessExpression?
get() = (this as? FirQualifiedAccess)?.explicitReceiver?.unwrapped as? FirQualifiedAccessExpression get() = (this as? FirQualifiedAccessExpression)?.explicitReceiver?.unwrapped as? FirQualifiedAccessExpression
private val FirExpression.unwrapped: FirExpression private val FirExpression.unwrapped: FirExpression
get() = get() =
@@ -111,7 +111,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: CheckerContext) {} override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: CheckerContext) {}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
val propertySymbol = variableAssignment.calleeReference.toResolvedCallableSymbol() as? FirPropertySymbol ?: return val propertySymbol = variableAssignment.calleeReference?.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
val setterSymbol = propertySymbol.setterSymbol ?: return val setterSymbol = propertySymbol.setterSymbol ?: return
checkQualifiedAccess(variableAssignment, setterSymbol, data) checkQualifiedAccess(variableAssignment, setterSymbol, data)
} }
@@ -237,7 +237,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
} }
private fun checkQualifiedAccess( private fun checkQualifiedAccess(
qualifiedAccess: FirQualifiedAccess, qualifiedAccess: FirStatement,
targetSymbol: FirBasedSymbol<*>?, targetSymbol: FirBasedSymbol<*>?,
context: CheckerContext context: CheckerContext
) { ) {
@@ -253,18 +253,18 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
checkRecursion(targetSymbol, source, context) checkRecursion(targetSymbol, source, context)
} }
private fun FirQualifiedAccess.partOfCall(context: CheckerContext): Boolean { private fun FirStatement.partOfCall(context: CheckerContext): Boolean {
if (this !is FirExpression) return false if (this !is FirExpression) return false
val containingQualifiedAccess = context.qualifiedAccessOrAnnotationCalls.getOrNull( val containingQualifiedAccess = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.getOrNull(
context.qualifiedAccessOrAnnotationCalls.size - 2 context.qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 2
) ?: return false ) ?: return false
if (this == (containingQualifiedAccess as? FirQualifiedAccess)?.explicitReceiver) return true if (this == (containingQualifiedAccess as? FirQualifiedAccessExpression)?.explicitReceiver) return true
val call = containingQualifiedAccess as? FirCall ?: return false val call = containingQualifiedAccess as? FirCall ?: return false
return call.arguments.any { it.unwrapArgument() == this } return call.arguments.any { it.unwrapArgument() == this }
} }
private fun checkVisibilityAndAccess( private fun checkVisibilityAndAccess(
accessExpression: FirQualifiedAccess, accessExpression: FirStatement,
calledDeclaration: FirCallableSymbol<*>?, calledDeclaration: FirCallableSymbol<*>?,
source: KtSourceElement, source: KtSourceElement,
context: CheckerContext context: CheckerContext
@@ -321,16 +321,21 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() {
private fun checkSuperCalls( private fun checkSuperCalls(
calledDeclaration: FirCallableSymbol<*>, calledDeclaration: FirCallableSymbol<*>,
callExpression: FirQualifiedAccess, callExpression: FirStatement,
context: CheckerContext context: CheckerContext
) { ) {
val receiver = callExpression.dispatchReceiver as? FirQualifiedAccessExpression ?: return val receiver = when (callExpression) {
is FirQualifiedAccessExpression -> callExpression.dispatchReceiver
is FirVariableAssignment -> callExpression.dispatchReceiver
else -> null
} as? FirQualifiedAccessExpression ?: return
if (receiver.calleeReference is FirSuperReference) { if (receiver.calleeReference is FirSuperReference) {
val dispatchReceiverType = receiver.dispatchReceiver.typeRef.coneType val dispatchReceiverType = receiver.dispatchReceiver.typeRef.coneType
val classSymbol = dispatchReceiverType.toSymbol(session) ?: return val classSymbol = dispatchReceiverType.toSymbol(session) ?: return
if (!classSymbol.isDefinedInInlineFunction()) { if (!classSymbol.isDefinedInInlineFunction()) {
reporter.reportOn( reporter.reportOn(
callExpression.dispatchReceiver.source, receiver.source,
FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE, FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE,
calledDeclaration, calledDeclaration,
context context
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
@@ -38,7 +39,7 @@ object FirPropertyInitializationChecker : FirRegularClassChecker() {
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) {
variableAssignment.acceptChildren(this) variableAssignment.acceptChildren(this)
val propertySymbol = variableAssignment.lValue.toResolvedCallableSymbol() as? FirPropertySymbol ?: return val propertySymbol = variableAssignment.calleeReference?.toResolvedCallableSymbol() as? FirPropertySymbol ?: return
if (propertySymbol !in declaredLater) return if (propertySymbol !in declaredLater) return
reporter.reportOn(variableAssignment.lValue.source, FirErrors.INITIALIZATION_BEFORE_DECLARATION, propertySymbol, context) reporter.reportOn(variableAssignment.lValue.source, FirErrors.INITIALIZATION_BEFORE_DECLARATION, propertySymbol, context)
} }
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.types.coneType
object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() { object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() {
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
val source = expression.rValue.source ?: return val source = expression.rValue.source ?: return
val coneType = expression.lValueTypeRef.coneType val coneType = expression.lValue.typeRef.coneType
checkTypeMismatch( checkTypeMismatch(
coneType, coneType,
expression, expression,
@@ -29,7 +29,7 @@ object FirConstructorCallChecker : FirFunctionCallChecker() {
reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context) reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
} }
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS && if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
context.qualifiedAccessOrAnnotationCalls.all { call -> context.qualifiedAccessOrAssignmentsOrAnnotationCalls.all { call ->
call !is FirAnnotation call !is FirAnnotation
} && } &&
context.containingDeclarations.all { klass -> context.containingDeclarations.all { klass ->
@@ -15,11 +15,9 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FutureApiDeprecationInfo import org.jetbrains.kotlin.fir.declarations.FutureApiDeprecationInfo
import org.jetbrains.kotlin.fir.analysis.checkers.isLhsOfAssignment
import org.jetbrains.kotlin.fir.declarations.getDeprecation import org.jetbrains.kotlin.fir.declarations.getDeprecation
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirResolvable
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.references.resolved import org.jetbrains.kotlin.fir.references.resolved
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
@@ -36,11 +34,13 @@ object FirDeprecationChecker : FirBasicExpressionChecker() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
if (!allowedSourceKinds.contains(expression.source?.kind)) return if (!allowedSourceKinds.contains(expression.source?.kind)) return
if (expression is FirAnnotation || expression is FirDelegatedConstructorCall) return //checked by FirDeprecatedTypeChecker if (expression is FirAnnotation || expression is FirDelegatedConstructorCall) return //checked by FirDeprecatedTypeChecker
val resolvable = expression as? FirResolvable ?: return if (expression.isLhsOfAssignment(context)) return
val reference = resolvable.calleeReference.resolved ?: return
val referencedSymbol = reference.resolvedSymbol
reportApiStatusIfNeeded(reference.source, referencedSymbol, expression, context, reporter) val calleeReference = expression.calleeReference ?: return
val resolvedReference = calleeReference.resolved ?: return
val referencedSymbol = resolvedReference.resolvedSymbol
reportApiStatusIfNeeded(resolvedReference.source, referencedSymbol, expression, context, reporter)
} }
internal fun reportApiStatusIfNeeded( internal fun reportApiStatusIfNeeded(
@@ -8,33 +8,37 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.analysis.checkers.isLhsOfAssignment
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() { object FirOptInUsageAccessChecker : FirBasicExpressionChecker() {
override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
val sourceKind = expression.source?.kind val sourceKind = expression.source?.kind
if (sourceKind is KtFakeSourceElementKind.DataClassGeneratedMembers || if (sourceKind is KtFakeSourceElementKind.DataClassGeneratedMembers ||
sourceKind is KtFakeSourceElementKind.PropertyFromParameter sourceKind is KtFakeSourceElementKind.PropertyFromParameter
) return ) return
val resolvedSymbol = expression.calleeReference.toResolvedBaseSymbol() ?: return
val dispatchReceiverType = if (expression.isLhsOfAssignment(context)) return
expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }?.typeRef?.coneType?.fullyExpandedType(context.session)
val resolvedSymbol = expression.calleeReference?.toResolvedBaseSymbol() ?: return
with(FirOptInUsageBaseChecker) { with(FirOptInUsageBaseChecker) {
if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) { if (expression is FirVariableAssignment) {
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true, dispatchReceiverType) + val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true, null) +
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments) loadExperimentalitiesFromTypeArguments(context, emptyList())
reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter) reportNotAcceptedExperimentalities(experimentalities, expression.lValue, context, reporter)
return } else if (expression is FirQualifiedAccessExpression) {
val dispatchReceiverType =
expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }?.typeRef?.coneType?.fullyExpandedType(context.session)
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType) +
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
} }
val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = false, dispatchReceiverType) +
loadExperimentalitiesFromTypeArguments(context, expression.typeArguments)
reportNotAcceptedExperimentalities(experimentalities, expression, context, reporter)
} }
} }
} }
@@ -16,17 +16,14 @@ import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.references.FirBackingFieldReference import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithCandidates
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.visibilityChecker import org.jetbrains.kotlin.fir.visibilityChecker
@@ -36,7 +33,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
checkInvisibleSetter(expression, context, reporter) checkInvisibleSetter(expression, context, reporter)
checkValReassignmentViaBackingField(expression, context, reporter) checkValReassignmentViaBackingField(expression, context, reporter)
checkValReassignmentOnValueParameter(expression, context, reporter) checkValReassignmentOnValueParameter(expression, context, reporter)
checkAssignmentToThis(expression, context, reporter) checkVariableExpected(expression, context, reporter)
checkValReassignment(expression, context, reporter) checkValReassignment(expression, context, reporter)
} }
@@ -61,7 +58,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
return false return false
} }
val callableSymbol = expression.calleeReference.toResolvedCallableSymbol() val callableSymbol = expression.calleeReference?.toResolvedCallableSymbol()
if (callableSymbol is FirPropertySymbol && shouldInvisibleSetterBeReported(callableSymbol)) { if (callableSymbol is FirPropertySymbol && shouldInvisibleSetterBeReported(callableSymbol)) {
val explicitReceiver = expression.explicitReceiver val explicitReceiver = expression.explicitReceiver
// Try to get type from smartcast // Try to get type from smartcast
@@ -78,7 +75,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
} }
} }
reporter.reportOn( reporter.reportOn(
expression.source, expression.lValue.source,
FirErrors.INVISIBLE_SETTER, FirErrors.INVISIBLE_SETTER,
callableSymbol, callableSymbol,
callableSymbol.setterSymbol?.visibility ?: Visibilities.Private, callableSymbol.setterSymbol?.visibility ?: Visibilities.Private,
@@ -93,7 +90,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
context: CheckerContext, context: CheckerContext,
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
val backingFieldReference = expression.lValue as? FirBackingFieldReference ?: return val backingFieldReference = expression.calleeReference as? FirBackingFieldReference ?: return
val propertySymbol = backingFieldReference.resolvedSymbol val propertySymbol = backingFieldReference.resolvedSymbol
if (propertySymbol.isVar) return if (propertySymbol.isVar) return
val closestGetter = context.findClosest<FirPropertyAccessor> { it.isGetter }?.symbol ?: return val closestGetter = context.findClosest<FirPropertyAccessor> { it.isGetter }?.symbol ?: return
@@ -107,22 +104,37 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker()
context: CheckerContext, context: CheckerContext,
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
val valueParameter = expression.lValue.toResolvedValueParameterSymbol() ?: return val valueParameter = expression.calleeReference?.toResolvedValueParameterSymbol() ?: return
reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, valueParameter, context) reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, valueParameter, context)
} }
private fun checkAssignmentToThis( private fun checkVariableExpected(
expression: FirVariableAssignment, expression: FirVariableAssignment,
context: CheckerContext, context: CheckerContext,
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
if (expression.lValue is FirThisReference) { val calleeReference = expression.calleeReference
if (expression.unwrapLValue() !is FirPropertyAccessExpression ||
(calleeReference?.isConflictingError() != true && calleeReference?.toResolvedVariableSymbol() == null)
) {
reporter.reportOn(expression.lValue.source, FirErrors.VARIABLE_EXPECTED, context) reporter.reportOn(expression.lValue.source, FirErrors.VARIABLE_EXPECTED, context)
} }
} }
private fun FirReference.isConflictingError(): Boolean {
if (!isError()) return false
return when (val it = diagnostic) {
is ConeSimpleDiagnostic -> it.kind == DiagnosticKind.VariableExpected
is ConeUnresolvedNameError -> true
is ConeDiagnosticWithCandidates -> it.candidates.any { it.symbol is FirPropertySymbol }
else -> false
}
}
private fun checkValReassignment(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { private fun checkValReassignment(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
val property = expression.lValue.toResolvedPropertySymbol() ?: return val property = expression.calleeReference?.toResolvedPropertySymbol() ?: return
if (property.isVar) return if (property.isVar) return
// Assignments of uninitialized `val`s must be checked via CFG, since the first one is OK. // Assignments of uninitialized `val`s must be checked via CFG, since the first one is OK.
// See `FirPropertyInitializationAnalyzer` for locals and `FirMemberPropertiesChecker` for backing fields in initializers. // See `FirPropertyInitializationAnalyzer` for locals and `FirMemberPropertiesChecker` for backing fields in initializers.
@@ -36,7 +36,7 @@ object FirReturnSyntaxAndLabelChecker : FirReturnExpressionChecker() {
if (targetSymbol is FirAnonymousFunctionSymbol) { if (targetSymbol is FirAnonymousFunctionSymbol) {
val label = targetSymbol.label val label = targetSymbol.label
if (label?.source?.kind !is KtRealSourceElementKind) { if (label?.source?.kind !is KtRealSourceElementKind) {
val functionCall = context.qualifiedAccessOrAnnotationCalls.asReversed().find { val functionCall = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.asReversed().find {
it is FirFunctionCall && it is FirFunctionCall &&
(it.calleeReference.toResolvedFunctionSymbol())?.callableId == (it.calleeReference.toResolvedFunctionSymbol())?.callableId ==
FirSuspendCallChecker.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID FirSuspendCallChecker.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.isUnit
object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() { object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() {
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
val lastQualifiedAccess = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirQualifiedAccess val lastQualifiedAccess = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull() as? FirQualifiedAccessExpression
// Note: qualifier isn't standalone when it's in receiver (SomeClass.foo) or getClass (SomeClass::class) position // Note: qualifier isn't standalone when it's in receiver (SomeClass.foo) or getClass (SomeClass::class) position
if (lastQualifiedAccess?.explicitReceiver === expression || lastQualifiedAccess?.dispatchReceiver === expression) return if (lastQualifiedAccess?.explicitReceiver === expression || lastQualifiedAccess?.dispatchReceiver === expression) return
val lastGetClass = context.getClassCalls.lastOrNull() val lastGetClass = context.getClassCalls.lastOrNull()
@@ -33,7 +33,7 @@ object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionCh
// Make sure the current expression is not the receiver of a qualified access expression. // Make sure the current expression is not the receiver of a qualified access expression.
// E.g., for `T::toString`, which is a callable reference (a subtype of qualified access), type parameter T is checked once as an // E.g., for `T::toString`, which is a callable reference (a subtype of qualified access), type parameter T is checked once as an
// explicit receiver. When we visit `T` (as a qualified access expression), we should not regard it as an expression here. // explicit receiver. When we visit `T` (as a qualified access expression), we should not regard it as an expression here.
val secondLast = context.qualifiedAccessOrAnnotationCalls.elementAtOrNull(context.qualifiedAccessOrAnnotationCalls.size - 2) val secondLast = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.elementAtOrNull(context.qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 2)
if (secondLast is FirQualifiedAccessExpression && secondLast.explicitReceiver == expression) return if (secondLast is FirQualifiedAccessExpression && secondLast.explicitReceiver == expression) return
val diagnostic = expression.typeRef.coneTypeParameterInQualifiedAccess ?: return val diagnostic = expression.typeRef.coneTypeParameterInQualifiedAccess ?: return
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.*
object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() { object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() {
override fun check(expression: FirArrayOfCall, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirArrayOfCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (!isInsideAnnotationCall(expression, context) && if (!isInsideAnnotationCall(expression, context) &&
(context.qualifiedAccessOrAnnotationCalls.isNotEmpty() || !isInsideAnnotationClass(context)) (context.qualifiedAccessOrAssignmentsOrAnnotationCalls.isNotEmpty() || !isInsideAnnotationClass(context))
) { ) {
reporter.reportOn( reporter.reportOn(
expression.source, expression.source,
@@ -32,7 +32,7 @@ object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() {
} }
private fun isInsideAnnotationCall(expression: FirArrayOfCall, context: CheckerContext): Boolean { private fun isInsideAnnotationCall(expression: FirArrayOfCall, context: CheckerContext): Boolean {
context.qualifiedAccessOrAnnotationCalls.lastOrNull()?.let { context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull()?.let {
val arguments = when (it) { val arguments = when (it) {
is FirFunctionCall -> is FirFunctionCall ->
if (it.typeRef.toRegularClassSymbol(context.session)?.classKind == ClassKind.ANNOTATION_CLASS) { if (it.typeRef.toRegularClassSymbol(context.session)?.classKind == ClassKind.ANNOTATION_CLASS) {
@@ -87,4 +87,4 @@ object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() {
return false return false
} }
} }
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.dispatchReceiverClassTypeOrNull import org.jetbrains.kotlin.fir.dispatchReceiverClassTypeOrNull
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
@@ -32,7 +33,7 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression
object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker() { object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker() {
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
val lValue = expression.lValue val lValue = expression.calleeReference
if (lValue !is FirResolvedNamedReference) return if (lValue !is FirResolvedNamedReference) return
if (expression.source?.kind is KtFakeSourceElementKind) return if (expression.source?.kind is KtFakeSourceElementKind) return
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoData import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoData
import org.jetbrains.kotlin.fir.expressions.calleeReference
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -48,7 +49,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
override fun visitNode(node: CFGNode<*>) {} override fun visitNode(node: CFGNode<*>) {}
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) { override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: return val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return
if (symbol.isVar && symbol.source?.kind !is KtFakeSourceElementKind && symbol in data.properties && if (symbol.isVar && symbol.source?.kind !is KtFakeSourceElementKind && symbol in data.properties &&
(!symbol.requiresInitialization || data.getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) (!symbol.requiresInitialization || data.getValue(node).values.any { it[symbol]?.canBeRevisited() == true })
) { ) {
@@ -44,7 +44,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
override fun visitNode(node: CFGNode<*>) {} override fun visitNode(node: CFGNode<*>) {}
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) { override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val variableSymbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: return val variableSymbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return
val dataPerNode = data[node] ?: return val dataPerNode = data[node] ?: return
for (dataPerLabel in dataPerNode.values) { for (dataPerLabel in dataPerNode.values) {
val data = dataPerLabel[variableSymbol] ?: continue val data = dataPerLabel[variableSymbol] ?: continue
@@ -210,7 +210,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
data: PathAwareVariableStatusInfo data: PathAwareVariableStatusInfo
): PathAwareVariableStatusInfo { ): PathAwareVariableStatusInfo {
val dataForNode = visitNode(node, data) val dataForNode = visitNode(node, data)
val symbol = node.fir.lValue.toResolvedPropertySymbol() ?: return dataForNode val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return dataForNode
return update(dataForNode, symbol) update@{ prev -> return update(dataForNode, symbol) update@{ prev ->
val toPut = when { val toPut = when {
symbol !in localProperties -> { symbol !in localProperties -> {
@@ -247,7 +247,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
annotation: FirAnnotation, annotation: FirAnnotation,
): PathAwareVariableStatusInfo { ): PathAwareVariableStatusInfo {
return if (annotation is FirAnnotationCall) { return if (annotation is FirAnnotationCall) {
val qualifiedAccesses = annotation.argumentList.arguments.mapNotNull { it as? FirQualifiedAccess }.toTypedArray() val qualifiedAccesses = annotation.argumentList.arguments.mapNotNull { it as? FirQualifiedAccessExpression }.toTypedArray()
visitQualifiedAccesses(dataForNode, *qualifiedAccesses) visitQualifiedAccesses(dataForNode, *qualifiedAccesses)
} else { } else {
dataForNode dataForNode
@@ -256,9 +256,9 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() {
private fun visitQualifiedAccesses( private fun visitQualifiedAccesses(
dataForNode: PathAwareVariableStatusInfo, dataForNode: PathAwareVariableStatusInfo,
vararg qualifiedAccesses: FirQualifiedAccess, vararg qualifiedAccesses: FirQualifiedAccessExpression,
): PathAwareVariableStatusInfo { ): PathAwareVariableStatusInfo {
fun retrieveSymbol(qualifiedAccess: FirQualifiedAccess): FirPropertySymbol? { fun retrieveSymbol(qualifiedAccess: FirQualifiedAccessExpression): FirPropertySymbol? {
return qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.takeIf { it in localProperties } return qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.takeIf { it in localProperties }
} }
@@ -36,7 +36,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() {
val symbol = coneType.lookupTag.toSymbol(context.session) ?: return val symbol = coneType.lookupTag.toSymbol(context.session) ?: return
symbol.lazyResolveToPhase(FirResolvePhase.STATUS) symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
val classId = symbol.classId val classId = symbol.classId
val lastAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirAnnotation val lastAnnotationCall = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull() as? FirAnnotation
if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) { if (lastAnnotationCall == null || lastAnnotationCall.annotationTypeRef !== typeRef) {
if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) { if (classId == OptInNames.REQUIRES_OPT_IN_CLASS_ID || classId == OptInNames.OPT_IN_CLASS_ID) {
reporter.reportOn(source, OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION, context) reporter.reportOn(source, OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION, context)
@@ -36,9 +36,13 @@ abstract class AbstractDiagnosticCollectorVisitor(
override fun visitElement(element: FirElement, data: Nothing?) { override fun visitElement(element: FirElement, data: Nothing?) {
if (element is FirAnnotationContainer) { if (element is FirAnnotationContainer) {
visitAnnotationContainer(element, data) withAnnotationContainer(element) {
checkElement(element)
visitNestedElements(element)
}
return return
} }
checkElement(element) checkElement(element)
visitNestedElements(element) visitNestedElements(element)
} }
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.types.ConeErrorType import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.renderForDebugging
class ErrorNodeDiagnosticCollectorComponent( class ErrorNodeDiagnosticCollectorComponent(
session: FirSession, session: FirSession,
@@ -63,13 +60,9 @@ class ErrorNodeDiagnosticCollectorComponent(
private fun processErrorReference(reference: FirNamedReference, diagnostic: ConeDiagnostic, context: CheckerContext) { private fun processErrorReference(reference: FirNamedReference, diagnostic: ConeDiagnostic, context: CheckerContext) {
val source = reference.source ?: return val source = reference.source ?: return
val qualifiedAccessOrAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf { val qualifiedAccessOrAnnotationCall = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull()?.takeIf {
// Use the source of the enclosing FirQualifiedAccess if it is exactly the call to the erroneous callee. // Use the source of the enclosing FirQualifiedAccess if it is exactly the call to the erroneous callee.
when (it) { it.calleeReference == reference
is FirQualifiedAccess -> it.calleeReference == reference
is FirAnnotationCall -> it.calleeReference == reference
else -> false
}
} }
// Don't report duplicated unresolved reference on annotation entry (already reported on its type) // Don't report duplicated unresolved reference on annotation entry (already reported on its type)
if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return
@@ -79,7 +72,7 @@ class ErrorNodeDiagnosticCollectorComponent(
) return ) return
// If the receiver cannot be resolved, we skip reporting any further problems for this call. // If the receiver cannot be resolved, we skip reporting any further problems for this call.
if (qualifiedAccessOrAnnotationCall is FirQualifiedAccess) { if (qualifiedAccessOrAnnotationCall is FirQualifiedAccessExpression) {
if (qualifiedAccessOrAnnotationCall.dispatchReceiver.cannotBeResolved() || if (qualifiedAccessOrAnnotationCall.dispatchReceiver.cannotBeResolved() ||
qualifiedAccessOrAnnotationCall.extensionReceiver.cannotBeResolved() || qualifiedAccessOrAnnotationCall.extensionReceiver.cannotBeResolved() ||
qualifiedAccessOrAnnotationCall.explicitReceiver.cannotBeResolved() qualifiedAccessOrAnnotationCall.explicitReceiver.cannotBeResolved()
@@ -91,10 +91,6 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidateSymbols) is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidateSymbols)
is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.createOn(source) is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.createOn(source)
is ConeValReassignmentError -> when (val symbol = this.variable) {
is FirBackingFieldSymbol -> FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.errorFactory.createOn(source, symbol)
else -> FirErrors.VAL_REASSIGNMENT.createOn(source, symbol)
}
is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source ?: source) is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source ?: source)
is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString()) is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString())
@@ -727,7 +727,6 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
} }
private fun FlowContent.generate(variableAssignment: FirVariableAssignment) { private fun FlowContent.generate(variableAssignment: FirVariableAssignment) {
generateReceiver(variableAssignment)
generate(variableAssignment.lValue) generate(variableAssignment.lValue)
+" = " +" = "
generate(variableAssignment.rValue) generate(variableAssignment.rValue)
@@ -1324,7 +1323,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
} }
} }
private fun FlowContent.generateReceiver(access: FirQualifiedAccess) { private fun FlowContent.generateReceiver(access: FirQualifiedAccessExpression) {
val explicitReceiver = access.explicitReceiver val explicitReceiver = access.explicitReceiver
if (explicitReceiver != null) { if (explicitReceiver != null) {
generate(explicitReceiver) generate(explicitReceiver)
@@ -1608,14 +1607,10 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
+"?." +"?."
val selector = safeCallExpression.selector val selector = safeCallExpression.selector
if (selector is FirQualifiedAccess && selector.explicitReceiver == safeCallExpression.checkedSubjectRef.value) { if (selector is FirQualifiedAccessExpression && selector.explicitReceiver == safeCallExpression.checkedSubjectRef.value) {
when (selector) { return when (selector) {
is FirFunctionCall -> { is FirFunctionCall -> generate(selector, skipReceiver = true)
return generate(selector, skipReceiver = true) else -> generate(selector, skipReceiver = true)
}
is FirQualifiedAccessExpression -> {
return generate(selector, skipReceiver = true)
}
} }
} }
@@ -78,7 +78,14 @@ internal fun <T : IrElement> KtSourceElement?.convertWithOffsets(
return f(startOffset, endOffset) return f(startOffset, endOffset)
} }
internal fun <T : IrElement> FirQualifiedAccess.convertWithOffsets( internal fun <T : IrElement> FirQualifiedAccessExpression.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
return convertWithOffsets(this.calleeReference, f)
}
internal fun <T : IrElement> FirStatement.convertWithOffsets(
calleeReference: FirReference,
f: (startOffset: Int, endOffset: Int) -> T f: (startOffset: Int, endOffset: Int) -> T
): T { ): T {
val psi = calleeReference.psi val psi = calleeReference.psi
@@ -718,7 +725,7 @@ fun FirDeclaration?.computeIrOrigin(predefinedOrigin: IrDeclarationOrigin? = nul
} }
fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin { fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin {
val calleeReferenceSymbol = calleeReference.toResolvedCallableSymbol() ?: return IrStatementOrigin.EQ val calleeReferenceSymbol = calleeReference?.toResolvedCallableSymbol() ?: return IrStatementOrigin.EQ
val rValue = rValue val rValue = rValue
if (rValue is FirFunctionCall && calleeReferenceSymbol.callableId.isLocal) { if (rValue is FirFunctionCall && calleeReferenceSymbol.callableId.isLocal) {
val callableId = rValue.calleeReference.toResolvedCallableSymbol()?.callableId val callableId = rValue.calleeReference.toResolvedCallableSymbol()?.callableId
@@ -736,9 +743,8 @@ fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin {
IrStatementOrigin.POSTFIX_DECR IrStatementOrigin.POSTFIX_DECR
} }
if (calleeReference.source?.kind is KtFakeSourceElementKind && val kind = rValue.source?.kind
calleeReferenceSymbol == rValue.explicitReceiver?.toResolvedCallableSymbol() if (kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement || kind == KtFakeSourceElementKind.DesugaredCompoundAssignment) {
) {
if (callableName == OperatorNameConventions.PLUS) { if (callableName == OperatorNameConventions.PLUS) {
return IrStatementOrigin.PLUSEQ return IrStatementOrigin.PLUSEQ
} else if (callableName == OperatorNameConventions.MINUS) { } else if (callableName == OperatorNameConventions.MINUS) {
@@ -913,7 +913,7 @@ class Fir2IrDeclarationStorage(
val setter = property.setter val setter = property.setter
if (delegate != null || property.hasBackingField) { if (delegate != null || property.hasBackingField) {
backingField = if (delegate != null) { backingField = if (delegate != null) {
((delegate as? FirQualifiedAccess)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let { ((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let {
classifierStorage.preCacheTypeParameters(it, symbol) classifierStorage.preCacheTypeParameters(it, symbol)
} }
createBackingField( createBackingField(
@@ -274,10 +274,10 @@ class Fir2IrImplicitCastInserter(
internal fun implicitCastFromDispatchReceiver( internal fun implicitCastFromDispatchReceiver(
original: IrExpression, original: IrExpression,
originalTypeRef: FirTypeRef, originalTypeRef: FirTypeRef,
calleeReference: FirReference, calleeReference: FirReference?,
conversionTypeContext: ConversionTypeContext, conversionTypeContext: ConversionTypeContext,
): IrExpression { ): IrExpression {
val referencedDeclaration = calleeReference.toResolvedCallableSymbol()?.unwrapCallRepresentative()?.fir val referencedDeclaration = calleeReference?.toResolvedCallableSymbol()?.unwrapCallRepresentative()?.fir
val dispatchReceiverType = val dispatchReceiverType =
referencedDeclaration?.dispatchReceiverType as? ConeClassLikeType referencedDeclaration?.dispatchReceiverType as? ConeClassLikeType
@@ -704,7 +704,7 @@ class Fir2IrVisitor(
internal fun convertToIrReceiverExpression( internal fun convertToIrReceiverExpression(
expression: FirExpression?, expression: FirExpression?,
calleeReference: FirReference, calleeReference: FirReference?,
callableReferenceAccess: FirCallableReferenceAccess? = null callableReferenceAccess: FirCallableReferenceAccess? = null
): IrExpression? { ): IrExpression? {
return when (expression) { return when (expression) {
@@ -779,7 +779,7 @@ class Fir2IrVisitor(
val incrementStatement = this[index + 1] val incrementStatement = this[index + 1]
if (incrementStatement !is FirVariableAssignment) return null if (incrementStatement !is FirVariableAssignment) return null
if (incrementStatement.lValue.toResolvedCallableSymbol() != variable) return null if (incrementStatement.calleeReference?.toResolvedCallableSymbol() != variable) return null
val origin = incrementStatement.getIrAssignmentOrigin() val origin = incrementStatement.getIrAssignmentOrigin()
return if (origin == IrStatementOrigin.EQ) null else origin return if (origin == IrStatementOrigin.EQ) null else origin
@@ -180,7 +180,10 @@ internal class AdapterGenerator(
} }
} }
private fun FirQualifiedAccess.findBoundReceiver(explicitReceiverExpression: IrExpression?, isDispatch: Boolean): IrExpression? { private fun FirCallableReferenceAccess.findBoundReceiver(
explicitReceiverExpression: IrExpression?,
isDispatch: Boolean
): IrExpression? {
val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver
if (firReceiver is FirNoReceiverExpression) { if (firReceiver is FirNoReceiverExpression) {
return null return null
@@ -213,7 +213,7 @@ class CallAndReferenceGenerator(
return newType.toTypeProjection(typeProjection.kind) return newType.toTypeProjection(typeProjection.kind)
} }
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? { private fun FirQualifiedAccessExpression.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
val fir = calleeReference.resolvedSymbol.fir val fir = calleeReference.resolvedSymbol.fir
if (this is FirFunctionCall && fir is FirSimpleFunction && fir.origin == FirDeclarationOrigin.SamConstructor) { if (this is FirFunctionCall && fir is FirSimpleFunction && fir.origin == FirDeclarationOrigin.SamConstructor) {
@@ -227,7 +227,7 @@ class CallAndReferenceGenerator(
} }
private fun FirExpression.superQualifierSymbol(): IrClassSymbol? { private fun FirExpression.superQualifierSymbol(): IrClassSymbol? {
if (this !is FirQualifiedAccess) { if (this !is FirQualifiedAccessExpression) {
return null return null
} }
val dispatchReceiverReference = calleeReference val dispatchReceiverReference = calleeReference
@@ -264,7 +264,7 @@ class CallAndReferenceGenerator(
else -> null else -> null
} }
private val FirQualifiedAccess.dynamicOperator private val FirQualifiedAccessExpression.dynamicOperator
get() = when (calleeReference.source?.kind) { get() = when (calleeReference.source?.kind) {
is KtFakeSourceElementKind.ArrayAccessNameReference -> when (calleeReference.resolved?.name) { is KtFakeSourceElementKind.ArrayAccessNameReference -> when (calleeReference.resolved?.name) {
OperatorNameConventions.SET -> IrDynamicOperator.EQ OperatorNameConventions.SET -> IrDynamicOperator.EQ
@@ -288,7 +288,7 @@ class CallAndReferenceGenerator(
} }
private fun convertToIrCallForDynamic( private fun convertToIrCallForDynamic(
qualifiedAccess: FirQualifiedAccess, qualifiedAccess: FirQualifiedAccessExpression,
explicitReceiverExpression: IrExpression, explicitReceiverExpression: IrExpression,
type: IrType, type: IrType,
calleeReference: FirReference, calleeReference: FirReference,
@@ -333,7 +333,7 @@ class CallAndReferenceGenerator(
} }
fun convertToIrCall( fun convertToIrCall(
qualifiedAccess: FirQualifiedAccess, qualifiedAccess: FirQualifiedAccessExpression,
typeRef: FirTypeRef, typeRef: FirTypeRef,
explicitReceiverExpression: IrExpression?, explicitReceiverExpression: IrExpression?,
annotationMode: Boolean = false, annotationMode: Boolean = false,
@@ -501,13 +501,15 @@ class CallAndReferenceGenerator(
else -> generateErrorCallExpression(startOffset, endOffset, calleeReference) else -> generateErrorCallExpression(startOffset, endOffset, calleeReference)
} }
}.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment, convertedExplicitReceiver) }.apply {
variableAssignment.unwrapLValue()?.let { applyReceivers(it, convertedExplicitReceiver) }
}
} }
fun convertToIrSetCall(variableAssignment: FirVariableAssignment, explicitReceiverExpression: IrExpression?): IrExpression { fun convertToIrSetCall(variableAssignment: FirVariableAssignment, explicitReceiverExpression: IrExpression?): IrExpression {
try { try {
val type = irBuiltIns.unitType val type = irBuiltIns.unitType
val calleeReference = variableAssignment.calleeReference val calleeReference = variableAssignment.calleeReference ?: error("Reference not resolvable")
val assignedValue = visitor.convertToIrExpression(variableAssignment.rValue) val assignedValue = visitor.convertToIrExpression(variableAssignment.rValue)
val firSymbol = calleeReference.toResolvedBaseSymbol() val firSymbol = calleeReference.toResolvedBaseSymbol()
@@ -532,7 +534,8 @@ class CallAndReferenceGenerator(
) )
val origin = variableAssignment.getIrAssignmentOrigin() val origin = variableAssignment.getIrAssignmentOrigin()
return variableAssignment.convertWithOffsets { startOffset, endOffset -> val lValue = variableAssignment.unwrapLValue() ?: error("Assignment lValue unwrapped to null")
return variableAssignment.convertWithOffsets(calleeReference) { startOffset, endOffset ->
when (symbol) { when (symbol) {
is IrFieldSymbol -> IrSetFieldImpl(startOffset, endOffset, symbol, type, origin).apply { is IrFieldSymbol -> IrSetFieldImpl(startOffset, endOffset, symbol, type, origin).apply {
value = assignedValue value = assignedValue
@@ -548,7 +551,7 @@ class CallAndReferenceGenerator(
origin = origin, origin = origin,
superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol() superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol()
).apply { ).apply {
putContextReceiverArguments(variableAssignment) putContextReceiverArguments(lValue)
putValueArgument(0, assignedValue) putValueArgument(0, assignedValue)
} }
@@ -568,7 +571,7 @@ class CallAndReferenceGenerator(
origin = origin, origin = origin,
superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol() superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol()
).apply { ).apply {
putValueArgument(putContextReceiverArguments(variableAssignment), assignedValue) putValueArgument(putContextReceiverArguments(lValue), assignedValue)
} }
backingField != null -> IrSetFieldImpl( backingField != null -> IrSetFieldImpl(
@@ -600,7 +603,7 @@ class CallAndReferenceGenerator(
else -> generateErrorCallExpression(startOffset, endOffset, calleeReference) else -> generateErrorCallExpression(startOffset, endOffset, calleeReference)
} }
}.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment, explicitReceiverExpression) }.applyTypeArguments(lValue).applyReceivers(lValue, explicitReceiverExpression)
} catch (e: Throwable) { } catch (e: Throwable) {
throw IllegalStateException( throw IllegalStateException(
"Error while translating ${variableAssignment.render()} " + "Error while translating ${variableAssignment.render()} " +
@@ -957,7 +960,7 @@ class CallAndReferenceGenerator(
return this return this
} }
internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression { internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccessExpression): IrExpression {
if (this !is IrMemberAccessExpression<*>) return this if (this !is IrMemberAccessExpression<*>) return this
val argumentsCount = access.typeArguments.size val argumentsCount = access.typeArguments.size
if (argumentsCount <= typeArgumentsCount) { if (argumentsCount <= typeArgumentsCount) {
@@ -986,16 +989,16 @@ class CallAndReferenceGenerator(
} }
} }
private fun FirQualifiedAccess.findTypeParameter(index: Int): FirTypeParameter? = private fun FirQualifiedAccessExpression.findTypeParameter(index: Int): FirTypeParameter? =
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirTypeParametersOwner)?.typeParameters?.get(index) ((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirTypeParametersOwner)?.typeParameters?.get(index)
private fun FirQualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = private fun FirQualifiedAccessExpression.findIrDispatchReceiver(explicitReceiverExpression: IrExpression?): IrExpression? =
findIrReceiver(explicitReceiverExpression, isDispatch = true) findIrReceiver(explicitReceiverExpression, isDispatch = true)
private fun FirQualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = private fun FirQualifiedAccessExpression.findIrExtensionReceiver(explicitReceiverExpression: IrExpression?): IrExpression? =
findIrReceiver(explicitReceiverExpression, isDispatch = false) findIrReceiver(explicitReceiverExpression, isDispatch = false)
internal fun FirQualifiedAccess.findIrReceiver(explicitReceiverExpression: IrExpression?, isDispatch: Boolean): IrExpression? { internal fun FirQualifiedAccessExpression.findIrReceiver(explicitReceiverExpression: IrExpression?, isDispatch: Boolean): IrExpression? {
val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver val firReceiver = if (isDispatch) dispatchReceiver else extensionReceiver
if (firReceiver == explicitReceiver) { if (firReceiver == explicitReceiver) {
return explicitReceiverExpression return explicitReceiverExpression
@@ -1011,7 +1014,7 @@ class CallAndReferenceGenerator(
} }
} }
private fun IrExpression.applyReceivers(qualifiedAccess: FirQualifiedAccess, explicitReceiverExpression: IrExpression?): IrExpression { private fun IrExpression.applyReceivers(qualifiedAccess: FirQualifiedAccessExpression, explicitReceiverExpression: IrExpression?): IrExpression {
when (this) { when (this) {
is IrMemberAccessExpression<*> -> { is IrMemberAccessExpression<*> -> {
val ownerFunction = val ownerFunction =
@@ -552,7 +552,7 @@ class ExpressionsConverter(
} }
var result = firSelector var result = firSelector
(firSelector as? FirQualifiedAccess)?.let { (firSelector as? FirQualifiedAccessExpression)?.let {
if (isSafe) { if (isSafe) {
@OptIn(FirImplementationDetail::class) @OptIn(FirImplementationDetail::class)
it.replaceSource(dotQualifiedExpression.toFirSourceElement(KtFakeSourceElementKind.DesugaredSafeCallExpression)) it.replaceSource(dotQualifiedExpression.toFirSourceElement(KtFakeSourceElementKind.DesugaredSafeCallExpression))
@@ -562,7 +562,7 @@ class ExpressionsConverter(
) )
} }
result = convertFirSelector(it, dotQualifiedExpression.toFirSourceElement(), firReceiver!!) as? FirExpression result = convertFirSelector(it, dotQualifiedExpression.toFirSourceElement(), firReceiver!!)
} }
val receiver = firReceiver val receiver = firReceiver
@@ -663,7 +663,7 @@ class ExpressionsConverter(
) )
} }
val builder: FirQualifiedAccessBuilder = if (hasArguments) { val builder: FirQualifiedAccessExpressionBuilder = if (hasArguments) {
val builder = if (isImplicitInvoke) FirImplicitInvokeCallBuilder() else FirFunctionCallBuilder() val builder = if (isImplicitInvoke) FirImplicitInvokeCallBuilder() else FirFunctionCallBuilder()
builder.apply { builder.apply {
this.source = source this.source = source
@@ -682,7 +682,7 @@ class ExpressionsConverter(
return builder.apply { return builder.apply {
this.explicitReceiver = explicitReceiver this.explicitReceiver = explicitReceiver
typeArguments += firTypeArguments typeArguments += firTypeArguments
}.build() as FirExpression }.build()
} }
/** /**
@@ -2545,7 +2545,7 @@ open class RawFirBuilder(
val source = expression.toFirSourceElement() val source = expression.toFirSourceElement()
val (calleeReference, explicitReceiver, isImplicitInvoke) = splitToCalleeAndReceiver(expression.calleeExpression, source) val (calleeReference, explicitReceiver, isImplicitInvoke) = splitToCalleeAndReceiver(expression.calleeExpression, source)
val result: FirQualifiedAccessBuilder = if (expression.valueArgumentList == null && expression.lambdaArguments.isEmpty()) { val result: FirQualifiedAccessExpressionBuilder = if (expression.valueArgumentList == null && expression.lambdaArguments.isEmpty()) {
FirPropertyAccessExpressionBuilder().apply { FirPropertyAccessExpressionBuilder().apply {
this.source = source this.source = source
this.calleeReference = calleeReference this.calleeReference = calleeReference
@@ -2603,7 +2603,7 @@ open class RawFirBuilder(
} }
val firSelector = selector.toFirExpression("Incorrect selector expression") val firSelector = selector.toFirExpression("Incorrect selector expression")
if (firSelector is FirQualifiedAccess) { if (firSelector is FirQualifiedAccessExpression) {
if (expression is KtSafeQualifiedExpression) { if (expression is KtSafeQualifiedExpression) {
@OptIn(FirImplementationDetail::class) @OptIn(FirImplementationDetail::class)
firSelector.replaceSource(expression.toFirSourceElement(KtFakeSourceElementKind.DesugaredSafeCallExpression)) firSelector.replaceSource(expression.toFirSourceElement(KtFakeSourceElementKind.DesugaredSafeCallExpression))
@@ -11,15 +11,10 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.isCatchParameter
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference
import org.jetbrains.kotlin.fir.references.isError import org.jetbrains.kotlin.fir.references.isError
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderer.FirRenderer import org.jetbrains.kotlin.fir.renderer.FirRenderer
@@ -84,15 +79,15 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
errorExpression.psi?.let { println(it) } errorExpression.psi?.let { println(it) }
} }
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) { override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: FirElement) {
val calleeReference = qualifiedAccess.calleeReference val calleeReference = qualifiedAccessExpression.calleeReference
if (calleeReference.isError()) { if (calleeReference.isError()) {
errorReferences++ errorReferences++
println((calleeReference as FirDiagnosticHolder).diagnostic.reason) println((calleeReference as FirDiagnosticHolder).diagnostic.reason)
} else { } else {
normalReferences++ normalReferences++
} }
visitStatement(qualifiedAccess, data) visitStatement(qualifiedAccessExpression, data)
} }
override fun visitExpression(expression: FirExpression, data: FirElement) { override fun visitExpression(expression: FirExpression, data: FirElement) {
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
@@ -558,9 +556,12 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
resultInitializer, resultInitializer,
FirOperation.ASSIGN, FirOperation.ASSIGN,
resultInitializer.annotations, resultInitializer.annotations,
null, null
convert ) {
) // We want the DesugaredAssignmentValueReferenceExpression on the LHS to point to the same receiver instance
// as in the initializer, therefore don't create a new instance here if the argument is the receiver.
if (this == unwrappedReceiver) convertedReceiver else convert()
}
if (assignment is FirBlock) { if (assignment is FirBlock) {
statements += assignment.statements statements += assignment.statements
@@ -695,6 +696,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
* } * }
* *
*/ */
@OptIn(FirContractViolation::class)
private fun generateIncrementOrDecrementBlockForQualifiedAccess( private fun generateIncrementOrDecrementBlockForQualifiedAccess(
wholeExpression: T, wholeExpression: T,
operationReference: T?, operationReference: T?,
@@ -708,7 +710,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
convert, convert,
receiverForOperation.toFirSourceElement(), receiverForOperation.toFirSourceElement(),
) { qualifiedFir -> ) { qualifiedFir ->
val receiverFir = (qualifiedFir as? FirQualifiedAccess)?.explicitReceiver ?: buildErrorExpression { val receiverFir = (qualifiedFir as? FirQualifiedAccessExpression)?.explicitReceiver ?: buildErrorExpression {
source = receiverForOperation.toFirSourceElement() source = receiverForOperation.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax)
} }
@@ -724,7 +726,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
initializer = receiverFir, initializer = receiverFir,
).also { statements += it } ).also { statements += it }
val firArgument = generateResolvedAccessExpression(argumentReceiverVariable.source, argumentReceiverVariable).let { receiver -> val receiverSource = receiverFir.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
val firArgument = generateResolvedAccessExpression(receiverSource, argumentReceiverVariable).let { receiver ->
qualifiedFir.also { if (it is FirQualifiedAccessExpression) it.replaceExplicitReceiver(receiver) } qualifiedFir.also { if (it is FirQualifiedAccessExpression) it.replaceExplicitReceiver(receiver) }
} }
@@ -735,16 +738,15 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements
statements += buildVariableAssignment { statements += buildVariableAssignment {
source = desugaredSource source = desugaredSource
lValue = buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(firArgument) }
source = firArgument.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
}
rValue = if (prefix) { rValue = if (prefix) {
generateResolvedAccessExpression(source, resultVar) generateResolvedAccessExpression(source, resultVar)
} else { } else {
resultInitializer resultInitializer
} }
explicitReceiver = generateResolvedAccessExpression(argumentReceiverVariable.source, argumentReceiverVariable)
calleeReference = buildSimpleNamedReference {
source = firArgument.calleeReference.source
name = (firArgument.calleeReference as FirSimpleNamedReference).name
}
} }
} }
} }
@@ -891,46 +893,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
} }
private fun FirQualifiedAccessBuilder.initializeLValue(
left: T?,
convertQualified: T.() -> FirQualifiedAccess?
): FirReference {
val tokenType = left?.elementType
if (left != null) {
when (tokenType) {
REFERENCE_EXPRESSION -> {
return buildSimpleNamedReference {
source = left.toFirSourceElement()
name = left.getReferencedNameAsName()
}
}
THIS_EXPRESSION -> {
return buildExplicitThisReference {
source = left.toFirSourceElement()
labelName = left.getLabelName()
}
}
DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> {
val firMemberAccess = left.convertQualified()
return if (firMemberAccess != null) {
explicitReceiver = firMemberAccess.explicitReceiver
firMemberAccess.calleeReference
} else {
buildErrorNamedReference {
source = left.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported qualified LValue: ${left.asText}", DiagnosticKind.Syntax)
}
}
}
}
}
return buildErrorNamedReference {
source = left?.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported LValue: $tokenType", DiagnosticKind.VariableExpected)
}
}
// T is a PSI or a light-tree node // T is a PSI or a light-tree node
@OptIn(FirContractViolation::class)
fun T?.generateAssignment( fun T?.generateAssignment(
baseSource: KtSourceElement?, baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?, arrayAccessSource: KtSourceElement?,
@@ -1010,10 +974,18 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
} }
val assignmentLValue = unwrappedLhs.convert()
return buildVariableAssignment { return buildVariableAssignment {
source = baseSource source = baseSource
lValue = if (baseSource?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement) {
buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(assignmentLValue) }
source = assignmentLValue.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
}
} else {
assignmentLValue
}
rValue = rhsExpression rValue = rhsExpression
calleeReference = initializeLValue(unwrappedLhs) { convert() as? FirQualifiedAccess }
this.annotations += annotations this.annotations += annotations
} }
} }
@@ -1025,13 +997,12 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
rhsExpression: FirExpression, rhsExpression: FirExpression,
annotations: List<FirAnnotation> annotations: List<FirAnnotation>
): FirSafeCallExpression { ): FirSafeCallExpression {
val nestedAccess = safeCallNonAssignment.selector as FirQualifiedAccess val nestedAccess = safeCallNonAssignment.selector as FirQualifiedAccessExpression
val assignment = buildVariableAssignment { val assignment = buildVariableAssignment {
source = baseSource source = baseSource
lValue = nestedAccess
rValue = rhsExpression rValue = rhsExpression
calleeReference = nestedAccess.calleeReference
explicitReceiver = safeCallNonAssignment.checkedSubjectRef.value
this.annotations += annotations this.annotations += annotations
} }
@@ -1228,10 +1199,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
protected fun convertFirSelector( protected fun convertFirSelector(
firSelector: FirQualifiedAccess, firSelector: FirQualifiedAccessExpression,
source: KtSourceElement?, source: KtSourceElement?,
receiver: FirExpression receiver: FirExpression
): FirQualifiedAccess { ): FirQualifiedAccessExpression {
return if (firSelector is FirImplicitInvokeCall) { return if (firSelector is FirImplicitInvokeCall) {
buildImplicitInvokeCall { buildImplicitInvokeCall {
this.source = source this.source = source
@@ -531,7 +531,7 @@ private fun FirExpression.checkReceiver(name: String?): Boolean {
// this = .f(...) // this = .f(...)
// receiver = <expr> // receiver = <expr>
// Returns safe call <expr>?.{ f(...) } // Returns safe call <expr>?.{ f(...) }
fun FirQualifiedAccess.createSafeCall(receiver: FirExpression, source: KtSourceElement): FirSafeCallExpression { fun FirQualifiedAccessExpression.createSafeCall(receiver: FirExpression, source: KtSourceElement): FirSafeCallExpression {
val checkedSafeCallSubject = buildCheckedSafeCallSubject { val checkedSafeCallSubject = buildCheckedSafeCallSubject {
@OptIn(FirContractViolation::class) @OptIn(FirContractViolation::class)
this.originalReceiverRef = FirExpressionRef<FirExpression>().apply { this.originalReceiverRef = FirExpressionRef<FirExpression>().apply {
@@ -555,7 +555,7 @@ fun FirQualifiedAccess.createSafeCall(receiver: FirExpression, source: KtSourceE
// Turns (a?.b).f(...) to a?.{ b.f(...) ) -- for any qualified access `.f(...)` // Turns (a?.b).f(...) to a?.{ b.f(...) ) -- for any qualified access `.f(...)`
// Other patterns remain unchanged // Other patterns remain unchanged
fun FirExpression.pullUpSafeCallIfNecessary(): FirExpression { fun FirExpression.pullUpSafeCallIfNecessary(): FirExpression {
if (this !is FirQualifiedAccess) return this if (this !is FirQualifiedAccessExpression) return this
val safeCall = explicitReceiver as? FirSafeCallExpression ?: return this val safeCall = explicitReceiver as? FirSafeCallExpression ?: return this
val safeCallSelector = safeCall.selector as? FirExpression ?: return this val safeCallSelector = safeCall.selector as? FirExpression ?: return this
@@ -121,8 +121,8 @@ class FirCallResolver(
) )
/** WARNING: This function is public for the analysis API and should only be used there. */ /** WARNING: This function is public for the analysis API and should only be used there. */
fun <T : FirQualifiedAccess> collectAllCandidates( fun collectAllCandidates(
qualifiedAccess: T, qualifiedAccess: FirQualifiedAccessExpression,
name: Name, name: Name,
containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations, containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations,
resolutionContext: ResolutionContext = transformer.resolutionContext resolutionContext: ResolutionContext = transformer.resolutionContext
@@ -134,21 +134,22 @@ class FirCallResolver(
return collector.allCandidates.map { OverloadCandidate(it, isInBestCandidates = it in result.candidates) } return collector.allCandidates.map { OverloadCandidate(it, isInBestCandidates = it in result.candidates) }
} }
private fun <T : FirQualifiedAccess> collectCandidates( private fun collectCandidates(
qualifiedAccess: T, qualifiedAccess: FirQualifiedAccessExpression,
name: Name, name: Name,
forceCallKind: CallKind? = null, forceCallKind: CallKind? = null,
origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular, origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular,
containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations, containingDeclarations: List<FirDeclaration> = transformer.components.containingDeclarations,
resolutionContext: ResolutionContext = transformer.resolutionContext, resolutionContext: ResolutionContext = transformer.resolutionContext,
collector: CandidateCollector? = null collector: CandidateCollector? = null,
callSite: FirElement = qualifiedAccess,
): ResolutionResult { ): ResolutionResult {
val explicitReceiver = qualifiedAccess.explicitReceiver val explicitReceiver = qualifiedAccess.explicitReceiver
val argumentList = (qualifiedAccess as? FirFunctionCall)?.argumentList ?: FirEmptyArgumentList val argumentList = (qualifiedAccess as? FirFunctionCall)?.argumentList ?: FirEmptyArgumentList
val typeArguments = (qualifiedAccess as? FirFunctionCall)?.typeArguments.orEmpty() val typeArguments = (qualifiedAccess as? FirFunctionCall)?.typeArguments.orEmpty()
val info = CallInfo( val info = CallInfo(
qualifiedAccess, callSite,
forceCallKind ?: if (qualifiedAccess is FirFunctionCall) CallKind.Function else CallKind.VariableAccess, forceCallKind ?: if (qualifiedAccess is FirFunctionCall) CallKind.Function else CallKind.VariableAccess,
name, name,
explicitReceiver, explicitReceiver,
@@ -188,8 +189,12 @@ class FirCallResolver(
return ResolutionResult(info, result.currentApplicability, reducedCandidates) return ResolutionResult(info, result.currentApplicability, reducedCandidates)
} }
fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidate(qualifiedAccess: T, isUsedAsReceiver: Boolean): FirStatement { fun resolveVariableAccessAndSelectCandidate(
return resolveVariableAccessAndSelectCandidateImpl(qualifiedAccess, isUsedAsReceiver) { true } qualifiedAccess: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean,
callSite: FirElement,
): FirStatement {
return resolveVariableAccessAndSelectCandidateImpl(qualifiedAccess, isUsedAsReceiver, callSite) { true }
} }
fun resolveOnlyEnumOrQualifierAccessAndSelectCandidate( fun resolveOnlyEnumOrQualifierAccessAndSelectCandidate(
@@ -202,19 +207,20 @@ class FirCallResolver(
} }
} }
private fun <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidateImpl( private fun resolveVariableAccessAndSelectCandidateImpl(
qualifiedAccess: T, qualifiedAccess: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean, isUsedAsReceiver: Boolean,
acceptCandidates: (Collection<Candidate>) -> Boolean callSite: FirElement = qualifiedAccess,
acceptCandidates: (Collection<Candidate>) -> Boolean,
): FirStatement { ): FirStatement {
val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val qualifiedAccess = transformer.transformExplicitReceiver(qualifiedAccess) val qualifiedAccess = qualifiedAccess.let(transformer::transformExplicitReceiver)
val nonFatalDiagnosticFromExpression = (qualifiedAccess as? FirPropertyAccessExpression)?.nonFatalDiagnostics val nonFatalDiagnosticFromExpression = (qualifiedAccess as? FirPropertyAccessExpression)?.nonFatalDiagnostics
val basicResult by lazy(LazyThreadSafetyMode.NONE) { val basicResult by lazy(LazyThreadSafetyMode.NONE) {
collectCandidates(qualifiedAccess, callee.name) collectCandidates(qualifiedAccess, callee.name, callSite = callSite)
} }
// Even if it's not receiver, it makes sense to continue qualifier if resolution is unsuccessful // Even if it's not receiver, it makes sense to continue qualifier if resolution is unsuccessful
@@ -327,7 +333,7 @@ class FirCallResolver(
replaceContextReceiverArguments(candidate.contextReceiverArguments()) replaceContextReceiverArguments(candidate.contextReceiverArguments())
} }
} }
if (qualifiedAccess is FirExpression) transformer.storeTypeFromCallee(qualifiedAccess) transformer.storeTypeFromCallee(qualifiedAccess, isLhsOfAssignment = callSite is FirVariableAssignment)
return qualifiedAccess return qualifiedAccess
} }
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.fir.resolve package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ResolutionMode.Companion.prettyString
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
@@ -86,6 +86,10 @@ sealed class ResolutionMode {
} }
} }
class AssignmentLValue(val variableAssignment: FirVariableAssignment) : ResolutionMode() {
override fun toString(): String = "AssignmentLValue: ${variableAssignment.render()}"
}
private companion object { private companion object {
private fun FirTypeRef?.prettyString(): String { private fun FirTypeRef?.prettyString(): String {
if (this == null) return "null" if (this == null) return "null"
@@ -98,6 +102,7 @@ sealed class ResolutionMode {
fun ResolutionMode.expectedType(components: BodyResolveComponents, allowFromCast: Boolean = false): FirTypeRef? = when (this) { fun ResolutionMode.expectedType(components: BodyResolveComponents, allowFromCast: Boolean = false): FirTypeRef? = when (this) {
is ResolutionMode.WithExpectedType -> expectedTypeRef is ResolutionMode.WithExpectedType -> expectedTypeRef
is ResolutionMode.ContextIndependent, is ResolutionMode.ContextIndependent,
is ResolutionMode.AssignmentLValue,
is ResolutionMode.ReceiverResolution -> components.noExpectedType is ResolutionMode.ReceiverResolution -> components.noExpectedType
is ResolutionMode.WithExpectedTypeFromCast -> expectedTypeRef.takeIf { allowFromCast } is ResolutionMode.WithExpectedTypeFromCast -> expectedTypeRef.takeIf { allowFromCast }
is ResolutionMode.WithSuggestedType -> suggestedTypeRef is ResolutionMode.WithSuggestedType -> suggestedTypeRef
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.calls.FirPropertyWithExplicitBackingFieldResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.calls.FirPropertyWithExplicitBackingFieldResolvedNamedReference
@@ -289,24 +286,29 @@ private fun FirPropertyWithExplicitBackingFieldResolvedNamedReference.getNarrowe
} }
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef { fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
return when (val newCallee = access.calleeReference) { val calleeReference = access.calleeReference
return typeFromCallee(access, calleeReference)
}
fun BodyResolveComponents.typeFromCallee(access: FirElement, calleeReference: FirReference): FirResolvedTypeRef {
return when (calleeReference) {
is FirErrorNamedReference -> is FirErrorNamedReference ->
buildErrorTypeRef { buildErrorTypeRef {
source = access.source?.fakeElement(KtFakeSourceElementKind.ErrorTypeRef) source = access.source?.fakeElement(KtFakeSourceElementKind.ErrorTypeRef)
diagnostic = ConeStubDiagnostic(newCallee.diagnostic) diagnostic = ConeStubDiagnostic(calleeReference.diagnostic)
} }
is FirNamedReferenceWithCandidate -> { is FirNamedReferenceWithCandidate -> {
typeFromSymbol(newCallee.candidateSymbol, false) typeFromSymbol(calleeReference.candidateSymbol, false)
} }
is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> { is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> {
val symbol = newCallee.getNarrowedDownSymbol(session) val symbol = calleeReference.getNarrowedDownSymbol(session)
typeFromSymbol(symbol, false) typeFromSymbol(symbol, false)
} }
is FirResolvedNamedReference -> { is FirResolvedNamedReference -> {
typeFromSymbol(newCallee.resolvedSymbol, false) typeFromSymbol(calleeReference.resolvedSymbol, false)
} }
is FirThisReference -> { is FirThisReference -> {
val labelName = newCallee.labelName val labelName = calleeReference.labelName
val implicitReceiver = implicitReceiverStack[labelName] val implicitReceiver = implicitReceiverStack[labelName]
buildResolvedTypeRef { buildResolvedTypeRef {
source = null source = null
@@ -319,19 +321,19 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
} }
} }
is FirSuperReference -> { is FirSuperReference -> {
val labelName = newCallee.labelName val labelName = calleeReference.labelName
val implicitReceiver = val implicitReceiver =
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
else implicitReceiverStack.lastDispatchReceiver() else implicitReceiverStack.lastDispatchReceiver()
val resolvedTypeRef = val resolvedTypeRef =
newCallee.superTypeRef as? FirResolvedTypeRef calleeReference.superTypeRef as? FirResolvedTypeRef
?: implicitReceiver?.boundSymbol?.fir?.superTypeRefs?.singleOrNull() as? FirResolvedTypeRef ?: implicitReceiver?.boundSymbol?.fir?.superTypeRefs?.singleOrNull() as? FirResolvedTypeRef
resolvedTypeRef ?: buildErrorTypeRef { resolvedTypeRef ?: buildErrorTypeRef {
source = newCallee.source source = calleeReference.source
diagnostic = ConeUnresolvedNameError(Name.identifier("super")) diagnostic = ConeUnresolvedNameError(Name.identifier("super"))
} }
} }
else -> error("Failed to extract type from: $newCallee") else -> error("Failed to extract type from: $calleeReference")
} }
} }
@@ -397,6 +399,7 @@ private fun FirSmartCastExpressionBuilder.applyResultTypeRef() {
else else
originalExpression.typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef) originalExpression.typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
} }
private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo( private fun <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo(
expression: T, expression: T,
stability: PropertyStability, stability: PropertyStability,
@@ -528,22 +531,15 @@ fun FirAnnotation.getCorrespondingClassSymbolOrNull(session: FirSession): FirReg
} }
} }
fun <T> BodyResolveComponents.initialTypeOfCandidate(
candidate: Candidate,
call: T
): ConeKotlinType where T : FirResolvable, T : FirStatement {
return initialTypeOfCandidate(candidate, typeFromCallee(call))
}
fun BodyResolveComponents.initialTypeOfCandidate(candidate: Candidate): ConeKotlinType { fun BodyResolveComponents.initialTypeOfCandidate(candidate: Candidate): ConeKotlinType {
val typeRef = typeFromSymbol(candidate.symbol, makeNullable = false) val typeRef = typeFromSymbol(candidate.symbol, makeNullable = false)
return initialTypeOfCandidate(candidate, typeRef) return typeRef.initialTypeOfCandidate(candidate)
} }
private fun initialTypeOfCandidate(candidate: Candidate, typeRef: FirResolvedTypeRef): ConeKotlinType { fun FirResolvedTypeRef.initialTypeOfCandidate(candidate: Candidate): ConeKotlinType {
val system = candidate.system val system = candidate.system
val resultingSubstitutor = system.buildCurrentSubstitutor() val resultingSubstitutor = system.buildCurrentSubstitutor()
return resultingSubstitutor.safeSubstitute(system, candidate.substitutor.substituteOrSelf(typeRef.type)) as ConeKotlinType return resultingSubstitutor.safeSubstitute(system, candidate.substitutor.substituteOrSelf(type)) as ConeKotlinType
} }
fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? = fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? =
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
fun BodyResolveComponents.findTypesForSuperCandidates( fun BodyResolveComponents.findTypesForSuperCandidates(
superTypeRefs: List<FirTypeRef>, superTypeRefs: List<FirTypeRef>,
containingCall: FirQualifiedAccess, containingCall: FirQualifiedAccessExpression,
): List<ConeKotlinType> { ): List<ConeKotlinType> {
val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type } val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type }
val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall) val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall)
@@ -794,9 +794,17 @@ abstract class FirDataFlowAnalyzer(
graphBuilder.exitStringConcatenationCall(call).mergeIncomingFlow() graphBuilder.exitStringConcatenationCall(call).mergeIncomingFlow()
} }
private fun FirQualifiedAccess.orderedArguments(callee: FirFunction): Array<out FirExpression?>? { private fun FirStatement.orderedArguments(callee: FirFunction): Array<out FirExpression?>? {
val receiver = extensionReceiver.takeIf { it != FirNoReceiverExpression } fun FirQualifiedAccessExpression.firstReceiver(): FirExpression? =
?: dispatchReceiver.takeIf { it != FirNoReceiverExpression } (extensionReceiver.takeIf { it != FirNoReceiverExpression }
?: dispatchReceiver.takeIf { it != FirNoReceiverExpression })
val receiver = when (this) {
is FirQualifiedAccessExpression -> firstReceiver()
is FirVariableAssignment -> (lValue as? FirQualifiedAccessExpression)?.firstReceiver()
else -> null
}
return when (this) { return when (this) {
is FirFunctionCall -> { is FirFunctionCall -> {
val argumentToParameter = resolvedArgumentMapping ?: return null val argumentToParameter = resolvedArgumentMapping ?: return null
@@ -811,11 +819,11 @@ abstract class FirDataFlowAnalyzer(
} }
} }
private fun processConditionalContract(flow: MutableFlow, qualifiedAccess: FirQualifiedAccess) { private fun processConditionalContract(flow: MutableFlow, qualifiedAccess: FirStatement) {
val callee = when (qualifiedAccess) { val callee = when (qualifiedAccess) {
is FirFunctionCall -> qualifiedAccess.toResolvedCallableSymbol()?.fir as? FirSimpleFunction is FirFunctionCall -> qualifiedAccess.toResolvedCallableSymbol()?.fir as? FirSimpleFunction
is FirQualifiedAccessExpression -> qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.fir?.getter is FirQualifiedAccessExpression -> qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.fir?.getter
is FirVariableAssignment -> qualifiedAccess.lValue.toResolvedPropertySymbol()?.fir?.setter is FirVariableAssignment -> qualifiedAccess.calleeReference?.toResolvedPropertySymbol()?.fir?.setter
else -> null else -> null
} ?: return } ?: return
@@ -837,7 +845,7 @@ abstract class FirDataFlowAnalyzer(
if (argumentVariables.all { it == null }) return if (argumentVariables.all { it == null }) return
val typeParameters = callee.typeParameters val typeParameters = callee.typeParameters
val substitutor = if (typeParameters.isNotEmpty()) { val substitutor = if (typeParameters.isNotEmpty() && qualifiedAccess is FirQualifiedAccessExpression) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val substitutionFromArguments = typeParameters.zip(qualifiedAccess.typeArguments).map { (typeParameterRef, typeArgument) -> val substitutionFromArguments = typeParameters.zip(qualifiedAccess.typeArguments).map { (typeParameterRef, typeArgument) ->
typeParameterRef.symbol to typeArgument.toConeTypeProjection().type typeParameterRef.symbol to typeArgument.toConeTypeProjection().type
@@ -870,15 +878,15 @@ abstract class FirDataFlowAnalyzer(
fun exitLocalVariableDeclaration(variable: FirProperty, hadExplicitType: Boolean) { fun exitLocalVariableDeclaration(variable: FirProperty, hadExplicitType: Boolean) {
graphBuilder.exitVariableDeclaration(variable).mergeIncomingFlow { flow -> graphBuilder.exitVariableDeclaration(variable).mergeIncomingFlow { flow ->
val initializer = variable.initializer ?: return@mergeIncomingFlow val initializer = variable.initializer ?: return@mergeIncomingFlow
exitVariableInitialization(flow, initializer, variable, assignment = null, hadExplicitType) exitVariableInitialization(flow, initializer, variable, assignmentLhs = null, hadExplicitType)
} }
} }
fun exitVariableAssignment(assignment: FirVariableAssignment) { fun exitVariableAssignment(assignment: FirVariableAssignment) {
graphBuilder.exitVariableAssignment(assignment).mergeIncomingFlow { flow -> graphBuilder.exitVariableAssignment(assignment).mergeIncomingFlow { flow ->
val property = assignment.lValue.toResolvedPropertySymbol()?.fir ?: return@mergeIncomingFlow val property = assignment.calleeReference?.toResolvedPropertySymbol()?.fir ?: return@mergeIncomingFlow
if (property.isLocal || property.isVal) { if (property.isLocal || property.isVal) {
exitVariableInitialization(flow, assignment.rValue, property, assignment, hasExplicitType = false) exitVariableInitialization(flow, assignment.rValue, property, assignment.lValue, hasExplicitType = false)
} else { } else {
// TODO: add unstable smartcast for non-local var // TODO: add unstable smartcast for non-local var
val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment) val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment)
@@ -894,16 +902,16 @@ abstract class FirDataFlowAnalyzer(
flow: MutableFlow, flow: MutableFlow,
initializer: FirExpression, initializer: FirExpression,
property: FirProperty, property: FirProperty,
assignment: FirVariableAssignment?, assignmentLhs: FirExpression?,
hasExplicitType: Boolean, hasExplicitType: Boolean,
) { ) {
val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias( val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias(
flow, flow,
property.symbol, property.symbol,
assignment ?: property, assignmentLhs ?: property,
if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR
) )
val isAssignment = assignment != null val isAssignment = assignmentLhs != null
if (isAssignment) { if (isAssignment) {
logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex()) logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex())
} }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.expressions.explicitReceiver
import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -380,7 +381,7 @@ internal class FirLocalVariableAssignmentAnalyzer {
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MiniCfgData) { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MiniCfgData) {
visitElement(variableAssignment, data) visitElement(variableAssignment, data)
if (variableAssignment.explicitReceiver != null) return if (variableAssignment.explicitReceiver != null) return
data.recordAssignment(variableAssignment.lValue) variableAssignment.calleeReference?.let { data.recordAssignment(it) }
} }
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: MiniCfgData) { override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: MiniCfgData) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.expressions.explicitReceiver
import org.jetbrains.kotlin.fir.util.SetMultimap import org.jetbrains.kotlin.fir.util.SetMultimap
import org.jetbrains.kotlin.fir.util.setMultimapOf import org.jetbrains.kotlin.fir.util.setMultimapOf
import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.fir.visitors.FirVisitor
@@ -48,7 +49,7 @@ class PreliminaryLoopVisitor {
// property assignment, the smart cast will be unstable anyway. // property assignment, the smart cast will be unstable anyway.
if (variableAssignment.explicitReceiver != null) return if (variableAssignment.explicitReceiver != null) return
val reference = variableAssignment.lValue as? FirNamedReference val reference = variableAssignment.calleeReference as? FirNamedReference
if (reference != null) { if (reference != null) {
requireNotNull(data) requireNotNull(data)
reassignedVariablesPerElement.put(data, reference.name) reassignedVariablesPerElement.put(data, reference.name)
@@ -503,7 +503,7 @@ fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, proc
} }
is FirVariableAssignment -> { is FirVariableAssignment -> {
processCandidateIfApplicable(processor, processBlocks) (lValue as? FirResolvable)?.processCandidateIfApplicable(processor, processBlocks)
rValue.processAllContainingCallCandidates(processBlocks, processor) rValue.processAllContainingCallCandidates(processBlocks, processor)
} }
@@ -81,7 +81,8 @@ class FirCallCompleter(
) )
private fun <T> completeCall( private fun <T> completeCall(
call: T, expectedTypeRef: FirTypeRef?, call: T,
expectedTypeRef: FirTypeRef?,
mayBeCoercionToUnitApplied: Boolean, mayBeCoercionToUnitApplied: Boolean,
expectedTypeMismatchIsReportedInChecker: Boolean, expectedTypeMismatchIsReportedInChecker: Boolean,
isFromCast: Boolean, isFromCast: Boolean,
@@ -90,14 +91,10 @@ class FirCallCompleter(
where T : FirResolvable, T : FirStatement { where T : FirResolvable, T : FirStatement {
val typeRef = components.typeFromCallee(call) val typeRef = components.typeFromCallee(call)
if (call is FirVariableAssignment) {
call.replaceLValueTypeRef(typeRef)
}
val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true) val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true)
val candidate = reference.candidate val candidate = reference.candidate
val initialType = components.initialTypeOfCandidate(candidate, call) val initialType = typeRef.initialTypeOfCandidate(candidate)
if (call is FirExpression) { if (call is FirExpression) {
val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(initialType) val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(initialType)
@@ -83,7 +83,7 @@ class FirCallCompletionResultsWriterTransformer(
} }
} }
private fun <T : FirQualifiedAccess> prepareQualifiedTransform( private fun <T : FirQualifiedAccessExpression> prepareQualifiedTransform(
qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate
): T { ): T {
val subCandidate = calleeReference.candidate val subCandidate = calleeReference.candidate
@@ -129,7 +129,7 @@ class FirCallCompletionResultsWriterTransformer(
extensionReceiver = extensionReceiver.transformSingle(integerOperatorApproximator, expectedExtensionReceiverType) extensionReceiver = extensionReceiver.transformSingle(integerOperatorApproximator, expectedExtensionReceiverType)
} }
qualifiedAccessExpression.apply { (qualifiedAccessExpression as? FirQualifiedAccessExpression)?.apply {
replaceCalleeReference(calleeReference.toResolvedReference()) replaceCalleeReference(calleeReference.toResolvedReference())
replaceDispatchReceiver(dispatchReceiver) replaceDispatchReceiver(dispatchReceiver)
replaceExtensionReceiver(extensionReceiver) replaceExtensionReceiver(extensionReceiver)
@@ -146,11 +146,7 @@ class FirCallCompletionResultsWriterTransformer(
qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics) qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics)
} }
if (qualifiedAccessExpression is FirQualifiedAccessExpression) { qualifiedAccessExpression.replaceTypeRef(typeRef)
qualifiedAccessExpression.replaceTypeRef(typeRef)
} else if (qualifiedAccessExpression is FirVariableAssignment) {
qualifiedAccessExpression.replaceLValueTypeRef(typeRef)
}
if (declaration !is FirErrorFunction) { if (declaration !is FirErrorFunction) {
qualifiedAccessExpression.replaceTypeArguments(typeArguments) qualifiedAccessExpression.replaceTypeArguments(typeArguments)
@@ -405,25 +401,6 @@ class FirCallCompletionResultsWriterTransformer(
} }
} }
override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment,
data: ExpectedArgumentType?,
): FirStatement {
val calleeReference = variableAssignment.calleeReference as? FirNamedReferenceWithCandidate ?: return variableAssignment
// Initialize lValueTypeRef
val qualifiedTransform = prepareQualifiedTransform(variableAssignment, calleeReference)
val lValueTypeRef = qualifiedTransform.lValueTypeRef as FirResolvedTypeRef
val resultLValueType = lValueTypeRef.substituteTypeRef(calleeReference.candidate)
resultLValueType.ensureResolvedTypeDeclaration(session)
variableAssignment.replaceLValueTypeRef(resultLValueType)
session.lookupTracker?.recordTypeResolveAsLookup(resultLValueType, variableAssignment.lValue.source, context.file.source)
return variableAssignment.apply {
replaceCalleeReference(calleeReference.toResolvedReference())
}
}
override fun transformSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: ExpectedArgumentType?): FirStatement { override fun transformSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: ExpectedArgumentType?): FirStatement {
return smartCastExpression.transformOriginalExpression(this, data) return smartCastExpression.transformOriginalExpression(this, data)
} }
@@ -509,7 +486,7 @@ class FirCallCompletionResultsWriterTransformer(
} }
private fun computeTypeArguments( private fun computeTypeArguments(
access: FirQualifiedAccess, access: FirQualifiedAccessExpression,
candidate: Candidate candidate: Candidate
): List<FirTypeProjection> { ): List<FirTypeProjection> {
val typeArguments = computeTypeArgumentTypes(candidate) val typeArguments = computeTypeArgumentTypes(candidate)
@@ -181,6 +181,13 @@ abstract class FirAbstractBodyResolveTransformerDispatcher(
return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data) return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data)
} }
override fun transformDesugaredAssignmentValueReferenceExpression(
desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression, data)
}
override fun transformVariableAssignment( override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment, variableAssignment: FirVariableAssignment,
data: ResolutionMode data: ResolutionMode
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctiona
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolver
import org.jetbrains.kotlin.fir.resolve.transformers.toExpectedType
import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType import org.jetbrains.kotlin.fir.resolve.transformers.transformVarargTypeToArrayType
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.types.constructStarProjectedType import org.jetbrains.kotlin.fir.types.constructStarProjectedType
@@ -317,7 +316,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
.transformSingle(components.integerLiteralAndOperatorApproximationTransformer, null) .transformSingle(components.integerLiteralAndOperatorApproximationTransformer, null)
// Second, replace result type of delegate expression with stub type if delegate not yet resolved // Second, replace result type of delegate expression with stub type if delegate not yet resolved
if (delegateExpression is FirQualifiedAccess) { if (delegateExpression is FirQualifiedAccessExpression) {
val calleeReference = delegateExpression.calleeReference val calleeReference = delegateExpression.calleeReference
if (calleeReference is FirNamedReferenceWithCandidate) { if (calleeReference is FirNamedReferenceWithCandidate) {
val system = calleeReference.candidate.system val system = calleeReference.candidate.system
@@ -736,7 +735,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
transformAnonymousFunctionWithExpectedType(anonymousFunction, data.expectedTypeRef, data) transformAnonymousFunctionWithExpectedType(anonymousFunction, data.expectedTypeRef, data)
is ResolutionMode.WithSuggestedType -> is ResolutionMode.WithSuggestedType ->
transformAnonymousFunctionWithExpectedType(anonymousFunction, data.suggestedTypeRef, data) transformAnonymousFunctionWithExpectedType(anonymousFunction, data.suggestedTypeRef, data)
is ResolutionMode.ContextIndependent, is ResolutionMode.ReceiverResolution -> is ResolutionMode.ContextIndependent, is ResolutionMode.AssignmentLValue, is ResolutionMode.ReceiverResolution ->
transformAnonymousFunctionWithExpectedType(anonymousFunction, buildImplicitTypeRef(), data) transformAnonymousFunctionWithExpectedType(anonymousFunction, buildImplicitTypeRef(), data)
is ResolutionMode.WithStatus, is ResolutionMode.WithExpectedTypeFromCast -> is ResolutionMode.WithStatus, is ResolutionMode.WithExpectedTypeFromCast ->
throw AssertionError("Should not be here in WithStatus/WithExpectedTypeFromCast mode") throw AssertionError("Should not be here in WithStatus/WithExpectedTypeFromCast mode")
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
@@ -133,7 +132,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
transformSuperReceiver( transformSuperReceiver(
callee, callee,
qualifiedAccessExpression, qualifiedAccessExpression,
containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.selector as? FirQualifiedAccess containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.selector as? FirQualifiedAccessExpression
) )
} }
is FirDelegateFieldReference -> { is FirDelegateFieldReference -> {
@@ -144,12 +143,19 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
is FirResolvedNamedReference, is FirResolvedNamedReference,
is FirErrorNamedReference -> { is FirErrorNamedReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) { if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
storeTypeFromCallee(qualifiedAccessExpression) storeTypeFromCallee(qualifiedAccessExpression, isLhsOfAssignment = false)
} }
qualifiedAccessExpression qualifiedAccessExpression
} }
else -> { else -> {
val transformedCallee = resolveQualifiedAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver) val transformedCallee = resolveQualifiedAccessAndSelectCandidate(
qualifiedAccessExpression,
isUsedAsReceiver,
when (data) {
is ResolutionMode.AssignmentLValue -> data.variableAssignment
else -> qualifiedAccessExpression
}
)
// NB: here we can get raw expression because of dropped qualifiers (see transform callee), // NB: here we can get raw expression because of dropped qualifiers (see transform callee),
// so candidate existence must be checked before calling completion // so candidate existence must be checked before calling completion
if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) { if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) {
@@ -162,22 +168,24 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
} }
} }
} }
when (result) { if (data !is ResolutionMode.AssignmentLValue) {
is FirQualifiedAccessExpression -> { when (result) {
dataFlowAnalyzer.exitQualifiedAccessExpression(result) is FirQualifiedAccessExpression -> {
result = components.transformQualifiedAccessUsingSmartcastInfo(result) dataFlowAnalyzer.exitQualifiedAccessExpression(result)
if (result is FirSmartCastExpression) { result = components.transformQualifiedAccessUsingSmartcastInfo(result)
dataFlowAnalyzer.exitSmartCastExpression(result) if (result is FirSmartCastExpression) {
dataFlowAnalyzer.exitSmartCastExpression(result)
}
}
is FirResolvedQualifier -> {
dataFlowAnalyzer.exitResolvedQualifierNode(result)
} }
}
is FirResolvedQualifier -> {
dataFlowAnalyzer.exitResolvedQualifierNode(result)
} }
} }
return result return result
} }
fun <Q : FirQualifiedAccess> transformExplicitReceiver(qualifiedAccessExpression: Q): Q { fun <Q : FirQualifiedAccessExpression> transformExplicitReceiver(qualifiedAccessExpression: Q): Q {
val explicitReceiver = qualifiedAccessExpression.explicitReceiver as? FirQualifiedAccessExpression val explicitReceiver = qualifiedAccessExpression.explicitReceiver as? FirQualifiedAccessExpression
if (explicitReceiver is FirQualifiedAccessExpression) { if (explicitReceiver is FirQualifiedAccessExpression) {
val superReference = explicitReceiver.calleeReference as? FirSuperReference val superReference = explicitReceiver.calleeReference as? FirSuperReference
@@ -208,14 +216,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
protected open fun resolveQualifiedAccessAndSelectCandidate( protected open fun resolveQualifiedAccessAndSelectCandidate(
qualifiedAccessExpression: FirQualifiedAccessExpression, qualifiedAccessExpression: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean, isUsedAsReceiver: Boolean,
callSite: FirElement,
): FirStatement { ): FirStatement {
return callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver) return callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver, callSite)
} }
fun transformSuperReceiver( fun transformSuperReceiver(
superReference: FirSuperReference, superReference: FirSuperReference,
superReferenceContainer: FirQualifiedAccessExpression, superReferenceContainer: FirQualifiedAccessExpression,
containingCall: FirQualifiedAccess? containingCall: FirQualifiedAccessExpression?
): FirQualifiedAccessExpression { ): FirQualifiedAccessExpression {
val labelName = superReference.labelName val labelName = superReference.labelName
val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver() val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver()
@@ -385,7 +394,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
(calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) && (calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) &&
functionCall.resultType is FirImplicitTypeRef functionCall.resultType is FirImplicitTypeRef
) { ) {
storeTypeFromCallee(functionCall) storeTypeFromCallee(functionCall, isLhsOfAssignment = false)
} }
if (calleeReference is FirNamedReferenceWithCandidate) return functionCall if (calleeReference is FirNamedReferenceWithCandidate) return functionCall
if (calleeReference !is FirSimpleNamedReference) { if (calleeReference !is FirSimpleNamedReference) {
@@ -413,7 +422,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
} }
val resultExpression = callResolver.resolveCallAndSelectCandidate(withTransformedArguments) val resultExpression = callResolver.resolveCallAndSelectCandidate(withTransformedArguments)
val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression() val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression()
if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) { if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccessExpression) {
// name.invoke() case // name.invoke() case
callCompleter.completeCall(resultExplicitReceiver, noExpectedType) callCompleter.completeCall(resultExplicitReceiver, noExpectedType)
} }
@@ -549,6 +558,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
} }
} }
@OptIn(FirContractViolation::class)
override fun transformAssignmentOperatorStatement( override fun transformAssignmentOperatorStatement(
assignmentOperatorStatement: FirAssignmentOperatorStatement, assignmentOperatorStatement: FirAssignmentOperatorStatement,
data: ResolutionMode data: ResolutionMode
@@ -612,32 +622,18 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
expectedTypeMismatchIsReportedInChecker = true expectedTypeMismatchIsReportedInChecker = true
) )
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
val unwrappedLeftArgument = leftArgument.unwrapSmartcastExpression()
val assignmentLeftArgument = buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(unwrappedLeftArgument) }
source = leftArgument.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment)
}.also { storeTypeFromCallee(it) }
val assignment = val assignment =
buildVariableAssignment { buildVariableAssignment {
source = assignmentOperatorStatement.source source = assignmentOperatorStatement.source
lValue = assignmentLeftArgument
rValue = resolvedOperatorCall rValue = resolvedOperatorCall
calleeReference = when {
lhsIsVar -> lhsReference!!
else -> buildErrorNamedReference {
source = when (leftArgument) {
is FirFunctionCall -> leftArgument.source
is FirQualifiedAccess ->
leftArgument.calleeReference.source
else -> leftArgument.source
}
diagnostic = when {
// Use a stub diagnostic to suppress unresolved error here because it would be reported by other logic
lhsReference is FirErrorNamedReference -> ConeStubDiagnostic(ConeUnresolvedReferenceError(lhsReference.name))
lhsSymbol == null -> ConeVariableExpectedError
else -> ConeValReassignmentError(lhsSymbol)
}
}
}
(leftArgument.unwrapSmartcastExpression() as? FirQualifiedAccess)?.let {
dispatchReceiver = it.dispatchReceiver
extensionReceiver = it.extensionReceiver
contextReceiverArguments.addAll(it.contextReceiverArguments)
}
annotations += assignmentOperatorStatement.annotations annotations += assignmentOperatorStatement.annotations
} }
return assignment.transform(transformer, ResolutionMode.ContextIndependent) return assignment.transform(transformer, ResolutionMode.ContextIndependent)
@@ -863,49 +859,66 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
.also { it.resultType = booleanType } .also { it.resultType = booleanType }
} }
override fun transformDesugaredAssignmentValueReferenceExpression(
desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression,
data: ResolutionMode
): FirStatement {
storeTypeFromCallee(desugaredAssignmentValueReferenceExpression)
return desugaredAssignmentValueReferenceExpression
}
override fun transformVariableAssignment( override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment, variableAssignment: FirVariableAssignment,
data: ResolutionMode, data: ResolutionMode,
): FirStatement = whileAnalysing(session, variableAssignment) { ): FirStatement = whileAnalysing(session, variableAssignment) {
// val resolvedAssignment = transformCallee(variableAssignment)
variableAssignment.transformAnnotations(transformer, ResolutionMode.ContextIndependent) variableAssignment.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment, isUsedAsReceiver = false)
val result = if (resolvedAssignment is FirVariableAssignment) {
val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType).result // TODO: check
val resolvedReference = completeAssignment.calleeReference
if (assignAltererExtensions != null && resolvedReference is FirResolvedNamedReference) {
val alteredAssignments = assignAltererExtensions.mapNotNull { alterer ->
alterer.transformVariableAssignment(variableAssignment)?.let { it to alterer }
}
when (alteredAssignments.size) {
0 -> {}
1 -> {
val transformedAssignment = alteredAssignments.first().first
return transformedAssignment.transform(transformer, ResolutionMode.ContextIndependent)
}
else -> { val isDesugaredIncrementDecrement = variableAssignment.source?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement
val altererNames = alteredAssignments.map { it.second::class.qualifiedName }
val errorReference = buildResolvedErrorReference { // Expressions like `++a` are desugared into `a = a.inc()` where the LHS is a FirDesugaredAssignmentValueReferenceExpression
source = resolvedReference.source // that's pointing to the not yet resolved `a` on the RHS. For the resolution to work, the RHS must therefore be resolved first.
name = resolvedReference.name if (isDesugaredIncrementDecrement) {
resolvedSymbol = resolvedReference.resolvedSymbol variableAssignment.transformRValue(transformer, ResolutionMode.ContextIndependent)
diagnostic = ConeAmbiguousAlteredAssign(altererNames) }
}
completeAssignment.replaceCalleeReference(errorReference) variableAssignment.transformLValue(transformer, ResolutionMode.AssignmentLValue(variableAssignment))
val resolvedReference = variableAssignment.calleeReference
if (assignAltererExtensions != null && resolvedReference is FirResolvedNamedReference) {
val alteredAssignments = assignAltererExtensions.mapNotNull { alterer ->
alterer.transformVariableAssignment(variableAssignment)?.let { it to alterer }
}
when (alteredAssignments.size) {
0 -> {}
1 -> {
val transformedAssignment = alteredAssignments.first().first
return transformedAssignment.transform(transformer, ResolutionMode.ContextIndependent)
}
else -> {
val extensionNames = alteredAssignments.map { it.second::class.qualifiedName }
val errorLValue = buildErrorExpression {
expression = variableAssignment.lValue
source = variableAssignment.lValue.source?.fakeElement(KtFakeSourceElementKind.AssignmentLValueError)
diagnostic = ConeAmbiguousAlteredAssign(extensionNames)
} }
variableAssignment.replaceLValue(errorLValue)
} }
} }
}
completeAssignment.transformRValue( val result = if (!isDesugaredIncrementDecrement) {
variableAssignment.transformRValue(
transformer, transformer,
withExpectedType(variableAssignment.lValueTypeRef, expectedTypeMismatchIsReportedInChecker = true), withExpectedType(variableAssignment.lValue.typeRef, expectedTypeMismatchIsReportedInChecker = true),
) )
} else { } else {
// This can happen in erroneous code only variableAssignment
resolvedAssignment
} }
(result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) } (result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) }
return result return result
} }
@@ -1517,12 +1530,34 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
internal fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { internal fun storeTypeFromCallee(access: FirQualifiedAccessExpression, isLhsOfAssignment: Boolean) {
val typeFromCallee = components.typeFromCallee(access) val typeFromCallee = components.typeFromCallee(access)
access.resultType = typeFromCallee.withReplacedConeType( access.resultType = typeFromCallee.withReplacedConeType(
session.typeApproximator.approximateToSuperType( if (isLhsOfAssignment) {
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference session.typeApproximator.approximateToSubType(
) typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
} else {
session.typeApproximator.approximateToSuperType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
}
) )
} }
private fun storeTypeFromCallee(expression: FirDesugaredAssignmentValueReferenceExpression) {
val referencedExpression = expression.expressionRef.value
if (referencedExpression is FirQualifiedAccessExpression) {
val typeFromCallee = components.typeFromCallee(referencedExpression)
expression.resultType = typeFromCallee.withReplacedConeType(
session.typeApproximator.approximateToSubType(
typeFromCallee.type,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)
)
} else {
expression.resultType = referencedExpression.resultType.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
}
}
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers.plugin package org.jetbrains.kotlin.fir.resolve.transformers.plugin
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
@@ -168,6 +169,7 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations(
override fun resolveQualifiedAccessAndSelectCandidate( override fun resolveQualifiedAccessAndSelectCandidate(
qualifiedAccessExpression: FirQualifiedAccessExpression, qualifiedAccessExpression: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean, isUsedAsReceiver: Boolean,
callSite: FirElement,
): FirStatement { ): FirStatement {
return callResolver.resolveOnlyEnumOrQualifierAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver) return callResolver.resolveOnlyEnumOrQualifierAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver)
} }
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.fir.expressions.explicitReceiver
@OptIn(DfaInternals::class) @OptIn(DfaInternals::class)
class VariableStorageImpl(private val session: FirSession) : VariableStorage() { class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
@@ -92,7 +93,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
} }
private fun getIdentifierBySymbol(flow: Flow, symbol: FirBasedSymbol<*>, fir: FirElement): Identifier { private fun getIdentifierBySymbol(flow: Flow, symbol: FirBasedSymbol<*>, fir: FirElement): Identifier {
val expression = fir as? FirQualifiedAccess val expression = fir as? FirQualifiedAccessExpression ?: (fir as? FirVariableAssignment)?.lValue as? FirQualifiedAccessExpression
// TODO: don't create receiver variables if not going to create the composed variable either? // TODO: don't create receiver variables if not going to create the composed variable either?
return Identifier( return Identifier(
symbol, symbol,
@@ -104,10 +105,10 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
private fun createReal(flow: Flow, identifier: Identifier, originalFir: FirElement, stability: PropertyStability): RealVariable { private fun createReal(flow: Flow, identifier: Identifier, originalFir: FirElement, stability: PropertyStability): RealVariable {
val receiver: FirExpression? val receiver: FirExpression?
val isThisReference: Boolean val isThisReference: Boolean
val expression: FirQualifiedAccess? = when (originalFir) { val expression: FirQualifiedAccessExpression? = when (originalFir) {
is FirQualifiedAccessExpression -> originalFir is FirQualifiedAccessExpression -> originalFir
is FirWhenSubjectExpression -> originalFir.whenRef.value.subject as? FirQualifiedAccessExpression is FirWhenSubjectExpression -> originalFir.whenRef.value.subject as? FirQualifiedAccessExpression
is FirVariableAssignment -> originalFir is FirVariableAssignment -> originalFir.unwrapLValue()
else -> null else -> null
} }
@@ -162,7 +163,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
property.receiverParameter != null -> PropertyStability.PROPERTY_WITH_GETTER property.receiverParameter != null -> PropertyStability.PROPERTY_WITH_GETTER
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER
property.modality != Modality.FINAL -> { property.modality != Modality.FINAL -> {
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return null val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccessExpression)?.dispatchReceiver ?: return null
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
when (val receiverFir = receiverSymbol.fir) { when (val receiverFir = receiverSymbol.fir) {
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.dfa.cfg package org.jetbrains.kotlin.fir.resolve.dfa.cfg
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderer.FirCallNoArgumentsRenderer import org.jetbrains.kotlin.fir.renderer.FirCallNoArgumentsRenderer
@@ -55,7 +53,7 @@ fun CFGNode<*>.render(): String =
CfgRenderer.renderAsCallableDeclarationString(fir) CfgRenderer.renderAsCallableDeclarationString(fir)
}" }"
is VariableAssignmentNode -> "Assignment: ${CfgRenderer.renderElementAsString(fir.lValue)}" is VariableAssignmentNode -> "Assignment: ${fir.calleeReference?.let(CfgRenderer::renderElementAsString)}"
is FunctionCallNode -> "Function call: ${CfgRenderer.renderElementAsString(fir)}" is FunctionCallNode -> "Function call: ${CfgRenderer.renderElementAsString(fir)}"
is DelegatedConstructorCallNode -> "Delegated constructor call: ${CfgRenderer.renderElementAsString(fir)}" is DelegatedConstructorCallNode -> "Delegated constructor call: ${CfgRenderer.renderElementAsString(fir)}"
is StringConcatenationCallNode -> "String concatenation call: ${CfgRenderer.renderElementAsString(fir)}" is StringConcatenationCallNode -> "String concatenation call: ${CfgRenderer.renderElementAsString(fir)}"
@@ -40,10 +40,12 @@ val FirExpression.coneType: ConeKotlinType
val FirElement.symbol: FirBasedSymbol<*>? val FirElement.symbol: FirBasedSymbol<*>?
get() = when (this) { get() = when (this) {
is FirResolvable -> symbol is FirResolvable -> symbol
is FirVariableAssignment -> unwrapLValue()?.symbol
is FirDeclaration -> symbol is FirDeclaration -> symbol
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
is FirSafeCallExpression -> selector.symbol is FirSafeCallExpression -> selector.symbol
is FirSmartCastExpression -> originalExpression.symbol is FirSmartCastExpression -> originalExpression.symbol
is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.symbol
else -> null else -> null
}?.takeIf { }?.takeIf {
(this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression || (this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression ||
@@ -138,10 +138,6 @@ object ConeVariableExpectedError : ConeDiagnostic {
override val reason: String get() = "Variable expected" override val reason: String get() = "Variable expected"
} }
class ConeValReassignmentError(val variable: FirVariableSymbol<*>) : ConeDiagnostic {
override val reason: String get() = "Re-assigning a val variable"
}
class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic
class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic { class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic {
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() { abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
@@ -28,6 +27,7 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() {
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract override val calleeReference: FirNamedReference abstract override val calleeReference: FirNamedReference
abstract val hasQuestionMarkAtLHS: Boolean abstract val hasQuestionMarkAtLHS: Boolean
@@ -37,9 +37,6 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformCallableReferenceAccess(this, data) as E transformer.transformCallableReferenceAccess(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -54,6 +51,9 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference)
abstract override fun replaceCalleeReference(newCalleeReference: FirReference) abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
@@ -20,13 +20,13 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirComponentCall : FirFunctionCall() { abstract class FirComponentCall : FirFunctionCall() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection> abstract override val typeArguments: List<FirTypeProjection>
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract override val argumentList: FirArgumentList abstract override val argumentList: FirArgumentList
abstract override val calleeReference: FirNamedReference abstract override val calleeReference: FirNamedReference
abstract override val origin: FirFunctionCallOrigin abstract override val origin: FirFunctionCallOrigin
@@ -39,9 +39,6 @@ abstract class FirComponentCall : FirFunctionCall() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformComponentCall(this, data) as E transformer.transformComponentCall(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -54,6 +51,9 @@ abstract class FirComponentCall : FirFunctionCall() {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceArgumentList(newArgumentList: FirArgumentList)
abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference)
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirDesugaredAssignmentValueReferenceExpression : FirExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract val expressionRef: FirExpressionRef<FirExpression>
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDesugaredAssignmentValueReferenceExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformDesugaredAssignmentValueReferenceExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirDesugaredAssignmentValueReferenceExpression
}
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall { abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
@@ -28,6 +27,7 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall {
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract override val argumentList: FirArgumentList abstract override val argumentList: FirArgumentList
abstract override val calleeReference: FirNamedReference abstract override val calleeReference: FirNamedReference
abstract val origin: FirFunctionCallOrigin abstract val origin: FirFunctionCallOrigin
@@ -38,9 +38,6 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformFunctionCall(this, data) as E transformer.transformFunctionCall(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -55,6 +52,9 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceArgumentList(newArgumentList: FirArgumentList)
abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference)
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirImplicitInvokeCall : FirFunctionCall() { abstract class FirImplicitInvokeCall : FirFunctionCall() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
@@ -28,6 +27,7 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() {
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract override val argumentList: FirArgumentList abstract override val argumentList: FirArgumentList
abstract override val calleeReference: FirNamedReference abstract override val calleeReference: FirNamedReference
abstract override val origin: FirFunctionCallOrigin abstract override val origin: FirFunctionCallOrigin
@@ -38,9 +38,6 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformImplicitInvokeCall(this, data) as E transformer.transformImplicitInvokeCall(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -55,6 +52,9 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceArgumentList(newArgumentList: FirArgumentList)
abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference)
@@ -20,12 +20,12 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() { abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection> abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val source: KtSourceElement?
abstract override val argumentList: FirArgumentList abstract override val argumentList: FirArgumentList
abstract override val calleeReference: FirNamedReference abstract override val calleeReference: FirNamedReference
abstract override val origin: FirFunctionCallOrigin abstract override val origin: FirFunctionCallOrigin
@@ -38,9 +38,6 @@ abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformIntegerLiteralOperatorCall(this, data) as E transformer.transformIntegerLiteralOperatorCall(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -51,6 +48,9 @@ abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() {
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceArgumentList(newArgumentList: FirArgumentList)
abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference)
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() { abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val calleeReference: FirReference abstract override val calleeReference: FirReference
@@ -29,6 +28,7 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() {
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract val nonFatalDiagnostics: List<ConeDiagnostic> abstract val nonFatalDiagnostics: List<ConeDiagnostic>
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitPropertyAccessExpression(this, data) override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitPropertyAccessExpression(this, data)
@@ -37,9 +37,6 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformPropertyAccessExpression(this, data) as E transformer.transformPropertyAccessExpression(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -56,6 +53,9 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract fun replaceNonFatalDiagnostics(newNonFatalDiagnostics: List<ConeDiagnostic>) abstract fun replaceNonFatalDiagnostics(newNonFatalDiagnostics: List<ConeDiagnostic>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirPropertyAccessExpression abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirPropertyAccessExpression
@@ -1,60 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
interface FirQualifiedAccess : FirResolvable, FirStatement, FirContextReceiverArgumentListOwner {
override val calleeReference: FirReference
override val annotations: List<FirAnnotation>
override val contextReceiverArguments: List<FirExpression>
val typeArguments: List<FirTypeProjection>
val explicitReceiver: FirExpression?
val dispatchReceiver: FirExpression
val extensionReceiver: FirExpression
override val source: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedAccess(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformQualifiedAccess(this, data) as E
override fun replaceCalleeReference(newCalleeReference: FirReference)
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>)
fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
fun replaceSource(newSource: KtSourceElement?)
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
}
@@ -18,16 +18,16 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
* DO NOT MODIFY IT MANUALLY * DO NOT MODIFY IT MANUALLY
*/ */
abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAccess { abstract class FirQualifiedAccessExpression : FirExpression(), FirResolvable, FirContextReceiverArgumentListOwner {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val calleeReference: FirReference abstract override val calleeReference: FirReference
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection> abstract val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression? abstract val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedAccessExpression(this, data) override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedAccessExpression(this, data)
@@ -35,9 +35,6 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformQualifiedAccessExpression(this, data) as E transformer.transformQualifiedAccessExpression(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -46,19 +43,22 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces
abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>) abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) abstract fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) abstract fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract override fun replaceDispatchReceiver(newDispatchReceiver: FirExpression) abstract fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract fun replaceSource(newSource: KtSourceElement?)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression abstract fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression abstract fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
} }
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/ */
abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() { abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation> abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression> abstract override val contextReceiverArguments: List<FirExpression>
@@ -28,6 +27,7 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() {
abstract override val explicitReceiver: FirExpression? abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
abstract override val calleeReference: FirThisReference abstract override val calleeReference: FirThisReference
abstract val isImplicit: Boolean abstract val isImplicit: Boolean
@@ -37,9 +37,6 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformThisReceiverExpression(this, data) as E transformer.transformThisReceiverExpression(this, data) as E
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
@@ -54,6 +51,9 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() {
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract fun replaceCalleeReference(newCalleeReference: FirThisReference) abstract fun replaceCalleeReference(newCalleeReference: FirThisReference)
abstract override fun replaceCalleeReference(newCalleeReference: FirReference) abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
@@ -8,28 +8,17 @@ package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirPureAbstractElement import org.jetbrains.kotlin.fir.FirPureAbstractElement
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
/* /*
* This file was generated automatically * This file was generated automatically
* DO NOT MODIFY IT MANUALLY * DO NOT MODIFY IT MANUALLY
*/ */
abstract class FirVariableAssignment : FirPureAbstractElement(), FirQualifiedAccess { abstract class FirVariableAssignment : FirPureAbstractElement(), FirStatement {
abstract override val calleeReference: FirReference
abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract override val source: KtSourceElement? abstract override val source: KtSourceElement?
abstract val lValue: FirReference abstract override val annotations: List<FirAnnotation>
abstract val lValueTypeRef: FirTypeRef abstract val lValue: FirExpression
abstract val rValue: FirExpression abstract val rValue: FirExpression
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitVariableAssignment(this, data) override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitVariableAssignment(this, data)
@@ -38,32 +27,13 @@ abstract class FirVariableAssignment : FirPureAbstractElement(), FirQualifiedAcc
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E = override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformVariableAssignment(this, data) as E transformer.transformVariableAssignment(this, data) as E
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>) abstract fun replaceLValue(newLValue: FirExpression)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract override fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract fun replaceLValueTypeRef(newLValueTypeRef: FirTypeRef)
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirVariableAssignment abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirVariableAssignment abstract fun <D> transformLValue(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract fun <D> transformRValue(transformer: FirTransformer<D>, data: D): FirVariableAssignment abstract fun <D> transformRValue(transformer: FirTransformer<D>, data: D): FirVariableAssignment
} }
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin
import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
interface FirAbstractFunctionCallBuilder : FirQualifiedAccessBuilder, FirCallBuilder { interface FirAbstractFunctionCallBuilder : FirQualifiedAccessExpressionBuilder, FirCallBuilder {
abstract override var typeRef: FirTypeRef
abstract override val annotations: MutableList<FirAnnotation> abstract override val annotations: MutableList<FirAnnotation>
abstract override val contextReceiverArguments: MutableList<FirExpression> abstract override val contextReceiverArguments: MutableList<FirExpression>
abstract override val typeArguments: MutableList<FirTypeProjection> abstract override val typeArguments: MutableList<FirTypeProjection>
@@ -36,7 +37,6 @@ interface FirAbstractFunctionCallBuilder : FirQualifiedAccessBuilder, FirCallBui
abstract override var extensionReceiver: FirExpression abstract override var extensionReceiver: FirExpression
abstract override var source: KtSourceElement? abstract override var source: KtSourceElement?
abstract override var argumentList: FirArgumentList abstract override var argumentList: FirArgumentList
abstract var typeRef: FirTypeRef
abstract var calleeReference: FirNamedReference abstract var calleeReference: FirNamedReference
abstract var origin: FirFunctionCallOrigin abstract var origin: FirFunctionCallOrigin
override fun build(): FirFunctionCall override fun build(): FirFunctionCall
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirCallableReferenceAccessImpl import org.jetbrains.kotlin.fir.expressions.impl.FirCallableReferenceAccessImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
@@ -33,8 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { class FirCallableReferenceAccessBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
@@ -42,12 +41,12 @@ class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotati
override var explicitReceiver: FirExpression? = null override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
lateinit var calleeReference: FirNamedReference lateinit var calleeReference: FirNamedReference
var hasQuestionMarkAtLHS: Boolean = false var hasQuestionMarkAtLHS: Boolean = false
override fun build(): FirCallableReferenceAccess { override fun build(): FirCallableReferenceAccess {
return FirCallableReferenceAccessImpl( return FirCallableReferenceAccessImpl(
source,
typeRef, typeRef,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
@@ -55,6 +54,7 @@ class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotati
explicitReceiver, explicitReceiver,
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
source,
calleeReference, calleeReference,
hasQuestionMarkAtLHS, hasQuestionMarkAtLHS,
) )
@@ -39,24 +39,24 @@ import org.jetbrains.kotlin.name.Name
@FirBuilderDsl @FirBuilderDsl
class FirComponentCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { class FirComponentCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
val typeArguments: MutableList<FirTypeProjection> = mutableListOf() val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
var dispatchReceiver: FirExpression = FirNoReceiverExpression var dispatchReceiver: FirExpression = FirNoReceiverExpression
var extensionReceiver: FirExpression = FirNoReceiverExpression var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
override var argumentList: FirArgumentList = FirEmptyArgumentList override var argumentList: FirArgumentList = FirEmptyArgumentList
lateinit var explicitReceiver: FirExpression lateinit var explicitReceiver: FirExpression
var componentIndex: Int by kotlin.properties.Delegates.notNull<Int>() var componentIndex: Int by kotlin.properties.Delegates.notNull<Int>()
override fun build(): FirComponentCall { override fun build(): FirComponentCall {
return FirComponentCallImpl( return FirComponentCallImpl(
source,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(),
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
source,
argumentList, argumentList,
explicitReceiver, explicitReceiver,
componentIndex, componentIndex,
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirDesugaredAssignmentValueReferenceExpressionImpl
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirDesugaredAssignmentValueReferenceExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var expressionRef: FirExpressionRef<FirExpression>
override fun build(): FirDesugaredAssignmentValueReferenceExpression {
return FirDesugaredAssignmentValueReferenceExpressionImpl(
source,
annotations.toMutableOrEmpty(),
expressionRef,
)
}
@Deprecated("Modification of 'typeRef' has no impact for FirDesugaredAssignmentValueReferenceExpressionBuilder", level = DeprecationLevel.HIDDEN)
override var typeRef: FirTypeRef
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildDesugaredAssignmentValueReferenceExpression(init: FirDesugaredAssignmentValueReferenceExpressionBuilder.() -> Unit): FirDesugaredAssignmentValueReferenceExpression {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirDesugaredAssignmentValueReferenceExpressionBuilder().apply(init).build()
}
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.visitors.*
@FirBuilderDsl @FirBuilderDsl
open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
@@ -45,6 +44,7 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio
override var explicitReceiver: FirExpression? = null override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
override var argumentList: FirArgumentList = FirEmptyArgumentList override var argumentList: FirArgumentList = FirEmptyArgumentList
override lateinit var calleeReference: FirNamedReference override lateinit var calleeReference: FirNamedReference
override var origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular override var origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular
@@ -52,7 +52,6 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio
@OptIn(FirImplementationDetail::class) @OptIn(FirImplementationDetail::class)
override fun build(): FirFunctionCall { override fun build(): FirFunctionCall {
return FirFunctionCallImpl( return FirFunctionCallImpl(
source,
typeRef, typeRef,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
@@ -60,6 +59,7 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio
explicitReceiver, explicitReceiver,
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
source,
argumentList, argumentList,
calleeReference, calleeReference,
origin, origin,
@@ -37,25 +37,25 @@ import org.jetbrains.kotlin.fir.visitors.*
@FirBuilderDsl @FirBuilderDsl
open class FirImplicitInvokeCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { open class FirImplicitInvokeCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf() override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
override var argumentList: FirArgumentList = FirEmptyArgumentList override var argumentList: FirArgumentList = FirEmptyArgumentList
override lateinit var calleeReference: FirNamedReference override lateinit var calleeReference: FirNamedReference
override fun build(): FirImplicitInvokeCall { override fun build(): FirImplicitInvokeCall {
return FirImplicitInvokeCallImpl( return FirImplicitInvokeCallImpl(
source,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(),
explicitReceiver, explicitReceiver,
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
source,
argumentList, argumentList,
calleeReference, calleeReference,
) )
@@ -36,12 +36,12 @@ import org.jetbrains.kotlin.fir.visitors.*
@FirBuilderDsl @FirBuilderDsl
open class FirIntegerLiteralOperatorCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { open class FirIntegerLiteralOperatorCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override lateinit var typeRef: FirTypeRef override lateinit var typeRef: FirTypeRef
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf() override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null override var explicitReceiver: FirExpression? = null
override var source: KtSourceElement? = null
override var argumentList: FirArgumentList = FirEmptyArgumentList override var argumentList: FirArgumentList = FirEmptyArgumentList
override lateinit var calleeReference: FirNamedReference override lateinit var calleeReference: FirNamedReference
override lateinit var origin: FirFunctionCallOrigin override lateinit var origin: FirFunctionCallOrigin
@@ -50,12 +50,12 @@ open class FirIntegerLiteralOperatorCallBuilder : FirAbstractFunctionCallBuilder
override fun build(): FirIntegerLiteralOperatorCall { override fun build(): FirIntegerLiteralOperatorCall {
return FirIntegerLiteralOperatorCallImpl( return FirIntegerLiteralOperatorCallImpl(
source,
typeRef, typeRef,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(),
explicitReceiver, explicitReceiver,
source,
argumentList, argumentList,
calleeReference, calleeReference,
origin, origin,
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirPropertyAccessExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirPropertyAccessExpressionImpl
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
@@ -33,8 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { class FirPropertyAccessExpressionBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var calleeReference: FirReference lateinit var calleeReference: FirReference
@@ -43,12 +42,12 @@ class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotat
override var explicitReceiver: FirExpression? = null override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
val nonFatalDiagnostics: MutableList<ConeDiagnostic> = mutableListOf() val nonFatalDiagnostics: MutableList<ConeDiagnostic> = mutableListOf()
@OptIn(FirImplementationDetail::class) @OptIn(FirImplementationDetail::class)
override fun build(): FirPropertyAccessExpression { override fun build(): FirPropertyAccessExpression {
return FirPropertyAccessExpressionImpl( return FirPropertyAccessExpressionImpl(
source,
typeRef, typeRef,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
calleeReference, calleeReference,
@@ -57,6 +56,7 @@ class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotat
explicitReceiver, explicitReceiver,
dispatchReceiver, dispatchReceiver,
extensionReceiver, extensionReceiver,
source,
nonFatalDiagnostics.toMutableOrEmpty(), nonFatalDiagnostics.toMutableOrEmpty(),
) )
} }
@@ -11,8 +11,9 @@ import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
/* /*
@@ -21,7 +22,8 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
interface FirQualifiedAccessBuilder { interface FirQualifiedAccessExpressionBuilder {
abstract var typeRef: FirTypeRef
abstract val annotations: MutableList<FirAnnotation> abstract val annotations: MutableList<FirAnnotation>
abstract val contextReceiverArguments: MutableList<FirExpression> abstract val contextReceiverArguments: MutableList<FirExpression>
abstract val typeArguments: MutableList<FirTypeProjection> abstract val typeArguments: MutableList<FirTypeProjection>
@@ -29,5 +31,5 @@ interface FirQualifiedAccessBuilder {
abstract var dispatchReceiver: FirExpression abstract var dispatchReceiver: FirExpression
abstract var extensionReceiver: FirExpression abstract var extensionReceiver: FirExpression
abstract var source: KtSourceElement? abstract var source: KtSourceElement?
fun build(): FirQualifiedAccess fun build(): FirQualifiedAccessExpression
} }
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
@@ -33,22 +33,22 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
class FirThisReceiverExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { class FirThisReceiverExpressionBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val annotations: MutableList<FirAnnotation> = mutableListOf() override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf() override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf() override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var source: KtSourceElement? = null
lateinit var calleeReference: FirThisReference lateinit var calleeReference: FirThisReference
var isImplicit: Boolean = false var isImplicit: Boolean = false
override fun build(): FirThisReceiverExpression { override fun build(): FirThisReceiverExpression {
return FirThisReceiverExpressionImpl( return FirThisReceiverExpressionImpl(
source,
typeRef, typeRef,
annotations.toMutableOrEmpty(), annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(),
source,
calleeReference, calleeReference,
isImplicit, isImplicit,
) )
@@ -9,20 +9,13 @@ package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.* import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirVariableAssignmentImpl import org.jetbrains.kotlin.fir.expressions.impl.FirVariableAssignmentImpl
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
/* /*
@@ -31,27 +24,17 @@ import org.jetbrains.kotlin.fir.visitors.*
*/ */
@FirBuilderDsl @FirBuilderDsl
class FirVariableAssignmentBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder { class FirVariableAssignmentBuilder : FirAnnotationContainerBuilder {
lateinit var calleeReference: FirReference
override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var lValue: FirExpression
lateinit var rValue: FirExpression lateinit var rValue: FirExpression
override fun build(): FirVariableAssignment { override fun build(): FirVariableAssignment {
return FirVariableAssignmentImpl( return FirVariableAssignmentImpl(
calleeReference,
annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(),
explicitReceiver,
dispatchReceiver,
extensionReceiver,
source, source,
annotations.toMutableOrEmpty(),
lValue,
rValue, rValue,
) )
} }

Some files were not shown because too many files have changed in this diff Show More