diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt index b33c2c73c18..45c3b7a1cbd 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.* import org.jetbrains.kotlin.fir.declarations.* 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.impl.* import org.jetbrains.kotlin.fir.types.ConeKotlinType @@ -306,7 +306,7 @@ internal object FirToKtConversionCreator { KtSymbol::class.createType(), importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration") ), - FirQualifiedAccess::class to HLFunctionCallConversion( + FirQualifiedAccessExpression::class to HLFunctionCallConversion( "{0}.source!!.psi as KtExpression", KtExpression::class.createType(), importsToAdd = listOf( diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirAnalysisSessionComponent.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirAnalysisSessionComponent.kt index 69c4f71758a..187eb43fd9a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirAnalysisSessionComponent.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirAnalysisSessionComponent.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics 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.resolve.substitution.ConeSubstitutor 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() } - fun FirQualifiedAccess.createSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): KtSubstitutor { + fun FirQualifiedAccessExpression.createSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): KtSubstitutor { return createConeSubstitutorFromTypeArguments(callableSymbol).toKtSubstitutor() } - fun FirQualifiedAccess.createConeSubstitutorFromTypeArguments(): ConeSubstitutor? { + fun FirQualifiedAccessExpression.createConeSubstitutorFromTypeArguments(): ConeSubstitutor? { val symbol = calleeReference.toResolvedCallableSymbol() ?: return null return createConeSubstitutorFromTypeArguments(symbol) } - fun FirQualifiedAccess.createConeSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): ConeSubstitutor { + fun FirQualifiedAccessExpression.createConeSubstitutorFromTypeArguments(callableSymbol: FirCallableSymbol<*>): ConeSubstitutor { val typeArgumentMap = buildMap { // 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 diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index 859d4255a43..f82b5a6cf50 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -124,9 +124,9 @@ internal class KtFirCallResolver( val containingBinaryExpressionForLhs = psi.getContainingBinaryExpressionForIncompleteLhs() val containingUnaryExpressionForIncOrDec = psi.getContainingUnaryIncOrDecExpression() val psiToResolve = containingCallExpressionForCalleeExpression - ?: psi.getContainingDotQualifiedExpressionForSelectorExpression() ?: containingBinaryExpressionForLhs ?: containingUnaryExpressionForIncOrDec + ?: psi.getContainingDotQualifiedExpressionForSelectorExpression() ?: psi val fir = psiToResolve.getOrBuildFir(analysisSession.firResolveSession) ?: return emptyList() if (fir is FirDiagnosticHolder) { @@ -189,7 +189,7 @@ internal class KtFirCallResolver( } } - fun transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder { + fun transformErrorReference(call: FirElement, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder { val diagnostic = calleeReference.diagnostic val ktDiagnostic = calleeReference.createKtDiagnostic(psi) @@ -199,16 +199,16 @@ internal class KtFirCallResolver( val candidateCalls = mutableListOf() if (diagnostic is ConeDiagnosticWithCandidates) { diagnostic.candidates.mapNotNullTo(candidateCalls) { - createKtCall(psi, call, it, resolveFragmentOfCall) + createKtCall(psi, call, calleeReference, it, resolveFragmentOfCall) } } else { - candidateCalls.addIfNotNull(createKtCall(psi, call, null, resolveFragmentOfCall)) + candidateCalls.addIfNotNull(createKtCall(psi, call, calleeReference, null, resolveFragmentOfCall)) } return KtErrorCallInfo(candidateCalls, ktDiagnostic, token) } return when (this) { - is FirResolvable -> { + is FirResolvable, is FirVariableAssignment -> { when (val calleeReference = calleeReference) { is FirResolvedErrorReference -> transformErrorReference(this, calleeReference) 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 // `FirPropertyAccessExpression` (which is `FirResolvable`). is FirCallableSymbol<*> -> { - val call = createKtCall(psi, this, null, resolveFragmentOfCall) + val call = createKtCall(psi, this, calleeReference, null, resolveFragmentOfCall) ?: errorWithFirSpecificEntries( "expect `createKtCall` to succeed for resolvable case with callable symbol", fir = this, @@ -307,7 +307,9 @@ internal class KtFirCallResolver( if (this !is KtExpression) return null val lhs = deparenthesize(this) val binaryExpression = parentOfType() ?: 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) if (firBinaryExpression is FirFunctionCall) { if (firBinaryExpression.origin == FirFunctionCallOrigin.Operator && @@ -349,9 +351,19 @@ internal class KtFirCallResolver( fir: FirResolvable, candidate: AbstractCandidate?, 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? { val targetSymbol = candidate?.symbol - ?: fir.calleeReference.toResolvedBaseSymbol() + ?: calleeReference.toResolvedBaseSymbol() ?: return null if (targetSymbol !is FirCallableSymbol<*>) 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 // candidate, `Candidate.substitutor` is not complete. maybe we can carry over the final substitutor if it's available from // body resolve phase? - val substitutor = - (fir as? FirQualifiedAccess)?.createSubstitutorFromTypeArguments(targetSymbol) ?: KtSubstitutor.Empty(token) + val substitutor = when (fir) { + is FirQualifiedAccessExpression -> fir.createSubstitutorFromTypeArguments(targetSymbol) + is FirVariableAssignment -> fir.unwrapLValue()?.createSubstitutorFromTypeArguments(targetSymbol) + else -> null + } ?: KtSubstitutor.Empty(token) fun createKtPartiallyAppliedSymbolForImplicitInvoke( dispatchReceiver: FirExpression, @@ -393,7 +408,8 @@ internal class KtFirCallResolver( val dispatchReceiverValue: KtReceiverValue? val extensionReceiverValue: KtReceiverValue? 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) { extensionReceiverValue = (fir as FirFunctionCall).arguments.first().toKtReceiverValue() } else { @@ -401,7 +417,8 @@ internal class KtFirCallResolver( } } else { dispatchReceiverValue = dispatchReceiver.toKtReceiverValue() - extensionReceiverValue = KtExplicitReceiverValue(explicitReceiverPsi, extensionReceiver.typeRef.coneType.asKtType(), false, token) + extensionReceiverValue = + KtExplicitReceiverValue(explicitReceiverPsi, extensionReceiver.typeRef.coneType.asKtType(), false, token) } return KtPartiallyAppliedSymbol( with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) }, @@ -412,7 +429,7 @@ internal class KtFirCallResolver( val partiallyAppliedSymbol = if (candidate != null) { 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`). createKtPartiallyAppliedSymbolForImplicitInvoke( @@ -427,21 +444,25 @@ internal class KtFirCallResolver( candidate.chosenExtensionReceiverValue?.receiverExpression?.toKtReceiverValue(), ) } - } else if (fir is FirQualifiedAccess) { - if (fir is FirImplicitInvokeCall) { - val explicitReceiverKind = if (fir.explicitReceiver == fir.dispatchReceiver) { - ExplicitReceiverKind.DISPATCH_RECEIVER - } else { - ExplicitReceiverKind.EXTENSION_RECEIVER - } - createKtPartiallyAppliedSymbolForImplicitInvoke(fir.dispatchReceiver, fir.extensionReceiver, explicitReceiverKind) + } else if (fir is FirImplicitInvokeCall) { + val explicitReceiverKind = if (fir.explicitReceiver == fir.dispatchReceiver) { + ExplicitReceiverKind.DISPATCH_RECEIVER } else { - KtPartiallyAppliedSymbol( - with(analysisSession) { unsubstitutedKtSignature.substitute(substitutor) }, - fir.dispatchReceiver.toKtReceiverValue(), - fir.extensionReceiver.toKtReceiverValue() - ) + ExplicitReceiverKind.EXTENSION_RECEIVER } + 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 { KtPartiallyAppliedSymbol(unsubstitutedKtSignature, _dispatchReceiver = null, _extensionReceiver = null) } @@ -470,7 +491,7 @@ internal class KtFirCallResolver( @Suppress("UNCHECKED_CAST") // safe because of the above check on targetKtSymbol KtSimpleVariableAccessCall( partiallyAppliedSymbol as KtPartiallyAppliedVariableSymbol, - fir.toTypeArgumentsMapping(partiallyAppliedSymbol), + fir.unwrapLValue()?.toTypeArgumentsMapping(partiallyAppliedSymbol) ?: emptyMap(), KtSimpleVariableAccess.Write(rhs) ) } @@ -519,12 +540,19 @@ internal class KtFirCallResolver( 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 } } - 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) { val rightOperandPsi = deparenthesize(psi.right) ?: return null val leftOperandPsi = deparenthesize(psi.left) ?: return null @@ -566,13 +594,13 @@ internal class KtFirCallResolver( return if (resolveFragmentOfCall) { KtSimpleVariableAccessCall( variablePartiallyAppliedSymbol, - fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), + fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(), KtSimpleVariableAccess.Read ) } else { KtCompoundVariableAccessCall( variablePartiallyAppliedSymbol, - fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), + fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(), KtCompoundAccess.CompoundAssign(operationPartiallyAppliedSymbol, compoundAssignKind, rightOperandPsi), ) } @@ -620,13 +648,13 @@ internal class KtFirCallResolver( return if (resolveFragmentOfCall) { KtSimpleVariableAccessCall( variablePartiallyAppliedSymbol, - fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), + fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(), KtSimpleVariableAccess.Read ) } else { KtCompoundVariableAccessCall( variablePartiallyAppliedSymbol, - fir.toTypeArgumentsMapping(variablePartiallyAppliedSymbol), + fir.unwrapLValue()?.toTypeArgumentsMapping(variablePartiallyAppliedSymbol) ?: emptyMap(), KtCompoundAccess.IncOrDecOperation(operationPartiallyAppliedSymbol, incOrDecOperationKind, incDecPrecedence), ) } @@ -707,10 +735,7 @@ internal class KtFirCallResolver( @OptIn(SymbolInternals::class) private fun getInitializerOfReferencedLocalVariable(variableReference: FirExpression): FirFunctionCall? { - val qualifiedAccess = variableReference as? FirQualifiedAccess - val resolvedNamedReference = qualifiedAccess?.calleeReference as? FirResolvedNamedReference - val unaryResult = resolvedNamedReference?.resolvedSymbol as? FirVariableSymbol<*> - return unaryResult?.fir?.initializer as? FirFunctionCall + return variableReference.toReference()?.toResolvedVariableSymbol()?.fir?.initializer as? FirFunctionCall } private fun getOperationPartiallyAppliedSymbolsForCompoundVariableAccess( @@ -718,14 +743,14 @@ internal class KtFirCallResolver( leftOperandPsi: KtExpression ): KtPartiallyAppliedFunctionSymbol? { // 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) } private fun FirVariableAssignment.toPartiallyAppliedSymbol(): KtPartiallyAppliedVariableSymbol? { val variableRef = calleeReference as? FirResolvedNamedReference ?: 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() return KtPartiallyAppliedSymbol( with(analysisSession) { ktSignature.substitute(substitutor.toKtSubstitutor()) }, @@ -801,7 +826,7 @@ internal class KtFirCallResolver( private fun FirVariableSymbol<*>.toKtSignature(): KtVariableLikeSignature = firSymbolBuilder.variableLikeBuilder.buildVariableLikeSignature(this) - private fun FirQualifiedAccess.toTypeArgumentsMapping( + private fun FirQualifiedAccessExpression.toTypeArgumentsMapping( partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *> ): Map { return toTypeArgumentsMapping(typeArguments, partiallyAppliedSymbol) @@ -1048,9 +1073,11 @@ internal class KtFirCallResolver( } private val FirResolvable.calleeOrCandidateName: Name? + get() = this.calleeReference.calleeOrCandidateName + + private val FirReference.calleeOrCandidateName: Name? get() { - val calleeReference = calleeReference - if (calleeReference !is FirNamedReference) return null + if (this !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 // 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 // element (`x` in the above example) if possible. - return when (val psi = calleeReference.psi) { + return when (val psi = psi) { is KtNameReferenceExpression -> psi.getReferencedNameAsName() else -> { // 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 // the applicability if not successful. - calleeReference.getCandidateSymbols().firstOrNull()?.safeAs>()?.name + getCandidateSymbols().firstOrNull()?.safeAs>()?.name } } } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt index b58fdd50845..fc278d814fd 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirExpressionTypeProvider.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.constructFunctionalType import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi.* import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -58,7 +59,9 @@ internal class KtFirExpressionTypeProvider( } } 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() } else { analysisSession.builtinTypes.UNIT diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirArgumentsConverter.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirArgumentsConverter.kt index a3868555b40..49af95dbfdd 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirArgumentsConverter.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirArgumentsConverter.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter 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.impl.FirBackingFieldSymbol 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 FirMemberDeclaration -> convertArgument(argument, firSymbolBuilder) is FirDeclaration -> convertArgument(argument, firSymbolBuilder) - is FirQualifiedAccess -> convertArgument(argument, firSymbolBuilder) + is FirQualifiedAccessExpression -> convertArgument(argument, firSymbolBuilder) is FirExpression -> convertArgument(argument, firSymbolBuilder) is ConeKotlinType -> convertArgument(argument, firSymbolBuilder) is FirTypeRef -> convertArgument(argument, firSymbolBuilder) @@ -163,7 +163,7 @@ private fun convertArgument(argument: FirDeclaration, firSymbolBuilder: KtSymbol 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 } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt index fa646a76b27..5ce4108b963 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt @@ -309,7 +309,7 @@ internal object FirReferenceResolveHelper { symbolBuilder: KtSymbolByFirBuilder, ): Collection { if (expression is KtNameReferenceExpression) { - return fir.calleeReference.toTargetSymbol(session, symbolBuilder) + return fir.calleeReference?.toTargetSymbol(session, symbolBuilder) ?: emptyList() } val assignmentRValue = fir.rValue diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt index 23fa2530caf..1c368869cb5 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt @@ -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.fir.FirElement import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider 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) { override val mappings = KtToFirMapping(fir, FirElementsRecorder()) @@ -252,4 +258,4 @@ internal class RootStructureElement( } } } -} \ No newline at end of file +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FirElementsRecorder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FirElementsRecorder.kt index 961a03bdf0a..3b8388d60ba 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FirElementsRecorder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FirElementsRecorder.kt @@ -63,7 +63,8 @@ internal open class FirElementsRecorder : FirVisitor) { - 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) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt index cc60ae29411..3681a8f1723 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolver/AllCandidatesResolver.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall 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.calls.InapplicableCandidate 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. */ 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 diagnostic = calleeReference.diagnostic as? ConeInapplicableCandidateError ?: return if (diagnostic.applicability != CandidateApplicability.INAPPLICABLE) return diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index 85dbbfce28b..71b4099b427 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -31,7 +31,6 @@ fun main(args: Array) { val expressionPackage = "$basePackage.checkers.expression" generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") { alias("BasicExpressionChecker") - alias("QualifiedAccessChecker") alias("QualifiedAccessExpressionChecker") alias("CallChecker") alias("FunctionCallChecker") diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 9692dfd9116..51b150cdc34 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -64,7 +64,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error() val NOT_A_LOOP_LABEL by error() val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error() - val VARIABLE_EXPECTED by error(PositioningStrategy.ASSIGNMENT_LHS) + val VARIABLE_EXPECTED by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) val DELEGATION_IN_INTERFACE by error() val DELEGATION_NOT_TO_INTERFACE by error() val NESTED_CLASS_NOT_ALLOWED by error(PositioningStrategy.DECLARATION_NAME) { @@ -91,7 +91,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error(PositioningStrategy.VAL_OR_VAR_NODE) { parameter("valOrVar") } - val INVISIBLE_SETTER by error(PositioningStrategy.ASSIGNMENT_LHS) { + val INVISIBLE_SETTER by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) { parameter("property") parameter("visibility") parameter("callableId") @@ -1135,10 +1135,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val UNINITIALIZED_ENUM_COMPANION by error(PositioningStrategy.REFERENCE_BY_QUALIFIED) { parameter("enumClass") } - val VAL_REASSIGNMENT by error { + val VAL_REASSIGNMENT by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) { parameter>("variable") } - val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError(LanguageFeature.RestrictionOfValReassignmentViaBackingField) { + val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError(LanguageFeature.RestrictionOfValReassignmentViaBackingField, PositioningStrategy.SELECTOR_BY_QUALIFIED) { parameter("property") } val CAPTURED_VAL_INITIALIZATION by error { @@ -1147,7 +1147,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val CAPTURED_MEMBER_VAL_INITIALIZATION by error { parameter("property") } - val SETTER_PROJECTED_OUT by error(PositioningStrategy.ASSIGNMENT_LHS) { + val SETTER_PROJECTED_OUT by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) { parameter("property") } val WRONG_INVOCATION_KIND by warning { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt index 20d8f48ba15..d96b53e2bd2 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/model/RegularDiagnosticData.kt @@ -90,7 +90,6 @@ enum class PositioningStrategy(private val strategy: String? = null) { NAME_IDENTIFIER, QUESTION_MARK_BY_TYPE, ANNOTATION_USE_SITE, - ASSIGNMENT_LHS, IMPORT_LAST_NAME, DATA_MODIFIER, SPREAD_OPERATOR, diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsExpressionCheckers.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsExpressionCheckers.kt index 0fd414ab8e6..97cc3ec81c0 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsExpressionCheckers.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsExpressionCheckers.kt @@ -14,8 +14,8 @@ object JsExpressionCheckers : ExpressionCheckers() { FirJsQualifierChecker, ) - override val qualifiedAccessCheckers: Set + override val basicExpressionCheckers: Set get() = setOf( - FirJsDefinedExternallyCallChecker, + FirJsDefinedExternallyCallChecker ) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/expression/FirJsDefinedExternallyCallChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/expression/FirJsDefinedExternallyCallChecker.kt index 949c162129a..73921a73f63 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/expression/FirJsDefinedExternallyCallChecker.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/expression/FirJsDefinedExternallyCallChecker.kt @@ -9,17 +9,20 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.checkers.closestNonLocal 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.isPredefinedObject -import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +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.name.JsStandardClassIds -object FirJsDefinedExternallyCallChecker : FirQualifiedAccessChecker() { - override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { - val symbol = expression.calleeReference.toResolvedCallableSymbol() ?: return +object FirJsDefinedExternallyCallChecker : FirBasicExpressionChecker() { + override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { + val symbol = expression.calleeReference?.toResolvedCallableSymbol() ?: return if (symbol.callableId !in JsStandardClassIds.Callables.definedExternallyPropertyNames) { return diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt index ac88135a421..b2634f739c9 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmExpressionCheckers.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.* import org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression.* object JvmExpressionCheckers : ExpressionCheckers() { - override val qualifiedAccessCheckers: Set + override val basicExpressionCheckers: Set get() = setOf( FirJvmProtectedInSuperClassCompanionCallChecker ) diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmProtectedInSuperClassCompanionCallChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmProtectedInSuperClassCompanionCallChecker.kt index c96dc89cb95..198a9d28f49 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmProtectedInSuperClassCompanionCallChecker.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmProtectedInSuperClassCompanionCallChecker.kt @@ -6,20 +6,19 @@ package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression 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.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.toRegularClassSymbol -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter 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.getAnnotationByClassId import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.declarations.utils.visibility -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess -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.references.toResolvedCallableSymbol 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.types.AbstractTypeChecker -object FirJvmProtectedInSuperClassCompanionCallChecker : FirQualifiedAccessChecker() { - override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { - val dispatchReceiver = expression.dispatchReceiver +object FirJvmProtectedInSuperClassCompanionCallChecker : FirBasicExpressionChecker() { + override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { + val dispatchReceiver = when (expression) { + is FirQualifiedAccessExpression -> expression.dispatchReceiver + is FirVariableAssignment -> expression.dispatchReceiver + else -> null + } ?: return + if (dispatchReceiver is FirNoReceiverExpression) 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) { if (expression is FirVariableAssignment) @@ -64,7 +69,7 @@ object FirJvmProtectedInSuperClassCompanionCallChecker : FirQualifiedAccessCheck it.symbol == dispatchClassSymbol || it.symbol == companionContainingClassSymbol } == 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) } } } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmSuspensionPointInsideMutexLockChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmSuspensionPointInsideMutexLockChecker.kt index 41608fca641..c2694e82f6d 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmSuspensionPointInsideMutexLockChecker.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJvmSuspensionPointInsideMutexLockChecker.kt @@ -28,7 +28,7 @@ object FirJvmSuspensionPointInsideMutexLockChecker : FirFunctionCallChecker() { if (!symbol.isSuspend) return val closestAnonymousFunction = context.findClosest() ?: return - for (call in context.qualifiedAccessOrAnnotationCalls.asReversed()) { + for (call in context.qualifiedAccessOrAssignmentsOrAnnotationCalls.asReversed()) { if (call is FirFunctionCall) { val callableSymbol = call.calleeReference.toResolvedCallableSymbol() ?: continue if (callableSymbol.callableId == synchronizedCallableId) { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt index 91f5c06d32f..a3f17178685 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt @@ -15,8 +15,6 @@ import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal class ComposedExpressionCheckers : ExpressionCheckers() { override val basicExpressionCheckers: Set get() = _basicExpressionCheckers - override val qualifiedAccessCheckers: Set - get() = _qualifiedAccessCheckers override val qualifiedAccessExpressionCheckers: Set get() = _qualifiedAccessExpressionCheckers override val callCheckers: Set @@ -81,7 +79,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() { get() = _classReferenceExpressionCheckers private val _basicExpressionCheckers: MutableSet = mutableSetOf() - private val _qualifiedAccessCheckers: MutableSet = mutableSetOf() private val _qualifiedAccessExpressionCheckers: MutableSet = mutableSetOf() private val _callCheckers: MutableSet = mutableSetOf() private val _functionCallCheckers: MutableSet = mutableSetOf() @@ -117,7 +114,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() { @CheckersComponentInternal fun register(checkers: ExpressionCheckers) { _basicExpressionCheckers += checkers.basicExpressionCheckers - _qualifiedAccessCheckers += checkers.qualifiedAccessCheckers _qualifiedAccessExpressionCheckers += checkers.qualifiedAccessExpressionCheckers _callCheckers += checkers.callCheckers _functionCallCheckers += checkers.functionCallCheckers diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt index 0b3c28c6605..9d455905526 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt @@ -18,7 +18,6 @@ abstract class ExpressionCheckers { } open val basicExpressionCheckers: Set = emptySet() - open val qualifiedAccessCheckers: Set = emptySet() open val qualifiedAccessExpressionCheckers: Set = emptySet() open val callCheckers: Set = emptySet() open val functionCallCheckers: Set = emptySet() @@ -52,13 +51,12 @@ abstract class ExpressionCheckers { open val classReferenceExpressionCheckers: Set = emptySet() @CheckersComponentInternal internal val allBasicExpressionCheckers: Set by lazy { basicExpressionCheckers } - @CheckersComponentInternal internal val allQualifiedAccessCheckers: Set by lazy { qualifiedAccessCheckers + basicExpressionCheckers } - @CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } + @CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allCallCheckers: Set by lazy { callCheckers + basicExpressionCheckers } - @CheckersComponentInternal internal val allFunctionCallCheckers: Set by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers } - @CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } - @CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers } - @CheckersComponentInternal internal val allVariableAssignmentCheckers: Set by lazy { variableAssignmentCheckers + qualifiedAccessCheckers + basicExpressionCheckers } + @CheckersComponentInternal internal val allFunctionCallCheckers: Set by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers } + @CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers } + @CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers } + @CheckersComponentInternal internal val allVariableAssignmentCheckers: Set by lazy { variableAssignmentCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allTryExpressionCheckers: Set by lazy { tryExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allWhenExpressionCheckers: Set by lazy { whenExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allLoopExpressionCheckers: Set by lazy { loopExpressionCheckers + basicExpressionCheckers } @@ -77,8 +75,8 @@ abstract class ExpressionCheckers { @CheckersComponentInternal internal val allTypeOperatorCallCheckers: Set by lazy { typeOperatorCallCheckers + basicExpressionCheckers + callCheckers } @CheckersComponentInternal internal val allResolvedQualifierCheckers: Set by lazy { resolvedQualifierCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allConstExpressionCheckers: Set by lazy { constExpressionCheckers + basicExpressionCheckers } - @CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } - @CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } + @CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers } + @CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allWhileLoopCheckers: Set by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allThrowExpressionCheckers: Set by lazy { throwExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allDoWhileLoopCheckers: Set by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt index 131337b03e3..80c1616b9bf 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall import org.jetbrains.kotlin.fir.expressions.FirLoop import org.jetbrains.kotlin.fir.expressions.FirLoopJump 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.FirResolvedQualifier 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 typealias FirBasicExpressionChecker = FirExpressionChecker -typealias FirQualifiedAccessChecker = FirExpressionChecker typealias FirQualifiedAccessExpressionChecker = FirExpressionChecker typealias FirCallChecker = FirExpressionChecker typealias FirFunctionCallChecker = FirExpressionChecker diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 73ac111274a..89462926f5e 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -123,7 +123,7 @@ object FirErrors { val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0() val NOT_A_LOOP_LABEL by error0() val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error0() - val VARIABLE_EXPECTED by error0(SourceElementPositioningStrategies.ASSIGNMENT_LHS) + val VARIABLE_EXPECTED by error0(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val DELEGATION_IN_INTERFACE by error0() val DELEGATION_NOT_TO_INTERFACE by error0() val NESTED_CLASS_NOT_ALLOWED by error1(SourceElementPositioningStrategies.DECLARATION_NAME) @@ -140,7 +140,7 @@ object FirErrors { val VAL_OR_VAR_ON_FUN_PARAMETER by error1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_CATCH_PARAMETER by error1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) - val INVISIBLE_SETTER by error3(SourceElementPositioningStrategies.ASSIGNMENT_LHS) + val INVISIBLE_SETTER by error3(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) // Unresolved val INVISIBLE_REFERENCE by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) @@ -607,11 +607,11 @@ object FirErrors { val UNINITIALIZED_PARAMETER by error1() val UNINITIALIZED_ENUM_ENTRY by error1() val UNINITIALIZED_ENUM_COMPANION by error1(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) - val VAL_REASSIGNMENT by error1>() - val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1(RestrictionOfValReassignmentViaBackingField) + val VAL_REASSIGNMENT by error1>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) + val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1(RestrictionOfValReassignmentViaBackingField, SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val CAPTURED_VAL_INITIALIZATION by error1() val CAPTURED_MEMBER_VAL_INITIALIZATION by error1() - val SETTER_PROJECTED_OUT by error1(SourceElementPositioningStrategies.ASSIGNMENT_LHS) + val SETTER_PROJECTED_OUT by error1(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val WRONG_INVOCATION_KIND by warning3, EventOccurrencesRange, EventOccurrencesRange>() val LEAKED_IN_PLACE_LAMBDA by warning1>() val WRONG_IMPLIES_CONDITION by warning0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirCallsEffectAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirCallsEffectAnalyzer.kt index 892152c4805..8048330a890 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirCallsEffectAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirCallsEffectAnalyzer.kt @@ -22,11 +22,8 @@ import org.jetbrains.kotlin.fir.contracts.effects import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner import org.jetbrains.kotlin.fir.declarations.FirFunction -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirFunctionCall -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.expressions.* 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.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirThisReference @@ -309,7 +306,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() { 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) { is FirResolvedNamedReference -> reference.resolvedSymbol diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt index 98ed59c7cf7..92f059d846c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/FirPropertyInitializationAnalyzer.kt @@ -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.hasExplicitBackingField 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.calleeReference +import org.jetbrains.kotlin.fir.expressions.unwrapLValue import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* @@ -65,7 +67,7 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( scope: FirDeclaration?, scopes: MutableMap, ) { - fun FirQualifiedAccess.hasCorrectReceiver() = + fun FirQualifiedAccessExpression.hasCorrectReceiver() = (dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol == receiver for (node in graph.nodes) { @@ -83,17 +85,17 @@ private fun PropertyInitializationInfoData.checkPropertyAccesses( } node is VariableAssignmentNode -> { - val symbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: continue - if (!symbol.fir.isVal || !node.fir.hasCorrectReceiver() || symbol !in properties) continue + val symbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: 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) FirErrors.CAPTURED_MEMBER_VAL_INITIALIZATION else FirErrors.CAPTURED_VAL_INITIALIZATION 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) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt index 9f6edb3a34f..a9a592e556d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/util/PropertyInitializationInfoCollector.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.cfa.util import kotlinx.collections.immutable.persistentMapOf import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange 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.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -51,7 +53,7 @@ class PropertyInitializationInfoCollector( val dataForNode = visitNode(node, data) val receiver = (node.fir.dispatchReceiver as? FirThisReceiverExpression)?.calleeReference?.boundSymbol 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 return addRange(dataForNode, symbol, EventOccurrencesRange.EXACTLY_ONCE) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index ecea7c99c43..d6fc28d33ac 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -22,7 +22,8 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirUnderscoreChecker, FirExpressionAnnotationChecker, FirDeprecationChecker, - FirRecursiveProblemChecker + FirRecursiveProblemChecker, + FirOptInUsageAccessChecker, ) override val throwExpressionCheckers: Set @@ -30,11 +31,6 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirThrowExpressionTypeChecker, ) - override val qualifiedAccessCheckers: Set - get() = setOf( - FirOptInUsageAccessChecker, - ) - override val qualifiedAccessExpressionCheckers: Set get() = setOf( FirCallableReferenceChecker, @@ -83,7 +79,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val variableAssignmentCheckers: Set get() = setOf( FirReassignmentAndInvisibleSetterChecker, - FirAssignmentTypeMismatchChecker + FirAssignmentTypeMismatchChecker, ) override val whenExpressionCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index f2ef910b685..a2cae6209c3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -655,7 +655,7 @@ fun getActualTargetList(annotated: FirDeclaration): AnnotationTargetList { private typealias TargetLists = AnnotationTargetLists -fun FirQualifiedAccess.explicitReceiverIsNotSuperReference(): Boolean { +fun FirQualifiedAccessExpression.explicitReceiverIsNotSuperReference(): Boolean { 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<*> 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 +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt index 82b122fd3a5..e70c9cd70f6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt @@ -31,7 +31,7 @@ abstract class CheckerContext : MutableDiagnosticContext() { // Context abstract val implicitReceiverStack: ImplicitReceiverStack abstract val containingDeclarations: List - abstract val qualifiedAccessOrAnnotationCalls: List + abstract val qualifiedAccessOrAssignmentsOrAnnotationCalls: List abstract val getClassCalls: List abstract val annotationContainers: List abstract val isContractBody: Boolean diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt index 058072d09d9..9959ed6c55d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/MutableCheckerContext.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.name.Name class MutableCheckerContext private constructor( override val implicitReceiverStack: PersistentImplicitReceiverStack, override val containingDeclarations: MutableList, - override val qualifiedAccessOrAnnotationCalls: MutableList, + override val qualifiedAccessOrAssignmentsOrAnnotationCalls: MutableList, override val getClassCalls: MutableList, override val annotationContainers: MutableList, override var isContractBody: Boolean, @@ -50,7 +50,7 @@ class MutableCheckerContext private constructor( return MutableCheckerContext( implicitReceiverStack.add(name, value), containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody, @@ -73,12 +73,12 @@ class MutableCheckerContext private constructor( } override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): MutableCheckerContext { - qualifiedAccessOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall) + qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall) return this } override fun dropQualifiedAccessOrAnnotationCall() { - qualifiedAccessOrAnnotationCalls.removeAt(qualifiedAccessOrAnnotationCalls.size - 1) + qualifiedAccessOrAssignmentsOrAnnotationCalls.removeAt(qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 1) } override fun addGetClassCall(getClassCall: FirGetClassCall): MutableCheckerContext { @@ -109,7 +109,7 @@ class MutableCheckerContext private constructor( return MutableCheckerContext( implicitReceiverStack, containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt index 733f6af83ff..75b9eb41412 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/PersistentCheckerContext.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.Name class PersistentCheckerContext private constructor( override val implicitReceiverStack: PersistentImplicitReceiverStack, override val containingDeclarations: PersistentList, - override val qualifiedAccessOrAnnotationCalls: PersistentList, + override val qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList, override val getClassCalls: PersistentList, override val annotationContainers: PersistentList, override val isContractBody: Boolean, @@ -52,7 +52,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack.add(name, value), containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody, @@ -69,7 +69,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations.add(declaration), - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody, @@ -89,7 +89,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations, - this.qualifiedAccessOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall), + this.qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall), getClassCalls, annotationContainers, isContractBody, @@ -109,7 +109,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls.add(getClassCall), annotationContainers, isContractBody, @@ -129,7 +129,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers.add(annotationContainer), isContractBody, @@ -155,7 +155,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody, @@ -174,7 +174,7 @@ class PersistentCheckerContext private constructor( return PersistentCheckerContext( implicitReceiverStack, containingDeclarations, - qualifiedAccessOrAnnotationCalls, + qualifiedAccessOrAssignmentsOrAnnotationCalls, getClassCalls, annotationContainers, isContractBody = newValue, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt index 7d9b44e53b7..5e41b0ee3d3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt @@ -182,7 +182,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() { } 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 get() = diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt index c9c7e4a2d41..901f144a118 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineDeclarationChecker.kt @@ -111,7 +111,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() { override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, 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 checkQualifiedAccess(variableAssignment, setterSymbol, data) } @@ -237,7 +237,7 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() { } private fun checkQualifiedAccess( - qualifiedAccess: FirQualifiedAccess, + qualifiedAccess: FirStatement, targetSymbol: FirBasedSymbol<*>?, context: CheckerContext ) { @@ -253,18 +253,18 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() { checkRecursion(targetSymbol, source, context) } - private fun FirQualifiedAccess.partOfCall(context: CheckerContext): Boolean { + private fun FirStatement.partOfCall(context: CheckerContext): Boolean { if (this !is FirExpression) return false - val containingQualifiedAccess = context.qualifiedAccessOrAnnotationCalls.getOrNull( - context.qualifiedAccessOrAnnotationCalls.size - 2 + val containingQualifiedAccess = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.getOrNull( + context.qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 2 ) ?: 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 return call.arguments.any { it.unwrapArgument() == this } } private fun checkVisibilityAndAccess( - accessExpression: FirQualifiedAccess, + accessExpression: FirStatement, calledDeclaration: FirCallableSymbol<*>?, source: KtSourceElement, context: CheckerContext @@ -321,16 +321,21 @@ abstract class FirInlineDeclarationChecker : FirFunctionChecker() { private fun checkSuperCalls( calledDeclaration: FirCallableSymbol<*>, - callExpression: FirQualifiedAccess, + callExpression: FirStatement, 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) { val dispatchReceiverType = receiver.dispatchReceiver.typeRef.coneType val classSymbol = dispatchReceiverType.toSymbol(session) ?: return if (!classSymbol.isDefinedInInlineFunction()) { reporter.reportOn( - callExpression.dispatchReceiver.source, + receiver.source, FirErrors.SUPER_CALL_FROM_PUBLIC_INLINE, calledDeclaration, context diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirPropertyInitializationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirPropertyInitializationChecker.kt index cf142552897..ebb28e3ef13 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirPropertyInitializationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirPropertyInitializationChecker.kt @@ -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.declarations.* 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.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid @@ -38,7 +39,7 @@ object FirPropertyInitializationChecker : FirRegularClassChecker() { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) { variableAssignment.acceptChildren(this) - val propertySymbol = variableAssignment.lValue.toResolvedCallableSymbol() as? FirPropertySymbol ?: return + val propertySymbol = variableAssignment.calleeReference?.toResolvedCallableSymbol() as? FirPropertySymbol ?: return if (propertySymbol !in declaredLater) return reporter.reportOn(variableAssignment.lValue.source, FirErrors.INITIALIZATION_BEFORE_DECLARATION, propertySymbol, context) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAssignmentTypeMismatchChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAssignmentTypeMismatchChecker.kt index f0b115780e9..abf908128fc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAssignmentTypeMismatchChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAssignmentTypeMismatchChecker.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.types.coneType object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() { override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { val source = expression.rValue.source ?: return - val coneType = expression.lValueTypeRef.coneType + val coneType = expression.lValue.typeRef.coneType checkTypeMismatch( coneType, expression, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt index d9d02198064..449525d4084 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt @@ -29,7 +29,7 @@ object FirConstructorCallChecker : FirFunctionCallChecker() { reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context) } if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS && - context.qualifiedAccessOrAnnotationCalls.all { call -> + context.qualifiedAccessOrAssignmentsOrAnnotationCalls.all { call -> call !is FirAnnotation } && context.containingDeclarations.all { klass -> diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt index c97b27023ba..b8ea4d4c32a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecationChecker.kt @@ -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.diagnostics.FirErrors 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.expressions.FirAnnotation -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.expressions.* import org.jetbrains.kotlin.fir.references.resolved import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -36,11 +34,13 @@ object FirDeprecationChecker : FirBasicExpressionChecker() { override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { if (!allowedSourceKinds.contains(expression.source?.kind)) return if (expression is FirAnnotation || expression is FirDelegatedConstructorCall) return //checked by FirDeprecatedTypeChecker - val resolvable = expression as? FirResolvable ?: return - val reference = resolvable.calleeReference.resolved ?: return - val referencedSymbol = reference.resolvedSymbol + if (expression.isLhsOfAssignment(context)) return - 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( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt index a47d064c2a5..3e1cca30cf7 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirOptInUsageAccessChecker.kt @@ -8,33 +8,37 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess -import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.analysis.checkers.isLhsOfAssignment +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.resolve.fullyExpandedType -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.coneType -object FirOptInUsageAccessChecker : FirQualifiedAccessChecker() { - override fun check(expression: FirQualifiedAccess, context: CheckerContext, reporter: DiagnosticReporter) { +object FirOptInUsageAccessChecker : FirBasicExpressionChecker() { + override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) { val sourceKind = expression.source?.kind if (sourceKind is KtFakeSourceElementKind.DataClassGeneratedMembers || sourceKind is KtFakeSourceElementKind.PropertyFromParameter ) return - val resolvedSymbol = expression.calleeReference.toResolvedBaseSymbol() ?: return - val dispatchReceiverType = - expression.dispatchReceiver.takeIf { it !is FirNoReceiverExpression }?.typeRef?.coneType?.fullyExpandedType(context.session) + + if (expression.isLhsOfAssignment(context)) return + + val resolvedSymbol = expression.calleeReference?.toResolvedBaseSymbol() ?: return + with(FirOptInUsageBaseChecker) { - if (expression is FirVariableAssignment && resolvedSymbol is FirPropertySymbol) { - val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true, dispatchReceiverType) + - loadExperimentalitiesFromTypeArguments(context, expression.typeArguments) + if (expression is FirVariableAssignment) { + val experimentalities = resolvedSymbol.loadExperimentalities(context, fromSetter = true, null) + + loadExperimentalitiesFromTypeArguments(context, emptyList()) 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) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt index b6940a94935..99976c4d4d5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReassignmentAndInvisibleSetterChecker.kt @@ -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.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.visibility -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression -import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression -import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.originalForSubstitutionOverride -import org.jetbrains.kotlin.fir.references.FirBackingFieldReference -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.references.* 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.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.visibilityChecker @@ -36,7 +33,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() checkInvisibleSetter(expression, context, reporter) checkValReassignmentViaBackingField(expression, context, reporter) checkValReassignmentOnValueParameter(expression, context, reporter) - checkAssignmentToThis(expression, context, reporter) + checkVariableExpected(expression, context, reporter) checkValReassignment(expression, context, reporter) } @@ -61,7 +58,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() return false } - val callableSymbol = expression.calleeReference.toResolvedCallableSymbol() + val callableSymbol = expression.calleeReference?.toResolvedCallableSymbol() if (callableSymbol is FirPropertySymbol && shouldInvisibleSetterBeReported(callableSymbol)) { val explicitReceiver = expression.explicitReceiver // Try to get type from smartcast @@ -78,7 +75,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() } } reporter.reportOn( - expression.source, + expression.lValue.source, FirErrors.INVISIBLE_SETTER, callableSymbol, callableSymbol.setterSymbol?.visibility ?: Visibilities.Private, @@ -93,7 +90,7 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() context: CheckerContext, reporter: DiagnosticReporter ) { - val backingFieldReference = expression.lValue as? FirBackingFieldReference ?: return + val backingFieldReference = expression.calleeReference as? FirBackingFieldReference ?: return val propertySymbol = backingFieldReference.resolvedSymbol if (propertySymbol.isVar) return val closestGetter = context.findClosest { it.isGetter }?.symbol ?: return @@ -107,22 +104,37 @@ object FirReassignmentAndInvisibleSetterChecker : FirVariableAssignmentChecker() context: CheckerContext, reporter: DiagnosticReporter ) { - val valueParameter = expression.lValue.toResolvedValueParameterSymbol() ?: return + val valueParameter = expression.calleeReference?.toResolvedValueParameterSymbol() ?: return reporter.reportOn(expression.lValue.source, FirErrors.VAL_REASSIGNMENT, valueParameter, context) } - private fun checkAssignmentToThis( + private fun checkVariableExpected( expression: FirVariableAssignment, context: CheckerContext, 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) } } + 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) { - val property = expression.lValue.toResolvedPropertySymbol() ?: return + val property = expression.calleeReference?.toResolvedPropertySymbol() ?: return if (property.isVar) return // 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. diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReturnSyntaxAndLabelChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReturnSyntaxAndLabelChecker.kt index 35fc332a747..246a2679fa3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReturnSyntaxAndLabelChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirReturnSyntaxAndLabelChecker.kt @@ -36,7 +36,7 @@ object FirReturnSyntaxAndLabelChecker : FirReturnExpressionChecker() { if (targetSymbol is FirAnonymousFunctionSymbol) { val label = targetSymbol.label if (label?.source?.kind !is KtRealSourceElementKind) { - val functionCall = context.qualifiedAccessOrAnnotationCalls.asReversed().find { + val functionCall = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.asReversed().find { it is FirFunctionCall && (it.calleeReference.toResolvedFunctionSymbol())?.callableId == FirSuspendCallChecker.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_CALLABLE_ID diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt index 8d71b78c0bc..25b09ed88cc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirStandaloneQualifierChecker.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn 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.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.isUnit object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() { 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 if (lastQualifiedAccess?.explicitReceiver === expression || lastQualifiedAccess?.dispatchReceiver === expression) return val lastGetClass = context.getClassCalls.lastOrNull() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeParameterInQualifiedAccessChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeParameterInQualifiedAccessChecker.kt index dfbd85b2689..4b9784aee2a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeParameterInQualifiedAccessChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeParameterInQualifiedAccessChecker.kt @@ -33,7 +33,7 @@ object FirTypeParameterInQualifiedAccessChecker : FirQualifiedAccessExpressionCh // 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 // 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 val diagnostic = expression.typeRef.coneTypeParameterInQualifiedAccess ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnsupportedArrayLiteralChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnsupportedArrayLiteralChecker.kt index 0ad84fe236b..dc37d46524d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnsupportedArrayLiteralChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnsupportedArrayLiteralChecker.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.* object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() { override fun check(expression: FirArrayOfCall, context: CheckerContext, reporter: DiagnosticReporter) { if (!isInsideAnnotationCall(expression, context) && - (context.qualifiedAccessOrAnnotationCalls.isNotEmpty() || !isInsideAnnotationClass(context)) + (context.qualifiedAccessOrAssignmentsOrAnnotationCalls.isNotEmpty() || !isInsideAnnotationClass(context)) ) { reporter.reportOn( expression.source, @@ -32,7 +32,7 @@ object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() { } private fun isInsideAnnotationCall(expression: FirArrayOfCall, context: CheckerContext): Boolean { - context.qualifiedAccessOrAnnotationCalls.lastOrNull()?.let { + context.qualifiedAccessOrAssignmentsOrAnnotationCalls.lastOrNull()?.let { val arguments = when (it) { is FirFunctionCall -> if (it.typeRef.toRegularClassSymbol(context.session)?.classKind == ClassKind.ANNOTATION_CLASS) { @@ -87,4 +87,4 @@ object FirUnsupportedArrayLiteralChecker : FirArrayOfCallChecker() { return false } -} \ No newline at end of file +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt index 56c41fdffef..d478df63bee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.dispatchReceiverClassTypeOrNull import org.jetbrains.kotlin.fir.expressions.FirFunctionCall 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.references.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.psi @@ -32,7 +33,7 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker() { override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) { - val lValue = expression.lValue + val lValue = expression.calleeReference if (lValue !is FirResolvedNamedReference) return if (expression.source?.kind is KtFakeSourceElementKind) return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt index 5109dd94d1d..aacd6ff0889 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt @@ -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.diagnostics.FirErrors 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.resolve.dfa.cfg.* import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol @@ -48,7 +49,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() { override fun visitNode(node: CFGNode<*>) {} 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 && (!symbol.requiresInitialization || data.getValue(node).values.any { it[symbol]?.canBeRevisited() == true }) ) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt index 25f1d7d4d4f..e00b32afe6e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt @@ -44,7 +44,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() { override fun visitNode(node: CFGNode<*>) {} override fun visitVariableAssignmentNode(node: VariableAssignmentNode) { - val variableSymbol = node.fir.calleeReference.toResolvedPropertySymbol() ?: return + val variableSymbol = node.fir.calleeReference?.toResolvedPropertySymbol() ?: return val dataPerNode = data[node] ?: return for (dataPerLabel in dataPerNode.values) { val data = dataPerLabel[variableSymbol] ?: continue @@ -210,7 +210,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() { data: PathAwareVariableStatusInfo ): PathAwareVariableStatusInfo { 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 -> val toPut = when { symbol !in localProperties -> { @@ -247,7 +247,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() { annotation: FirAnnotation, ): PathAwareVariableStatusInfo { 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) } else { dataForNode @@ -256,9 +256,9 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() { private fun visitQualifiedAccesses( dataForNode: PathAwareVariableStatusInfo, - vararg qualifiedAccesses: FirQualifiedAccess, + vararg qualifiedAccesses: FirQualifiedAccessExpression, ): PathAwareVariableStatusInfo { - fun retrieveSymbol(qualifiedAccess: FirQualifiedAccess): FirPropertySymbol? { + fun retrieveSymbol(qualifiedAccess: FirQualifiedAccessExpression): FirPropertySymbol? { return qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.takeIf { it in localProperties } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt index c28fa90aada..6b3a1720a77 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/type/FirOptInUsageTypeRefChecker.kt @@ -36,7 +36,7 @@ object FirOptInUsageTypeRefChecker : FirTypeRefChecker() { val symbol = coneType.lookupTag.toSymbol(context.session) ?: return symbol.lazyResolveToPhase(FirResolvePhase.STATUS) 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 (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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt index 95023707239..ee75c1c8548 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt @@ -36,9 +36,13 @@ abstract class AbstractDiagnosticCollectorVisitor( override fun visitElement(element: FirElement, data: Nothing?) { if (element is FirAnnotationContainer) { - visitAnnotationContainer(element, data) + withAnnotationContainer(element) { + checkElement(element) + visitNestedElements(element) + } return } + checkElement(element) visitNestedElements(element) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index 5bb2fd7dcc9..9f56033fc39 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.diagnostics.* -import org.jetbrains.kotlin.fir.types.ConeErrorType -import org.jetbrains.kotlin.fir.types.FirErrorTypeRef -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.renderForDebugging +import org.jetbrains.kotlin.fir.types.* class ErrorNodeDiagnosticCollectorComponent( session: FirSession, @@ -63,13 +60,9 @@ class ErrorNodeDiagnosticCollectorComponent( private fun processErrorReference(reference: FirNamedReference, diagnostic: ConeDiagnostic, context: CheckerContext) { 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. - when (it) { - is FirQualifiedAccess -> it.calleeReference == reference - is FirAnnotationCall -> it.calleeReference == reference - else -> false - } + it.calleeReference == reference } // Don't report duplicated unresolved reference on annotation entry (already reported on its type) if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return @@ -79,7 +72,7 @@ class ErrorNodeDiagnosticCollectorComponent( ) return // 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() || qualifiedAccessOrAnnotationCall.extensionReceiver.cannotBeResolved() || qualifiedAccessOrAnnotationCall.explicitReceiver.cannotBeResolved() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 80bbec90347..2f4ac90ec05 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -91,10 +91,6 @@ private fun ConeDiagnostic.toKtDiagnostic( is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidateSymbols) 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 ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString()) diff --git a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt index 97b30d1c56c..8d8958e950b 100644 --- a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt +++ b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt @@ -727,7 +727,6 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver } private fun FlowContent.generate(variableAssignment: FirVariableAssignment) { - generateReceiver(variableAssignment) generate(variableAssignment.lValue) +" = " 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 if (explicitReceiver != null) { generate(explicitReceiver) @@ -1608,14 +1607,10 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver +"?." val selector = safeCallExpression.selector - if (selector is FirQualifiedAccess && selector.explicitReceiver == safeCallExpression.checkedSubjectRef.value) { - when (selector) { - is FirFunctionCall -> { - return generate(selector, skipReceiver = true) - } - is FirQualifiedAccessExpression -> { - return generate(selector, skipReceiver = true) - } + if (selector is FirQualifiedAccessExpression && selector.explicitReceiver == safeCallExpression.checkedSubjectRef.value) { + return when (selector) { + is FirFunctionCall -> generate(selector, skipReceiver = true) + else -> generate(selector, skipReceiver = true) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 6b8066d513f..15cc3440f82 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -78,7 +78,14 @@ internal fun KtSourceElement?.convertWithOffsets( return f(startOffset, endOffset) } -internal fun FirQualifiedAccess.convertWithOffsets( +internal fun FirQualifiedAccessExpression.convertWithOffsets( + f: (startOffset: Int, endOffset: Int) -> T +): T { + return convertWithOffsets(this.calleeReference, f) +} + +internal fun FirStatement.convertWithOffsets( + calleeReference: FirReference, f: (startOffset: Int, endOffset: Int) -> T ): T { val psi = calleeReference.psi @@ -718,7 +725,7 @@ fun FirDeclaration?.computeIrOrigin(predefinedOrigin: IrDeclarationOrigin? = nul } fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin { - val calleeReferenceSymbol = calleeReference.toResolvedCallableSymbol() ?: return IrStatementOrigin.EQ + val calleeReferenceSymbol = calleeReference?.toResolvedCallableSymbol() ?: return IrStatementOrigin.EQ val rValue = rValue if (rValue is FirFunctionCall && calleeReferenceSymbol.callableId.isLocal) { val callableId = rValue.calleeReference.toResolvedCallableSymbol()?.callableId @@ -736,9 +743,8 @@ fun FirVariableAssignment.getIrAssignmentOrigin(): IrStatementOrigin { IrStatementOrigin.POSTFIX_DECR } - if (calleeReference.source?.kind is KtFakeSourceElementKind && - calleeReferenceSymbol == rValue.explicitReceiver?.toResolvedCallableSymbol() - ) { + val kind = rValue.source?.kind + if (kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement || kind == KtFakeSourceElementKind.DesugaredCompoundAssignment) { if (callableName == OperatorNameConventions.PLUS) { return IrStatementOrigin.PLUSEQ } else if (callableName == OperatorNameConventions.MINUS) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 4a78772f8b4..04b57fb34d5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -913,7 +913,7 @@ class Fir2IrDeclarationStorage( val setter = property.setter if (delegate != null || property.hasBackingField) { 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) } createBackingField( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt index 54fe3db3ccb..6fcc521d32b 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrImplicitCastInserter.kt @@ -274,10 +274,10 @@ class Fir2IrImplicitCastInserter( internal fun implicitCastFromDispatchReceiver( original: IrExpression, originalTypeRef: FirTypeRef, - calleeReference: FirReference, + calleeReference: FirReference?, conversionTypeContext: ConversionTypeContext, ): IrExpression { - val referencedDeclaration = calleeReference.toResolvedCallableSymbol()?.unwrapCallRepresentative()?.fir + val referencedDeclaration = calleeReference?.toResolvedCallableSymbol()?.unwrapCallRepresentative()?.fir val dispatchReceiverType = referencedDeclaration?.dispatchReceiverType as? ConeClassLikeType diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 67d9a58c0ca..ccd861ceb2f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -704,7 +704,7 @@ class Fir2IrVisitor( internal fun convertToIrReceiverExpression( expression: FirExpression?, - calleeReference: FirReference, + calleeReference: FirReference?, callableReferenceAccess: FirCallableReferenceAccess? = null ): IrExpression? { return when (expression) { @@ -779,7 +779,7 @@ class Fir2IrVisitor( val incrementStatement = this[index + 1] if (incrementStatement !is FirVariableAssignment) return null - if (incrementStatement.lValue.toResolvedCallableSymbol() != variable) return null + if (incrementStatement.calleeReference?.toResolvedCallableSymbol() != variable) return null val origin = incrementStatement.getIrAssignmentOrigin() return if (origin == IrStatementOrigin.EQ) null else origin diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt index 7e3c571593b..9c9b9daefb6 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt @@ -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 if (firReceiver is FirNoReceiverExpression) { return null diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index a930a370fc4..9c470f05a0e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -213,7 +213,7 @@ class CallAndReferenceGenerator( 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 fir = calleeReference.resolvedSymbol.fir if (this is FirFunctionCall && fir is FirSimpleFunction && fir.origin == FirDeclarationOrigin.SamConstructor) { @@ -227,7 +227,7 @@ class CallAndReferenceGenerator( } private fun FirExpression.superQualifierSymbol(): IrClassSymbol? { - if (this !is FirQualifiedAccess) { + if (this !is FirQualifiedAccessExpression) { return null } val dispatchReceiverReference = calleeReference @@ -264,7 +264,7 @@ class CallAndReferenceGenerator( else -> null } - private val FirQualifiedAccess.dynamicOperator + private val FirQualifiedAccessExpression.dynamicOperator get() = when (calleeReference.source?.kind) { is KtFakeSourceElementKind.ArrayAccessNameReference -> when (calleeReference.resolved?.name) { OperatorNameConventions.SET -> IrDynamicOperator.EQ @@ -288,7 +288,7 @@ class CallAndReferenceGenerator( } private fun convertToIrCallForDynamic( - qualifiedAccess: FirQualifiedAccess, + qualifiedAccess: FirQualifiedAccessExpression, explicitReceiverExpression: IrExpression, type: IrType, calleeReference: FirReference, @@ -333,7 +333,7 @@ class CallAndReferenceGenerator( } fun convertToIrCall( - qualifiedAccess: FirQualifiedAccess, + qualifiedAccess: FirQualifiedAccessExpression, typeRef: FirTypeRef, explicitReceiverExpression: IrExpression?, annotationMode: Boolean = false, @@ -501,13 +501,15 @@ class CallAndReferenceGenerator( else -> generateErrorCallExpression(startOffset, endOffset, calleeReference) } - }.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment, convertedExplicitReceiver) + }.apply { + variableAssignment.unwrapLValue()?.let { applyReceivers(it, convertedExplicitReceiver) } + } } fun convertToIrSetCall(variableAssignment: FirVariableAssignment, explicitReceiverExpression: IrExpression?): IrExpression { try { val type = irBuiltIns.unitType - val calleeReference = variableAssignment.calleeReference + val calleeReference = variableAssignment.calleeReference ?: error("Reference not resolvable") val assignedValue = visitor.convertToIrExpression(variableAssignment.rValue) val firSymbol = calleeReference.toResolvedBaseSymbol() @@ -532,7 +534,8 @@ class CallAndReferenceGenerator( ) 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) { is IrFieldSymbol -> IrSetFieldImpl(startOffset, endOffset, symbol, type, origin).apply { value = assignedValue @@ -548,7 +551,7 @@ class CallAndReferenceGenerator( origin = origin, superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol() ).apply { - putContextReceiverArguments(variableAssignment) + putContextReceiverArguments(lValue) putValueArgument(0, assignedValue) } @@ -568,7 +571,7 @@ class CallAndReferenceGenerator( origin = origin, superQualifierSymbol = variableAssignment.dispatchReceiver.superQualifierSymbol() ).apply { - putValueArgument(putContextReceiverArguments(variableAssignment), assignedValue) + putValueArgument(putContextReceiverArguments(lValue), assignedValue) } backingField != null -> IrSetFieldImpl( @@ -600,7 +603,7 @@ class CallAndReferenceGenerator( else -> generateErrorCallExpression(startOffset, endOffset, calleeReference) } - }.applyTypeArguments(variableAssignment).applyReceivers(variableAssignment, explicitReceiverExpression) + }.applyTypeArguments(lValue).applyReceivers(lValue, explicitReceiverExpression) } catch (e: Throwable) { throw IllegalStateException( "Error while translating ${variableAssignment.render()} " + @@ -957,7 +960,7 @@ class CallAndReferenceGenerator( return this } - internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression { + internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccessExpression): IrExpression { if (this !is IrMemberAccessExpression<*>) return this val argumentsCount = access.typeArguments.size 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) - private fun FirQualifiedAccess.findIrDispatchReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = + private fun FirQualifiedAccessExpression.findIrDispatchReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = findIrReceiver(explicitReceiverExpression, isDispatch = true) - private fun FirQualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = + private fun FirQualifiedAccessExpression.findIrExtensionReceiver(explicitReceiverExpression: IrExpression?): IrExpression? = 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 if (firReceiver == explicitReceiver) { 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) { is IrMemberAccessExpression<*> -> { val ownerFunction = diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 6867a242a75..aeb9dd6381e 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -552,7 +552,7 @@ class ExpressionsConverter( } var result = firSelector - (firSelector as? FirQualifiedAccess)?.let { + (firSelector as? FirQualifiedAccessExpression)?.let { if (isSafe) { @OptIn(FirImplementationDetail::class) 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 @@ -663,7 +663,7 @@ class ExpressionsConverter( ) } - val builder: FirQualifiedAccessBuilder = if (hasArguments) { + val builder: FirQualifiedAccessExpressionBuilder = if (hasArguments) { val builder = if (isImplicitInvoke) FirImplicitInvokeCallBuilder() else FirFunctionCallBuilder() builder.apply { this.source = source @@ -682,7 +682,7 @@ class ExpressionsConverter( return builder.apply { this.explicitReceiver = explicitReceiver typeArguments += firTypeArguments - }.build() as FirExpression + }.build() } /** diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index cfc1a6375cf..1a8bb91c8f4 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -2545,7 +2545,7 @@ open class RawFirBuilder( val source = expression.toFirSourceElement() 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 { this.source = source this.calleeReference = calleeReference @@ -2603,7 +2603,7 @@ open class RawFirBuilder( } val firSelector = selector.toFirExpression("Incorrect selector expression") - if (firSelector is FirQualifiedAccess) { + if (firSelector is FirQualifiedAccessExpression) { if (expression is KtSafeQualifiedExpression) { @OptIn(FirImplementationDetail::class) firSelector.replaceSource(expression.toFirSourceElement(KtFakeSourceElementKind.DesugaredSafeCallExpression)) diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index 9a554e0d126..b12eb91afac 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -11,15 +11,10 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder -import org.jetbrains.kotlin.fir.expressions.FirErrorExpression -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.* import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.isCatchParameter 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.render import org.jetbrains.kotlin.fir.renderer.FirRenderer @@ -84,15 +79,15 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { errorExpression.psi?.let { println(it) } } - override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) { - val calleeReference = qualifiedAccess.calleeReference + override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: FirElement) { + val calleeReference = qualifiedAccessExpression.calleeReference if (calleeReference.isError()) { errorReferences++ println((calleeReference as FirDiagnosticHolder).diagnostic.reason) } else { normalReferences++ } - visitStatement(qualifiedAccess, data) + visitStatement(qualifiedAccessExpression, data) } override fun visitExpression(expression: FirExpression, data: FirElement) { diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index e21ff366f58..b02aa5ea2d7 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -21,9 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.expressions.* 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.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirErrorTypeRef @@ -558,9 +556,12 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte resultInitializer, FirOperation.ASSIGN, resultInitializer.annotations, - null, - convert - ) + null + ) { + // 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) { statements += assignment.statements @@ -695,6 +696,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte * } * */ + @OptIn(FirContractViolation::class) private fun generateIncrementOrDecrementBlockForQualifiedAccess( wholeExpression: T, operationReference: T?, @@ -708,7 +710,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte convert, receiverForOperation.toFirSourceElement(), ) { qualifiedFir -> - val receiverFir = (qualifiedFir as? FirQualifiedAccess)?.explicitReceiver ?: buildErrorExpression { + val receiverFir = (qualifiedFir as? FirQualifiedAccessExpression)?.explicitReceiver ?: buildErrorExpression { source = receiverForOperation.toFirSourceElement() diagnostic = ConeSimpleDiagnostic("Qualified expression without selector", DiagnosticKind.Syntax) } @@ -724,7 +726,8 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte initializer = receiverFir, ).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) } } @@ -735,16 +738,15 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements statements += buildVariableAssignment { source = desugaredSource + lValue = buildDesugaredAssignmentValueReferenceExpression { + expressionRef = FirExpressionRef().apply { bind(firArgument) } + source = firArgument.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement) + } rValue = if (prefix) { generateResolvedAccessExpression(source, resultVar) } else { 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(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 + @OptIn(FirContractViolation::class) fun T?.generateAssignment( baseSource: KtSourceElement?, arrayAccessSource: KtSourceElement?, @@ -1010,10 +974,18 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte } } + val assignmentLValue = unwrappedLhs.convert() return buildVariableAssignment { source = baseSource + lValue = if (baseSource?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement) { + buildDesugaredAssignmentValueReferenceExpression { + expressionRef = FirExpressionRef().apply { bind(assignmentLValue) } + source = assignmentLValue.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement) + } + } else { + assignmentLValue + } rValue = rhsExpression - calleeReference = initializeLValue(unwrappedLhs) { convert() as? FirQualifiedAccess } this.annotations += annotations } } @@ -1025,13 +997,12 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte rhsExpression: FirExpression, annotations: List ): FirSafeCallExpression { - val nestedAccess = safeCallNonAssignment.selector as FirQualifiedAccess + val nestedAccess = safeCallNonAssignment.selector as FirQualifiedAccessExpression val assignment = buildVariableAssignment { source = baseSource + lValue = nestedAccess rValue = rhsExpression - calleeReference = nestedAccess.calleeReference - explicitReceiver = safeCallNonAssignment.checkedSubjectRef.value this.annotations += annotations } @@ -1228,10 +1199,10 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte } protected fun convertFirSelector( - firSelector: FirQualifiedAccess, + firSelector: FirQualifiedAccessExpression, source: KtSourceElement?, receiver: FirExpression - ): FirQualifiedAccess { + ): FirQualifiedAccessExpression { return if (firSelector is FirImplicitInvokeCall) { buildImplicitInvokeCall { this.source = source diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 97143e357b0..78265a2702d 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -531,7 +531,7 @@ private fun FirExpression.checkReceiver(name: String?): Boolean { // this = .f(...) // receiver = // Returns safe call ?.{ f(...) } -fun FirQualifiedAccess.createSafeCall(receiver: FirExpression, source: KtSourceElement): FirSafeCallExpression { +fun FirQualifiedAccessExpression.createSafeCall(receiver: FirExpression, source: KtSourceElement): FirSafeCallExpression { val checkedSafeCallSubject = buildCheckedSafeCallSubject { @OptIn(FirContractViolation::class) this.originalReceiverRef = FirExpressionRef().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(...)` // Other patterns remain unchanged fun FirExpression.pullUpSafeCallIfNecessary(): FirExpression { - if (this !is FirQualifiedAccess) return this + if (this !is FirQualifiedAccessExpression) return this val safeCall = explicitReceiver as? FirSafeCallExpression ?: return this val safeCallSelector = safeCall.selector as? FirExpression ?: return this diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 7e8bf628118..ba75414de7d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -121,8 +121,8 @@ class FirCallResolver( ) /** WARNING: This function is public for the analysis API and should only be used there. */ - fun collectAllCandidates( - qualifiedAccess: T, + fun collectAllCandidates( + qualifiedAccess: FirQualifiedAccessExpression, name: Name, containingDeclarations: List = transformer.components.containingDeclarations, resolutionContext: ResolutionContext = transformer.resolutionContext @@ -134,21 +134,22 @@ class FirCallResolver( return collector.allCandidates.map { OverloadCandidate(it, isInBestCandidates = it in result.candidates) } } - private fun collectCandidates( - qualifiedAccess: T, + private fun collectCandidates( + qualifiedAccess: FirQualifiedAccessExpression, name: Name, forceCallKind: CallKind? = null, origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular, containingDeclarations: List = transformer.components.containingDeclarations, resolutionContext: ResolutionContext = transformer.resolutionContext, - collector: CandidateCollector? = null + collector: CandidateCollector? = null, + callSite: FirElement = qualifiedAccess, ): ResolutionResult { val explicitReceiver = qualifiedAccess.explicitReceiver val argumentList = (qualifiedAccess as? FirFunctionCall)?.argumentList ?: FirEmptyArgumentList val typeArguments = (qualifiedAccess as? FirFunctionCall)?.typeArguments.orEmpty() val info = CallInfo( - qualifiedAccess, + callSite, forceCallKind ?: if (qualifiedAccess is FirFunctionCall) CallKind.Function else CallKind.VariableAccess, name, explicitReceiver, @@ -188,8 +189,12 @@ class FirCallResolver( return ResolutionResult(info, result.currentApplicability, reducedCandidates) } - fun resolveVariableAccessAndSelectCandidate(qualifiedAccess: T, isUsedAsReceiver: Boolean): FirStatement { - return resolveVariableAccessAndSelectCandidateImpl(qualifiedAccess, isUsedAsReceiver) { true } + fun resolveVariableAccessAndSelectCandidate( + qualifiedAccess: FirQualifiedAccessExpression, + isUsedAsReceiver: Boolean, + callSite: FirElement, + ): FirStatement { + return resolveVariableAccessAndSelectCandidateImpl(qualifiedAccess, isUsedAsReceiver, callSite) { true } } fun resolveOnlyEnumOrQualifierAccessAndSelectCandidate( @@ -202,19 +207,20 @@ class FirCallResolver( } } - private fun resolveVariableAccessAndSelectCandidateImpl( - qualifiedAccess: T, + private fun resolveVariableAccessAndSelectCandidateImpl( + qualifiedAccess: FirQualifiedAccessExpression, isUsedAsReceiver: Boolean, - acceptCandidates: (Collection) -> Boolean + callSite: FirElement = qualifiedAccess, + acceptCandidates: (Collection) -> Boolean, ): FirStatement { val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess @Suppress("NAME_SHADOWING") - val qualifiedAccess = transformer.transformExplicitReceiver(qualifiedAccess) + val qualifiedAccess = qualifiedAccess.let(transformer::transformExplicitReceiver) val nonFatalDiagnosticFromExpression = (qualifiedAccess as? FirPropertyAccessExpression)?.nonFatalDiagnostics 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 @@ -327,7 +333,7 @@ class FirCallResolver( replaceContextReceiverArguments(candidate.contextReceiverArguments()) } } - if (qualifiedAccess is FirExpression) transformer.storeTypeFromCallee(qualifiedAccess) + transformer.storeTypeFromCallee(qualifiedAccess, isLhsOfAssignment = callSite is FirVariableAssignment) return qualifiedAccess } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt index 6a5457893a1..21d825e20c9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.fir.resolve 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.resolve.ResolutionMode.Companion.prettyString import org.jetbrains.kotlin.fir.types.* 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 fun FirTypeRef?.prettyString(): String { if (this == null) return "null" @@ -98,6 +102,7 @@ sealed class ResolutionMode { fun ResolutionMode.expectedType(components: BodyResolveComponents, allowFromCast: Boolean = false): FirTypeRef? = when (this) { is ResolutionMode.WithExpectedType -> expectedTypeRef is ResolutionMode.ContextIndependent, + is ResolutionMode.AssignmentLValue, is ResolutionMode.ReceiverResolution -> components.noExpectedType is ResolutionMode.WithExpectedTypeFromCast -> expectedTypeRef.takeIf { allowFromCast } is ResolutionMode.WithSuggestedType -> suggestedTypeRef diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 137d6a419e4..e2329a6e616 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -25,10 +25,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression -import org.jetbrains.kotlin.fir.references.FirErrorNamedReference -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.references.* import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.FirPropertyWithExplicitBackingFieldResolvedNamedReference @@ -289,24 +286,29 @@ private fun FirPropertyWithExplicitBackingFieldResolvedNamedReference.getNarrowe } fun 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 -> buildErrorTypeRef { source = access.source?.fakeElement(KtFakeSourceElementKind.ErrorTypeRef) - diagnostic = ConeStubDiagnostic(newCallee.diagnostic) + diagnostic = ConeStubDiagnostic(calleeReference.diagnostic) } is FirNamedReferenceWithCandidate -> { - typeFromSymbol(newCallee.candidateSymbol, false) + typeFromSymbol(calleeReference.candidateSymbol, false) } is FirPropertyWithExplicitBackingFieldResolvedNamedReference -> { - val symbol = newCallee.getNarrowedDownSymbol(session) + val symbol = calleeReference.getNarrowedDownSymbol(session) typeFromSymbol(symbol, false) } is FirResolvedNamedReference -> { - typeFromSymbol(newCallee.resolvedSymbol, false) + typeFromSymbol(calleeReference.resolvedSymbol, false) } is FirThisReference -> { - val labelName = newCallee.labelName + val labelName = calleeReference.labelName val implicitReceiver = implicitReceiverStack[labelName] buildResolvedTypeRef { source = null @@ -319,19 +321,19 @@ fun BodyResolveComponents.typeFromCallee(access: T): FirReso } } is FirSuperReference -> { - val labelName = newCallee.labelName + val labelName = calleeReference.labelName val implicitReceiver = if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue else implicitReceiverStack.lastDispatchReceiver() val resolvedTypeRef = - newCallee.superTypeRef as? FirResolvedTypeRef + calleeReference.superTypeRef as? FirResolvedTypeRef ?: implicitReceiver?.boundSymbol?.fir?.superTypeRefs?.singleOrNull() as? FirResolvedTypeRef resolvedTypeRef ?: buildErrorTypeRef { - source = newCallee.source + source = calleeReference.source 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 originalExpression.typeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef) } + private fun BodyResolveComponents.transformExpressionUsingSmartcastInfo( expression: T, stability: PropertyStability, @@ -528,22 +531,15 @@ fun FirAnnotation.getCorrespondingClassSymbolOrNull(session: FirSession): FirReg } } -fun BodyResolveComponents.initialTypeOfCandidate( - candidate: Candidate, - call: T -): ConeKotlinType where T : FirResolvable, T : FirStatement { - return initialTypeOfCandidate(candidate, typeFromCallee(call)) -} - fun BodyResolveComponents.initialTypeOfCandidate(candidate: Candidate): ConeKotlinType { 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 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? = diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt index e1b76afd1cf..7d97191c834 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/SuperCalls.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull 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.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.scope @@ -31,7 +31,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull fun BodyResolveComponents.findTypesForSuperCandidates( superTypeRefs: List, - containingCall: FirQualifiedAccess, + containingCall: FirQualifiedAccessExpression, ): List { val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type } val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 2e026e929ba..a7c72af5f2a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -794,9 +794,17 @@ abstract class FirDataFlowAnalyzer( graphBuilder.exitStringConcatenationCall(call).mergeIncomingFlow() } - private fun FirQualifiedAccess.orderedArguments(callee: FirFunction): Array? { - val receiver = extensionReceiver.takeIf { it != FirNoReceiverExpression } - ?: dispatchReceiver.takeIf { it != FirNoReceiverExpression } + private fun FirStatement.orderedArguments(callee: FirFunction): Array? { + fun FirQualifiedAccessExpression.firstReceiver(): FirExpression? = + (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) { is FirFunctionCall -> { 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) { is FirFunctionCall -> qualifiedAccess.toResolvedCallableSymbol()?.fir as? FirSimpleFunction is FirQualifiedAccessExpression -> qualifiedAccess.calleeReference.toResolvedPropertySymbol()?.fir?.getter - is FirVariableAssignment -> qualifiedAccess.lValue.toResolvedPropertySymbol()?.fir?.setter + is FirVariableAssignment -> qualifiedAccess.calleeReference?.toResolvedPropertySymbol()?.fir?.setter else -> null } ?: return @@ -837,7 +845,7 @@ abstract class FirDataFlowAnalyzer( if (argumentVariables.all { it == null }) return val typeParameters = callee.typeParameters - val substitutor = if (typeParameters.isNotEmpty()) { + val substitutor = if (typeParameters.isNotEmpty() && qualifiedAccess is FirQualifiedAccessExpression) { @Suppress("UNCHECKED_CAST") val substitutionFromArguments = typeParameters.zip(qualifiedAccess.typeArguments).map { (typeParameterRef, typeArgument) -> typeParameterRef.symbol to typeArgument.toConeTypeProjection().type @@ -870,15 +878,15 @@ abstract class FirDataFlowAnalyzer( fun exitLocalVariableDeclaration(variable: FirProperty, hadExplicitType: Boolean) { graphBuilder.exitVariableDeclaration(variable).mergeIncomingFlow { flow -> val initializer = variable.initializer ?: return@mergeIncomingFlow - exitVariableInitialization(flow, initializer, variable, assignment = null, hadExplicitType) + exitVariableInitialization(flow, initializer, variable, assignmentLhs = null, hadExplicitType) } } fun exitVariableAssignment(assignment: FirVariableAssignment) { 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) { - exitVariableInitialization(flow, assignment.rValue, property, assignment, hasExplicitType = false) + exitVariableInitialization(flow, assignment.rValue, property, assignment.lValue, hasExplicitType = false) } else { // TODO: add unstable smartcast for non-local var val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment) @@ -894,16 +902,16 @@ abstract class FirDataFlowAnalyzer( flow: MutableFlow, initializer: FirExpression, property: FirProperty, - assignment: FirVariableAssignment?, + assignmentLhs: FirExpression?, hasExplicitType: Boolean, ) { val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias( flow, property.symbol, - assignment ?: property, + assignmentLhs ?: property, if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR ) - val isAssignment = assignment != null + val isAssignment = assignmentLhs != null if (isAssignment) { logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex()) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirLocalVariableAssignmentAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirLocalVariableAssignmentAnalyzer.kt index d3a821d298b..ce9f87d9c57 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirLocalVariableAssignmentAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirLocalVariableAssignmentAnalyzer.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol 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.name.Name @@ -380,7 +381,7 @@ internal class FirLocalVariableAssignmentAnalyzer { override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MiniCfgData) { visitElement(variableAssignment, data) if (variableAssignment.explicitReceiver != null) return - data.recordAssignment(variableAssignment.lValue) + variableAssignment.calleeReference?.let { data.recordAssignment(it) } } override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement, data: MiniCfgData) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PreliminaryLoopVisitor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PreliminaryLoopVisitor.kt index 43279a8c426..d6ba249e350 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PreliminaryLoopVisitor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/PreliminaryLoopVisitor.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* 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.setMultimapOf import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -48,7 +49,7 @@ class PreliminaryLoopVisitor { // property assignment, the smart cast will be unstable anyway. if (variableAssignment.explicitReceiver != null) return - val reference = variableAssignment.lValue as? FirNamedReference + val reference = variableAssignment.calleeReference as? FirNamedReference if (reference != null) { requireNotNull(data) reassignedVariablesPerElement.put(data, reference.name) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt index e8de535c77f..29376612432 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/ConstraintSystemCompleter.kt @@ -503,7 +503,7 @@ fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, proc } is FirVariableAssignment -> { - processCandidateIfApplicable(processor, processBlocks) + (lValue as? FirResolvable)?.processCandidateIfApplicable(processor, processBlocks) rValue.processAllContainingCallCandidates(processBlocks, processor) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 78449608243..15117becc1a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -81,7 +81,8 @@ class FirCallCompleter( ) private fun completeCall( - call: T, expectedTypeRef: FirTypeRef?, + call: T, + expectedTypeRef: FirTypeRef?, mayBeCoercionToUnitApplied: Boolean, expectedTypeMismatchIsReportedInChecker: Boolean, isFromCast: Boolean, @@ -90,14 +91,10 @@ class FirCallCompleter( where T : FirResolvable, T : FirStatement { val typeRef = components.typeFromCallee(call) - if (call is FirVariableAssignment) { - call.replaceLValueTypeRef(typeRef) - } - val reference = call.calleeReference as? FirNamedReferenceWithCandidate ?: return CompletionResult(call, true) val candidate = reference.candidate - val initialType = components.initialTypeOfCandidate(candidate, call) + val initialType = typeRef.initialTypeOfCandidate(candidate) if (call is FirExpression) { val resolvedTypeRef = typeRef.resolvedTypeFromPrototype(initialType) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 67fd9745e82..1663af9c3fd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -83,7 +83,7 @@ class FirCallCompletionResultsWriterTransformer( } } - private fun prepareQualifiedTransform( + private fun prepareQualifiedTransform( qualifiedAccessExpression: T, calleeReference: FirNamedReferenceWithCandidate ): T { val subCandidate = calleeReference.candidate @@ -129,7 +129,7 @@ class FirCallCompletionResultsWriterTransformer( extensionReceiver = extensionReceiver.transformSingle(integerOperatorApproximator, expectedExtensionReceiverType) } - qualifiedAccessExpression.apply { + (qualifiedAccessExpression as? FirQualifiedAccessExpression)?.apply { replaceCalleeReference(calleeReference.toResolvedReference()) replaceDispatchReceiver(dispatchReceiver) replaceExtensionReceiver(extensionReceiver) @@ -146,11 +146,7 @@ class FirCallCompletionResultsWriterTransformer( qualifiedAccessExpression.replaceNonFatalDiagnostics(nonFatalDiagnostics) } - if (qualifiedAccessExpression is FirQualifiedAccessExpression) { - qualifiedAccessExpression.replaceTypeRef(typeRef) - } else if (qualifiedAccessExpression is FirVariableAssignment) { - qualifiedAccessExpression.replaceLValueTypeRef(typeRef) - } + qualifiedAccessExpression.replaceTypeRef(typeRef) if (declaration !is FirErrorFunction) { 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 { return smartCastExpression.transformOriginalExpression(this, data) } @@ -509,7 +486,7 @@ class FirCallCompletionResultsWriterTransformer( } private fun computeTypeArguments( - access: FirQualifiedAccess, + access: FirQualifiedAccessExpression, candidate: Candidate ): List { val typeArguments = computeTypeArgumentTypes(candidate) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt index 08ade393beb..630f86b450b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransformerDispatcher.kt @@ -181,6 +181,13 @@ abstract class FirAbstractBodyResolveTransformerDispatcher( return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data) } + override fun transformDesugaredAssignmentValueReferenceExpression( + desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, + data: ResolutionMode + ): FirStatement { + return expressionsTransformer.transformDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression, data) + } + override fun transformVariableAssignment( variableAssignment: FirVariableAssignment, data: ResolutionMode diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index ffc0570acca..0e58bb542b5 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -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.transformers.FirCallCompletionResultsWriterTransformer 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.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.types.constructStarProjectedType @@ -317,7 +316,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve .transformSingle(components.integerLiteralAndOperatorApproximationTransformer, null) // 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 if (calleeReference is FirNamedReferenceWithCandidate) { val system = calleeReference.candidate.system @@ -736,7 +735,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve transformAnonymousFunctionWithExpectedType(anonymousFunction, data.expectedTypeRef, data) is ResolutionMode.WithSuggestedType -> transformAnonymousFunctionWithExpectedType(anonymousFunction, data.suggestedTypeRef, data) - is ResolutionMode.ContextIndependent, is ResolutionMode.ReceiverResolution -> + is ResolutionMode.ContextIndependent, is ResolutionMode.AssignmentLValue, is ResolutionMode.ReceiverResolution -> transformAnonymousFunctionWithExpectedType(anonymousFunction, buildImplicitTypeRef(), data) is ResolutionMode.WithStatus, is ResolutionMode.WithExpectedTypeFromCast -> throw AssertionError("Should not be here in WithStatus/WithExpectedTypeFromCast mode") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 33b2dd6eb68..b6a997c7752 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference 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.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.* @@ -133,7 +132,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT transformSuperReceiver( callee, qualifiedAccessExpression, - containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.selector as? FirQualifiedAccess + containingSafeCallExpression?.takeIf { qualifiedAccessExpression == it.receiver }?.selector as? FirQualifiedAccessExpression ) } is FirDelegateFieldReference -> { @@ -144,12 +143,19 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT is FirResolvedNamedReference, is FirErrorNamedReference -> { if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) { - storeTypeFromCallee(qualifiedAccessExpression) + storeTypeFromCallee(qualifiedAccessExpression, isLhsOfAssignment = false) } qualifiedAccessExpression } 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), // so candidate existence must be checked before calling completion if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) { @@ -162,22 +168,24 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT } } } - when (result) { - is FirQualifiedAccessExpression -> { - dataFlowAnalyzer.exitQualifiedAccessExpression(result) - result = components.transformQualifiedAccessUsingSmartcastInfo(result) - if (result is FirSmartCastExpression) { - dataFlowAnalyzer.exitSmartCastExpression(result) + if (data !is ResolutionMode.AssignmentLValue) { + when (result) { + is FirQualifiedAccessExpression -> { + dataFlowAnalyzer.exitQualifiedAccessExpression(result) + result = components.transformQualifiedAccessUsingSmartcastInfo(result) + if (result is FirSmartCastExpression) { + dataFlowAnalyzer.exitSmartCastExpression(result) + } + } + is FirResolvedQualifier -> { + dataFlowAnalyzer.exitResolvedQualifierNode(result) } - } - is FirResolvedQualifier -> { - dataFlowAnalyzer.exitResolvedQualifierNode(result) } } return result } - fun transformExplicitReceiver(qualifiedAccessExpression: Q): Q { + fun transformExplicitReceiver(qualifiedAccessExpression: Q): Q { val explicitReceiver = qualifiedAccessExpression.explicitReceiver as? FirQualifiedAccessExpression if (explicitReceiver is FirQualifiedAccessExpression) { val superReference = explicitReceiver.calleeReference as? FirSuperReference @@ -208,14 +216,15 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT protected open fun resolveQualifiedAccessAndSelectCandidate( qualifiedAccessExpression: FirQualifiedAccessExpression, isUsedAsReceiver: Boolean, + callSite: FirElement, ): FirStatement { - return callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver) + return callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver, callSite) } fun transformSuperReceiver( superReference: FirSuperReference, superReferenceContainer: FirQualifiedAccessExpression, - containingCall: FirQualifiedAccess? + containingCall: FirQualifiedAccessExpression? ): FirQualifiedAccessExpression { val labelName = superReference.labelName val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver() @@ -385,7 +394,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT (calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) && functionCall.resultType is FirImplicitTypeRef ) { - storeTypeFromCallee(functionCall) + storeTypeFromCallee(functionCall, isLhsOfAssignment = false) } if (calleeReference is FirNamedReferenceWithCandidate) return functionCall if (calleeReference !is FirSimpleNamedReference) { @@ -413,7 +422,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT } val resultExpression = callResolver.resolveCallAndSelectCandidate(withTransformedArguments) val resultExplicitReceiver = resultExpression.explicitReceiver?.unwrapSmartcastExpression() - if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) { + if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccessExpression) { // name.invoke() case callCompleter.completeCall(resultExplicitReceiver, noExpectedType) } @@ -549,6 +558,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT } } + @OptIn(FirContractViolation::class) override fun transformAssignmentOperatorStatement( assignmentOperatorStatement: FirAssignmentOperatorStatement, data: ResolutionMode @@ -612,32 +622,18 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT expectedTypeMismatchIsReportedInChecker = true ) dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true) + + val unwrappedLeftArgument = leftArgument.unwrapSmartcastExpression() + val assignmentLeftArgument = buildDesugaredAssignmentValueReferenceExpression { + expressionRef = FirExpressionRef().apply { bind(unwrappedLeftArgument) } + source = leftArgument.source?.fakeElement(KtFakeSourceElementKind.DesugaredCompoundAssignment) + }.also { storeTypeFromCallee(it) } + val assignment = buildVariableAssignment { source = assignmentOperatorStatement.source + lValue = assignmentLeftArgument 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 } return assignment.transform(transformer, ResolutionMode.ContextIndependent) @@ -863,49 +859,66 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT .also { it.resultType = booleanType } } + override fun transformDesugaredAssignmentValueReferenceExpression( + desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, + data: ResolutionMode + ): FirStatement { + storeTypeFromCallee(desugaredAssignmentValueReferenceExpression) + return desugaredAssignmentValueReferenceExpression + } + override fun transformVariableAssignment( variableAssignment: FirVariableAssignment, data: ResolutionMode, ): FirStatement = whileAnalysing(session, variableAssignment) { - // val resolvedAssignment = transformCallee(variableAssignment) 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 altererNames = alteredAssignments.map { it.second::class.qualifiedName } - val errorReference = buildResolvedErrorReference { - source = resolvedReference.source - name = resolvedReference.name - resolvedSymbol = resolvedReference.resolvedSymbol - diagnostic = ConeAmbiguousAlteredAssign(altererNames) - } - completeAssignment.replaceCalleeReference(errorReference) + val isDesugaredIncrementDecrement = variableAssignment.source?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement + + // Expressions like `++a` are desugared into `a = a.inc()` where the LHS is a FirDesugaredAssignmentValueReferenceExpression + // that's pointing to the not yet resolved `a` on the RHS. For the resolution to work, the RHS must therefore be resolved first. + if (isDesugaredIncrementDecrement) { + variableAssignment.transformRValue(transformer, ResolutionMode.ContextIndependent) + } + + 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, - withExpectedType(variableAssignment.lValueTypeRef, expectedTypeMismatchIsReportedInChecker = true), + withExpectedType(variableAssignment.lValue.typeRef, expectedTypeMismatchIsReportedInChecker = true), ) } else { - // This can happen in erroneous code only - resolvedAssignment + variableAssignment } + (result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) } + return result } @@ -1517,12 +1530,34 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT // ------------------------------------------------------------------------------------------------ - internal fun storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { + internal fun storeTypeFromCallee(access: FirQualifiedAccessExpression, isLhsOfAssignment: Boolean) { val typeFromCallee = components.typeFromCallee(access) access.resultType = typeFromCallee.withReplacedConeType( - session.typeApproximator.approximateToSuperType( - typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference - ) + if (isLhsOfAssignment) { + 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) + } + } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt index b15929473b7..20eca46498c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt @@ -5,6 +5,7 @@ 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.declarations.* import org.jetbrains.kotlin.fir.expressions.* @@ -168,6 +169,7 @@ private class FirExpressionsResolveTransformerForSpecificAnnotations( override fun resolveQualifiedAccessAndSelectCandidate( qualifiedAccessExpression: FirQualifiedAccessExpression, isUsedAsReceiver: Boolean, + callSite: FirElement, ): FirStatement { return callResolver.resolveOnlyEnumOrQualifierAccessAndSelectCandidate(qualifiedAccessExpression, isUsedAsReceiver) } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt index 2f46f6fb723..c65598abd78 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/VariableStorageImpl.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.fir.expressions.explicitReceiver @OptIn(DfaInternals::class) 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 { - 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? return Identifier( symbol, @@ -104,10 +105,10 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() { private fun createReal(flow: Flow, identifier: Identifier, originalFir: FirElement, stability: PropertyStability): RealVariable { val receiver: FirExpression? val isThisReference: Boolean - val expression: FirQualifiedAccess? = when (originalFir) { + val expression: FirQualifiedAccessExpression? = when (originalFir) { is FirQualifiedAccessExpression -> originalFir is FirWhenSubjectExpression -> originalFir.whenRef.value.subject as? FirQualifiedAccessExpression - is FirVariableAssignment -> originalFir + is FirVariableAssignment -> originalFir.unwrapLValue() else -> null } @@ -162,7 +163,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() { property.receiverParameter != null -> PropertyStability.PROPERTY_WITH_GETTER property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER 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()?.fullyExpandedType(session) ?: return null val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null when (val receiverFir = receiverSymbol.fir) { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt index 3a69bc7b8bf..02c0d676dc3 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/CFGNodeRenderer.kt @@ -5,9 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.dfa.cfg -import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop -import org.jetbrains.kotlin.fir.expressions.FirLoop -import org.jetbrains.kotlin.fir.expressions.FirWhileLoop +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.renderer.FirCallNoArgumentsRenderer @@ -55,7 +53,7 @@ fun CFGNode<*>.render(): String = 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 DelegatedConstructorCallNode -> "Delegated constructor call: ${CfgRenderer.renderElementAsString(fir)}" is StringConcatenationCallNode -> "String concatenation call: ${CfgRenderer.renderElementAsString(fir)}" diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt index 1c53e990744..3b03053cfa0 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/util.kt @@ -40,10 +40,12 @@ val FirExpression.coneType: ConeKotlinType val FirElement.symbol: FirBasedSymbol<*>? get() = when (this) { is FirResolvable -> symbol + is FirVariableAssignment -> unwrapLValue()?.symbol is FirDeclaration -> symbol is FirWhenSubjectExpression -> whenRef.value.subject?.symbol is FirSafeCallExpression -> selector.symbol is FirSmartCastExpression -> originalExpression.symbol + is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.symbol else -> null }?.takeIf { (this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression || diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt index c5eda0609a9..33e74280032 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt @@ -138,10 +138,6 @@ object ConeVariableExpectedError : ConeDiagnostic { 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 ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCallableReferenceAccess.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCallableReferenceAccess.kt index c60559a6902..6f09bacf592 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCallableReferenceAccess.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirCallableReferenceAccess.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List @@ -28,6 +27,7 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() { abstract override val explicitReceiver: FirExpression? abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract override val calleeReference: FirNamedReference abstract val hasQuestionMarkAtLHS: Boolean @@ -37,9 +37,6 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformCallableReferenceAccess(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -54,6 +51,9 @@ abstract class FirCallableReferenceAccess : FirQualifiedAccessExpression() { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference) abstract override fun replaceCalleeReference(newCalleeReference: FirReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirComponentCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirComponentCall.kt index 005b1a5272a..4e6e679e6be 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirComponentCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirComponentCall.kt @@ -20,13 +20,13 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirComponentCall : FirFunctionCall() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List abstract override val typeArguments: List abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract override val argumentList: FirArgumentList abstract override val calleeReference: FirNamedReference abstract override val origin: FirFunctionCallOrigin @@ -39,9 +39,6 @@ abstract class FirComponentCall : FirFunctionCall() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformComponentCall(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -54,6 +51,9 @@ abstract class FirComponentCall : FirFunctionCall() { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirDesugaredAssignmentValueReferenceExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirDesugaredAssignmentValueReferenceExpression.kt new file mode 100644 index 00000000000..57892af1af7 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirDesugaredAssignmentValueReferenceExpression.kt @@ -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 + abstract val expressionRef: FirExpressionRef + + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitDesugaredAssignmentValueReferenceExpression(this, data) + + @Suppress("UNCHECKED_CAST") + override fun transform(transformer: FirTransformer, data: D): E = + transformer.transformDesugaredAssignmentValueReferenceExpression(this, data) as E + + abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + + abstract override fun replaceAnnotations(newAnnotations: List) + + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirDesugaredAssignmentValueReferenceExpression +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirFunctionCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirFunctionCall.kt index 9ba1f59bffc..edb7e79dd2c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirFunctionCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirFunctionCall.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List @@ -28,6 +27,7 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall { abstract override val explicitReceiver: FirExpression? abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract override val argumentList: FirArgumentList abstract override val calleeReference: FirNamedReference abstract val origin: FirFunctionCallOrigin @@ -38,9 +38,6 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformFunctionCall(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -55,6 +52,9 @@ abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract fun replaceCalleeReference(newCalleeReference: FirNamedReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirImplicitInvokeCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirImplicitInvokeCall.kt index 81ea2cfb0f6..15a37340e1d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirImplicitInvokeCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirImplicitInvokeCall.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirImplicitInvokeCall : FirFunctionCall() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List @@ -28,6 +27,7 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() { abstract override val explicitReceiver: FirExpression? abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract override val argumentList: FirArgumentList abstract override val calleeReference: FirNamedReference abstract override val origin: FirFunctionCallOrigin @@ -38,9 +38,6 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformImplicitInvokeCall(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -55,6 +52,9 @@ abstract class FirImplicitInvokeCall : FirFunctionCall() { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirIntegerLiteralOperatorCall.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirIntegerLiteralOperatorCall.kt index 35dbd663802..eeab12024c6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirIntegerLiteralOperatorCall.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirIntegerLiteralOperatorCall.kt @@ -20,12 +20,12 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List abstract override val typeArguments: List abstract override val explicitReceiver: FirExpression? + abstract override val source: KtSourceElement? abstract override val argumentList: FirArgumentList abstract override val calleeReference: FirNamedReference abstract override val origin: FirFunctionCallOrigin @@ -38,9 +38,6 @@ abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformIntegerLiteralOperatorCall(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -51,6 +48,9 @@ abstract class FirIntegerLiteralOperatorCall : FirFunctionCall() { abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract override fun replaceArgumentList(newArgumentList: FirArgumentList) abstract override fun replaceCalleeReference(newCalleeReference: FirNamedReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirPropertyAccessExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirPropertyAccessExpression.kt index ad6337fb118..bc562f648a8 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirPropertyAccessExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirPropertyAccessExpression.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val calleeReference: FirReference @@ -29,6 +28,7 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() { abstract override val explicitReceiver: FirExpression? abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract val nonFatalDiagnostics: List override fun accept(visitor: FirVisitor, data: D): R = visitor.visitPropertyAccessExpression(this, data) @@ -37,9 +37,6 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformPropertyAccessExpression(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -56,6 +53,9 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract fun replaceNonFatalDiagnostics(newNonFatalDiagnostics: List) abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirPropertyAccessExpression diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccess.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccess.kt deleted file mode 100644 index 43adb950614..00000000000 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccess.kt +++ /dev/null @@ -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 - override val contextReceiverArguments: List - val typeArguments: List - val explicitReceiver: FirExpression? - val dispatchReceiver: FirExpression - val extensionReceiver: FirExpression - override val source: KtSourceElement? - - override fun accept(visitor: FirVisitor, data: D): R = visitor.visitQualifiedAccess(this, data) - - @Suppress("UNCHECKED_CAST") - override fun transform(transformer: FirTransformer, data: D): E = - transformer.transformQualifiedAccess(this, data) as E - - override fun replaceCalleeReference(newCalleeReference: FirReference) - - override fun replaceAnnotations(newAnnotations: List) - - override fun replaceContextReceiverArguments(newContextReceiverArguments: List) - - fun replaceTypeArguments(newTypeArguments: List) - - fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) - - fun replaceDispatchReceiver(newDispatchReceiver: FirExpression) - - fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) - - @FirImplementationDetail - fun replaceSource(newSource: KtSourceElement?) - - override fun transformCalleeReference(transformer: FirTransformer, data: D): FirQualifiedAccess - - override fun transformAnnotations(transformer: FirTransformer, data: D): FirQualifiedAccess - - fun transformTypeArguments(transformer: FirTransformer, data: D): FirQualifiedAccess - - fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirQualifiedAccess -} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccessExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccessExpression.kt index c79423f1a90..52f29a5507c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccessExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirQualifiedAccessExpression.kt @@ -18,16 +18,16 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail * DO NOT MODIFY IT MANUALLY */ -abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAccess { - abstract override val source: KtSourceElement? +abstract class FirQualifiedAccessExpression : FirExpression(), FirResolvable, FirContextReceiverArgumentListOwner { abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val calleeReference: FirReference abstract override val contextReceiverArguments: List - abstract override val typeArguments: List - abstract override val explicitReceiver: FirExpression? - abstract override val dispatchReceiver: FirExpression - abstract override val extensionReceiver: FirExpression + abstract val typeArguments: List + abstract val explicitReceiver: FirExpression? + abstract val dispatchReceiver: FirExpression + abstract val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? override fun accept(visitor: FirVisitor, data: D): R = visitor.visitQualifiedAccessExpression(this, data) @@ -35,9 +35,6 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces override fun transform(transformer: FirTransformer, data: D): E = transformer.transformQualifiedAccessExpression(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -46,19 +43,22 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List) - abstract override fun replaceTypeArguments(newTypeArguments: List) + abstract fun replaceTypeArguments(newTypeArguments: List) - 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 transformAnnotations(transformer: FirTransformer, data: D): FirQualifiedAccessExpression abstract override fun transformCalleeReference(transformer: FirTransformer, data: D): FirQualifiedAccessExpression - abstract override fun transformTypeArguments(transformer: FirTransformer, data: D): FirQualifiedAccessExpression + abstract fun transformTypeArguments(transformer: FirTransformer, data: D): FirQualifiedAccessExpression - abstract override fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirQualifiedAccessExpression + abstract fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirQualifiedAccessExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirThisReceiverExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirThisReceiverExpression.kt index e6252fb304c..dd56fadd22f 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirThisReceiverExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirThisReceiverExpression.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() { - abstract override val source: KtSourceElement? abstract override val typeRef: FirTypeRef abstract override val annotations: List abstract override val contextReceiverArguments: List @@ -28,6 +27,7 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() { abstract override val explicitReceiver: FirExpression? abstract override val dispatchReceiver: FirExpression abstract override val extensionReceiver: FirExpression + abstract override val source: KtSourceElement? abstract override val calleeReference: FirThisReference abstract val isImplicit: Boolean @@ -37,9 +37,6 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() { override fun transform(transformer: FirTransformer, data: D): E = transformer.transformThisReceiverExpression(this, data) as E - @FirImplementationDetail - abstract override fun replaceSource(newSource: KtSourceElement?) - abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) abstract override fun replaceAnnotations(newAnnotations: List) @@ -54,6 +51,9 @@ abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() { abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) + @FirImplementationDetail + abstract override fun replaceSource(newSource: KtSourceElement?) + abstract fun replaceCalleeReference(newCalleeReference: FirThisReference) abstract override fun replaceCalleeReference(newCalleeReference: FirReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirVariableAssignment.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirVariableAssignment.kt index ac0222ec58b..7a115d5b835 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirVariableAssignment.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirVariableAssignment.kt @@ -8,28 +8,17 @@ package org.jetbrains.kotlin.fir.expressions import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirElement 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.FirImplementationDetail /* * This file was generated automatically * DO NOT MODIFY IT MANUALLY */ -abstract class FirVariableAssignment : FirPureAbstractElement(), FirQualifiedAccess { - abstract override val calleeReference: FirReference - abstract override val annotations: List - abstract override val contextReceiverArguments: List - abstract override val typeArguments: List - abstract override val explicitReceiver: FirExpression? - abstract override val dispatchReceiver: FirExpression - abstract override val extensionReceiver: FirExpression +abstract class FirVariableAssignment : FirPureAbstractElement(), FirStatement { abstract override val source: KtSourceElement? - abstract val lValue: FirReference - abstract val lValueTypeRef: FirTypeRef + abstract override val annotations: List + abstract val lValue: FirExpression abstract val rValue: FirExpression override fun accept(visitor: FirVisitor, data: D): R = visitor.visitVariableAssignment(this, data) @@ -38,32 +27,13 @@ abstract class FirVariableAssignment : FirPureAbstractElement(), FirQualifiedAcc override fun transform(transformer: FirTransformer, data: D): E = transformer.transformVariableAssignment(this, data) as E - abstract override fun replaceCalleeReference(newCalleeReference: FirReference) - abstract override fun replaceAnnotations(newAnnotations: List) - abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List) - - abstract override fun replaceTypeArguments(newTypeArguments: List) - - 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 transformCalleeReference(transformer: FirTransformer, data: D): FirVariableAssignment + abstract fun replaceLValue(newLValue: FirExpression) abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirVariableAssignment - abstract override fun transformTypeArguments(transformer: FirTransformer, data: D): FirVariableAssignment - - abstract override fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirVariableAssignment + abstract fun transformLValue(transformer: FirTransformer, data: D): FirVariableAssignment abstract fun transformRValue(transformer: FirTransformer, data: D): FirVariableAssignment } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAbstractFunctionCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAbstractFunctionCallBuilder.kt index 83f1dd7cd7c..7df98818502 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAbstractFunctionCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirAbstractFunctionCallBuilder.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin 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.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -27,7 +27,8 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -interface FirAbstractFunctionCallBuilder : FirQualifiedAccessBuilder, FirCallBuilder { +interface FirAbstractFunctionCallBuilder : FirQualifiedAccessExpressionBuilder, FirCallBuilder { + abstract override var typeRef: FirTypeRef abstract override val annotations: MutableList abstract override val contextReceiverArguments: MutableList abstract override val typeArguments: MutableList @@ -36,7 +37,6 @@ interface FirAbstractFunctionCallBuilder : FirQualifiedAccessBuilder, FirCallBui abstract override var extensionReceiver: FirExpression abstract override var source: KtSourceElement? abstract override var argumentList: FirArgumentList - abstract var typeRef: FirTypeRef abstract var calleeReference: FirNamedReference abstract var origin: FirFunctionCallOrigin override fun build(): FirFunctionCall diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCallableReferenceAccessBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCallableReferenceAccessBuilder.kt index e61ea89858a..914601b6d34 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCallableReferenceAccessBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirCallableReferenceAccessBuilder.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirExpression 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.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.FirNamedReference @@ -33,8 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null +class FirCallableReferenceAccessBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override val annotations: MutableList = mutableListOf() override val contextReceiverArguments: MutableList = mutableListOf() @@ -42,12 +41,12 @@ class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotati override var explicitReceiver: FirExpression? = null override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression + override var source: KtSourceElement? = null lateinit var calleeReference: FirNamedReference var hasQuestionMarkAtLHS: Boolean = false override fun build(): FirCallableReferenceAccess { return FirCallableReferenceAccessImpl( - source, typeRef, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), @@ -55,6 +54,7 @@ class FirCallableReferenceAccessBuilder : FirQualifiedAccessBuilder, FirAnnotati explicitReceiver, dispatchReceiver, extensionReceiver, + source, calleeReference, hasQuestionMarkAtLHS, ) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirComponentCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirComponentCallBuilder.kt index b6ef8fadce8..182457951f0 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirComponentCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirComponentCallBuilder.kt @@ -39,24 +39,24 @@ import org.jetbrains.kotlin.name.Name @FirBuilderDsl class FirComponentCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null override val annotations: MutableList = mutableListOf() val contextReceiverArguments: MutableList = mutableListOf() val typeArguments: MutableList = mutableListOf() var dispatchReceiver: FirExpression = FirNoReceiverExpression var extensionReceiver: FirExpression = FirNoReceiverExpression + override var source: KtSourceElement? = null override var argumentList: FirArgumentList = FirEmptyArgumentList lateinit var explicitReceiver: FirExpression var componentIndex: Int by kotlin.properties.Delegates.notNull() override fun build(): FirComponentCall { return FirComponentCallImpl( - source, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(), dispatchReceiver, extensionReceiver, + source, argumentList, explicitReceiver, componentIndex, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirDesugaredAssignmentValueReferenceExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirDesugaredAssignmentValueReferenceExpressionBuilder.kt new file mode 100644 index 00000000000..ea301dc31ad --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirDesugaredAssignmentValueReferenceExpressionBuilder.kt @@ -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 = mutableListOf() + lateinit var expressionRef: FirExpressionRef + + 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() +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirFunctionCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirFunctionCallBuilder.kt index fe00c76023a..9cbf13208db 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirFunctionCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirFunctionCallBuilder.kt @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.visitors.* @FirBuilderDsl open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override val annotations: MutableList = mutableListOf() override val contextReceiverArguments: MutableList = mutableListOf() @@ -45,6 +44,7 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio override var explicitReceiver: FirExpression? = null override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression + override var source: KtSourceElement? = null override var argumentList: FirArgumentList = FirEmptyArgumentList override lateinit var calleeReference: FirNamedReference override var origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular @@ -52,7 +52,6 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio @OptIn(FirImplementationDetail::class) override fun build(): FirFunctionCall { return FirFunctionCallImpl( - source, typeRef, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), @@ -60,6 +59,7 @@ open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotatio explicitReceiver, dispatchReceiver, extensionReceiver, + source, argumentList, calleeReference, origin, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirImplicitInvokeCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirImplicitInvokeCallBuilder.kt index d4e8246863d..c0edfe4c29e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirImplicitInvokeCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirImplicitInvokeCallBuilder.kt @@ -37,25 +37,25 @@ import org.jetbrains.kotlin.fir.visitors.* @FirBuilderDsl open class FirImplicitInvokeCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null override val annotations: MutableList = mutableListOf() override val contextReceiverArguments: MutableList = mutableListOf() override val typeArguments: MutableList = mutableListOf() override var explicitReceiver: FirExpression? = null override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression + override var source: KtSourceElement? = null override var argumentList: FirArgumentList = FirEmptyArgumentList override lateinit var calleeReference: FirNamedReference override fun build(): FirImplicitInvokeCall { return FirImplicitInvokeCallImpl( - source, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(), explicitReceiver, dispatchReceiver, extensionReceiver, + source, argumentList, calleeReference, ) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirIntegerLiteralOperatorCallBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirIntegerLiteralOperatorCallBuilder.kt index 4f7a1b0c46e..f1d7e852e6d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirIntegerLiteralOperatorCallBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirIntegerLiteralOperatorCallBuilder.kt @@ -36,12 +36,12 @@ import org.jetbrains.kotlin.fir.visitors.* @FirBuilderDsl open class FirIntegerLiteralOperatorCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null override lateinit var typeRef: FirTypeRef override val annotations: MutableList = mutableListOf() override val contextReceiverArguments: MutableList = mutableListOf() override val typeArguments: MutableList = mutableListOf() override var explicitReceiver: FirExpression? = null + override var source: KtSourceElement? = null override var argumentList: FirArgumentList = FirEmptyArgumentList override lateinit var calleeReference: FirNamedReference override lateinit var origin: FirFunctionCallOrigin @@ -50,12 +50,12 @@ open class FirIntegerLiteralOperatorCallBuilder : FirAbstractFunctionCallBuilder override fun build(): FirIntegerLiteralOperatorCall { return FirIntegerLiteralOperatorCallImpl( - source, typeRef, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(), explicitReceiver, + source, argumentList, calleeReference, origin, diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirPropertyAccessExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirPropertyAccessExpressionBuilder.kt index 24fcf08c8d9..37f7f9b885d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirPropertyAccessExpressionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirPropertyAccessExpressionBuilder.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression 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.FirPropertyAccessExpressionImpl import org.jetbrains.kotlin.fir.references.FirReference @@ -33,8 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null +class FirPropertyAccessExpressionBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override val annotations: MutableList = mutableListOf() lateinit var calleeReference: FirReference @@ -43,12 +42,12 @@ class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotat override var explicitReceiver: FirExpression? = null override var dispatchReceiver: FirExpression = FirNoReceiverExpression override var extensionReceiver: FirExpression = FirNoReceiverExpression + override var source: KtSourceElement? = null val nonFatalDiagnostics: MutableList = mutableListOf() @OptIn(FirImplementationDetail::class) override fun build(): FirPropertyAccessExpression { return FirPropertyAccessExpressionImpl( - source, typeRef, annotations.toMutableOrEmpty(), calleeReference, @@ -57,6 +56,7 @@ class FirPropertyAccessExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotat explicitReceiver, dispatchReceiver, extensionReceiver, + source, nonFatalDiagnostics.toMutableOrEmpty(), ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessExpressionBuilder.kt similarity index 81% rename from compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessBuilder.kt rename to compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessExpressionBuilder.kt index dc77ca145f0..4ef3473a10c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirQualifiedAccessExpressionBuilder.kt @@ -11,8 +11,9 @@ import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.expressions.FirAnnotation 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.FirTypeRef import org.jetbrains.kotlin.fir.visitors.* /* @@ -21,7 +22,8 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -interface FirQualifiedAccessBuilder { +interface FirQualifiedAccessExpressionBuilder { + abstract var typeRef: FirTypeRef abstract val annotations: MutableList abstract val contextReceiverArguments: MutableList abstract val typeArguments: MutableList @@ -29,5 +31,5 @@ interface FirQualifiedAccessBuilder { abstract var dispatchReceiver: FirExpression abstract var extensionReceiver: FirExpression abstract var source: KtSourceElement? - fun build(): FirQualifiedAccess + fun build(): FirQualifiedAccessExpression } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirThisReceiverExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirThisReceiverExpressionBuilder.kt index 666967c98a9..0c023d23ca5 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirThisReceiverExpressionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirThisReceiverExpressionBuilder.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression 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.FirThisReceiverExpressionImpl import org.jetbrains.kotlin.fir.references.FirReference @@ -33,22 +33,22 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -class FirThisReceiverExpressionBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { - override var source: KtSourceElement? = null +class FirThisReceiverExpressionBuilder : FirQualifiedAccessExpressionBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder { override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override val annotations: MutableList = mutableListOf() override val contextReceiverArguments: MutableList = mutableListOf() override val typeArguments: MutableList = mutableListOf() + override var source: KtSourceElement? = null lateinit var calleeReference: FirThisReference var isImplicit: Boolean = false override fun build(): FirThisReceiverExpression { return FirThisReceiverExpressionImpl( - source, typeRef, annotations.toMutableOrEmpty(), contextReceiverArguments.toMutableOrEmpty(), typeArguments.toMutableOrEmpty(), + source, calleeReference, isImplicit, ) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirVariableAssignmentBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirVariableAssignmentBuilder.kt index 501719d4ff3..958a573ab0e 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirVariableAssignmentBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirVariableAssignmentBuilder.kt @@ -9,20 +9,13 @@ package org.jetbrains.kotlin.fir.expressions.builder import kotlin.contracts.* import org.jetbrains.kotlin.KtSourceElement -import org.jetbrains.kotlin.fir.FirImplementationDetail 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.FirExpression 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.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.* /* @@ -31,27 +24,17 @@ import org.jetbrains.kotlin.fir.visitors.* */ @FirBuilderDsl -class FirVariableAssignmentBuilder : FirQualifiedAccessBuilder, FirAnnotationContainerBuilder { - lateinit var calleeReference: FirReference - override val annotations: MutableList = mutableListOf() - override val contextReceiverArguments: MutableList = mutableListOf() - override val typeArguments: MutableList = mutableListOf() - override var explicitReceiver: FirExpression? = null - override var dispatchReceiver: FirExpression = FirNoReceiverExpression - override var extensionReceiver: FirExpression = FirNoReceiverExpression +class FirVariableAssignmentBuilder : FirAnnotationContainerBuilder { override var source: KtSourceElement? = null + override val annotations: MutableList = mutableListOf() + lateinit var lValue: FirExpression lateinit var rValue: FirExpression override fun build(): FirVariableAssignment { return FirVariableAssignmentImpl( - calleeReference, - annotations.toMutableOrEmpty(), - contextReceiverArguments.toMutableOrEmpty(), - typeArguments.toMutableOrEmpty(), - explicitReceiver, - dispatchReceiver, - extensionReceiver, source, + annotations.toMutableOrEmpty(), + lValue, rValue, ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCallableReferenceAccessImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCallableReferenceAccessImpl.kt index b083267a7ef..bdc7a53fcab 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCallableReferenceAccessImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirCallableReferenceAccessImpl.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ internal class FirCallableReferenceAccessImpl( - override var source: KtSourceElement?, override var typeRef: FirTypeRef, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, @@ -34,6 +33,7 @@ internal class FirCallableReferenceAccessImpl( override var explicitReceiver: FirExpression?, override var dispatchReceiver: FirExpression, override var extensionReceiver: FirExpression, + override var source: KtSourceElement?, override var calleeReference: FirNamedReference, override var hasQuestionMarkAtLHS: Boolean, ) : FirCallableReferenceAccess() { @@ -88,11 +88,6 @@ internal class FirCallableReferenceAccessImpl( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -121,6 +116,11 @@ internal class FirCallableReferenceAccessImpl( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceCalleeReference(newCalleeReference: FirNamedReference) { calleeReference = newCalleeReference } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirComponentCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirComponentCallImpl.kt index 83f9a4e6cb8..625f6629ad5 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirComponentCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirComponentCallImpl.kt @@ -32,12 +32,12 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty @OptIn(FirImplementationDetail::class) internal class FirComponentCallImpl( - override var source: KtSourceElement?, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, override var typeArguments: MutableOrEmptyList, override var dispatchReceiver: FirExpression, override var extensionReceiver: FirExpression, + override var source: KtSourceElement?, override var argumentList: FirArgumentList, override var explicitReceiver: FirExpression, override val componentIndex: Int, @@ -99,11 +99,6 @@ internal class FirComponentCallImpl( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -128,6 +123,11 @@ internal class FirComponentCallImpl( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceArgumentList(newArgumentList: FirArgumentList) { argumentList = newArgumentList } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirDesugaredAssignmentValueReferenceExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirDesugaredAssignmentValueReferenceExpressionImpl.kt new file mode 100644 index 00000000000..9059c61067a --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirDesugaredAssignmentValueReferenceExpressionImpl.kt @@ -0,0 +1,56 @@ +/* + * 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.impl + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirExpressionRef +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.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.MutableOrEmptyList +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +internal class FirDesugaredAssignmentValueReferenceExpressionImpl( + override val source: KtSourceElement?, + override var annotations: MutableOrEmptyList, + override val expressionRef: FirExpressionRef, +) : FirDesugaredAssignmentValueReferenceExpression() { + override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) + + override fun acceptChildren(visitor: FirVisitor, data: D) { + typeRef.accept(visitor, data) + annotations.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirDesugaredAssignmentValueReferenceExpressionImpl { + typeRef = typeRef.transform(transformer, data) + transformAnnotations(transformer, data) + return this + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirDesugaredAssignmentValueReferenceExpressionImpl { + annotations.transformInplace(transformer, data) + return this + } + + override fun replaceTypeRef(newTypeRef: FirTypeRef) { + typeRef = newTypeRef + } + + override fun replaceAnnotations(newAnnotations: List) { + annotations = newAnnotations.toMutableOrEmpty() + } +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirFunctionCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirFunctionCallImpl.kt index e4f2b06e64e..6b8ffa519d8 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirFunctionCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirFunctionCallImpl.kt @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty */ open class FirFunctionCallImpl @FirImplementationDetail constructor( - override var source: KtSourceElement?, override var typeRef: FirTypeRef, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, @@ -36,6 +35,7 @@ open class FirFunctionCallImpl @FirImplementationDetail constructor( override var explicitReceiver: FirExpression?, override var dispatchReceiver: FirExpression, override var extensionReceiver: FirExpression, + override var source: KtSourceElement?, override var argumentList: FirArgumentList, override var calleeReference: FirNamedReference, override val origin: FirFunctionCallOrigin, @@ -93,11 +93,6 @@ open class FirFunctionCallImpl @FirImplementationDetail constructor( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -126,6 +121,11 @@ open class FirFunctionCallImpl @FirImplementationDetail constructor( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceArgumentList(newArgumentList: FirArgumentList) { argumentList = newArgumentList } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirImplicitInvokeCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirImplicitInvokeCallImpl.kt index 9a7d4b1c965..8a85de4d14b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirImplicitInvokeCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirImplicitInvokeCallImpl.kt @@ -29,13 +29,13 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ internal class FirImplicitInvokeCallImpl( - override var source: KtSourceElement?, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, override var typeArguments: MutableOrEmptyList, override var explicitReceiver: FirExpression?, override var dispatchReceiver: FirExpression, override var extensionReceiver: FirExpression, + override var source: KtSourceElement?, override var argumentList: FirArgumentList, override var calleeReference: FirNamedReference, ) : FirImplicitInvokeCall() { @@ -95,11 +95,6 @@ internal class FirImplicitInvokeCallImpl( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -128,6 +123,11 @@ internal class FirImplicitInvokeCallImpl( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceArgumentList(newArgumentList: FirArgumentList) { argumentList = newArgumentList } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirIntegerLiteralOperatorCallImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirIntegerLiteralOperatorCallImpl.kt index 29bce30797c..aad13593900 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirIntegerLiteralOperatorCallImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirIntegerLiteralOperatorCallImpl.kt @@ -28,12 +28,12 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ internal class FirIntegerLiteralOperatorCallImpl( - override var source: KtSourceElement?, override var typeRef: FirTypeRef, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, override var typeArguments: MutableOrEmptyList, override var explicitReceiver: FirExpression?, + override var source: KtSourceElement?, override var argumentList: FirArgumentList, override var calleeReference: FirNamedReference, override val origin: FirFunctionCallOrigin, @@ -103,11 +103,6 @@ internal class FirIntegerLiteralOperatorCallImpl( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -128,6 +123,11 @@ internal class FirIntegerLiteralOperatorCallImpl( explicitReceiver = newExplicitReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceArgumentList(newArgumentList: FirArgumentList) { argumentList = newArgumentList } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirPropertyAccessExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirPropertyAccessExpressionImpl.kt index 33fe3eb1273..577bc92621d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirPropertyAccessExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirPropertyAccessExpressionImpl.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty */ class FirPropertyAccessExpressionImpl @FirImplementationDetail constructor( - override var source: KtSourceElement?, override var typeRef: FirTypeRef, override var annotations: MutableOrEmptyList, override var calleeReference: FirReference, @@ -35,6 +34,7 @@ class FirPropertyAccessExpressionImpl @FirImplementationDetail constructor( override var explicitReceiver: FirExpression?, override var dispatchReceiver: FirExpression, override var extensionReceiver: FirExpression, + override var source: KtSourceElement?, override var nonFatalDiagnostics: MutableOrEmptyList, ) : FirPropertyAccessExpression() { override fun acceptChildren(visitor: FirVisitor, data: D) { @@ -88,11 +88,6 @@ class FirPropertyAccessExpressionImpl @FirImplementationDetail constructor( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -125,6 +120,11 @@ class FirPropertyAccessExpressionImpl @FirImplementationDetail constructor( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceNonFatalDiagnostics(newNonFatalDiagnostics: List) { nonFatalDiagnostics = newNonFatalDiagnostics.toMutableOrEmpty() } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirThisReceiverExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirThisReceiverExpressionImpl.kt index abacf564b30..790626e3f2c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirThisReceiverExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirThisReceiverExpressionImpl.kt @@ -27,11 +27,11 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ internal class FirThisReceiverExpressionImpl( - override var source: KtSourceElement?, override var typeRef: FirTypeRef, override var annotations: MutableOrEmptyList, override var contextReceiverArguments: MutableOrEmptyList, override var typeArguments: MutableOrEmptyList, + override var source: KtSourceElement?, override var calleeReference: FirThisReference, override val isImplicit: Boolean, ) : FirThisReceiverExpression() { @@ -90,11 +90,6 @@ internal class FirThisReceiverExpressionImpl( return this } - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - override fun replaceTypeRef(newTypeRef: FirTypeRef) { typeRef = newTypeRef } @@ -123,6 +118,11 @@ internal class FirThisReceiverExpressionImpl( extensionReceiver = newExtensionReceiver } + @FirImplementationDetail + override fun replaceSource(newSource: KtSourceElement?) { + source = newSource + } + override fun replaceCalleeReference(newCalleeReference: FirThisReference) { calleeReference = newCalleeReference } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirVariableAssignmentImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirVariableAssignmentImpl.kt index fd4f3adf355..8285a93dddd 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirVariableAssignmentImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirVariableAssignmentImpl.kt @@ -11,14 +11,9 @@ import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment -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.MutableOrEmptyList import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty -import org.jetbrains.kotlin.fir.FirImplementationDetail /* * This file was generated automatically @@ -26,73 +21,31 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail */ internal class FirVariableAssignmentImpl( - override var calleeReference: FirReference, + override val source: KtSourceElement?, override var annotations: MutableOrEmptyList, - override var contextReceiverArguments: MutableOrEmptyList, - override var typeArguments: MutableOrEmptyList, - override var explicitReceiver: FirExpression?, - override var dispatchReceiver: FirExpression, - override var extensionReceiver: FirExpression, - override var source: KtSourceElement?, + override var lValue: FirExpression, override var rValue: FirExpression, ) : FirVariableAssignment() { - override var lValue: FirReference - get() = calleeReference - set(value) { - calleeReference = value - } - override var lValueTypeRef: FirTypeRef = FirImplicitTypeRefImpl(null) - override fun acceptChildren(visitor: FirVisitor, data: D) { - calleeReference.accept(visitor, data) annotations.forEach { it.accept(visitor, data) } - contextReceiverArguments.forEach { it.accept(visitor, data) } - typeArguments.forEach { it.accept(visitor, data) } - explicitReceiver?.accept(visitor, data) - if (dispatchReceiver !== explicitReceiver) { - dispatchReceiver.accept(visitor, data) - } - if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) { - extensionReceiver.accept(visitor, data) - } - lValueTypeRef.accept(visitor, data) + lValue.accept(visitor, data) rValue.accept(visitor, data) } override fun transformChildren(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { - transformCalleeReference(transformer, data) transformAnnotations(transformer, data) - contextReceiverArguments.transformInplace(transformer, data) - transformTypeArguments(transformer, data) - explicitReceiver = explicitReceiver?.transform(transformer, data) - if (dispatchReceiver !== explicitReceiver) { - dispatchReceiver = dispatchReceiver.transform(transformer, data) - } - if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) { - extensionReceiver = extensionReceiver.transform(transformer, data) - } - lValueTypeRef = lValueTypeRef.transform(transformer, data) + transformLValue(transformer, data) transformRValue(transformer, data) return this } - override fun transformCalleeReference(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { - calleeReference = calleeReference.transform(transformer, data) - return this - } - override fun transformAnnotations(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { annotations.transformInplace(transformer, data) return this } - override fun transformTypeArguments(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { - typeArguments.transformInplace(transformer, data) - return this - } - - override fun transformExplicitReceiver(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { - explicitReceiver = explicitReceiver?.transform(transformer, data) + override fun transformLValue(transformer: FirTransformer, data: D): FirVariableAssignmentImpl { + lValue = lValue.transform(transformer, data) return this } @@ -101,40 +54,11 @@ internal class FirVariableAssignmentImpl( return this } - override fun replaceCalleeReference(newCalleeReference: FirReference) { - calleeReference = newCalleeReference - } - override fun replaceAnnotations(newAnnotations: List) { annotations = newAnnotations.toMutableOrEmpty() } - override fun replaceContextReceiverArguments(newContextReceiverArguments: List) { - contextReceiverArguments = newContextReceiverArguments.toMutableOrEmpty() - } - - override fun replaceTypeArguments(newTypeArguments: List) { - typeArguments = newTypeArguments.toMutableOrEmpty() - } - - override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) { - explicitReceiver = newExplicitReceiver - } - - override fun replaceDispatchReceiver(newDispatchReceiver: FirExpression) { - dispatchReceiver = newDispatchReceiver - } - - override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression) { - extensionReceiver = newExtensionReceiver - } - - @FirImplementationDetail - override fun replaceSource(newSource: KtSourceElement?) { - source = newSource - } - - override fun replaceLValueTypeRef(newLValueTypeRef: FirTypeRef) { - lValueTypeRef = newLValueTypeRef + override fun replaceLValue(newLValue: FirExpression) { + lValue = newLValue } } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt index acf7af34c25..b8df2fc15c2 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt @@ -86,7 +86,6 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirContextReceiverArgumentListOwner -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirElvisExpression import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall @@ -124,6 +123,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression +import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase @@ -256,10 +256,12 @@ abstract class FirDefaultVisitor : FirVisitor() { override fun visitThrowExpression(throwExpression: FirThrowExpression, data: D): R = visitExpression(throwExpression, data) - override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: D): R = visitQualifiedAccess(variableAssignment, data) + override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: D): R = visitStatement(variableAssignment, data) override fun visitWhenSubjectExpression(whenSubjectExpression: FirWhenSubjectExpression, data: D): R = visitExpression(whenSubjectExpression, data) + override fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, data: D): R = visitExpression(desugaredAssignmentValueReferenceExpression, data) + override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitWrappedExpression(wrappedDelegateExpression, data) override fun visitNamedReference(namedReference: FirNamedReference, data: D): R = visitReference(namedReference, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt index b1fbefaed24..3d2b903a897 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt @@ -86,7 +86,6 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirContextReceiverArgumentListOwner -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirElvisExpression import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall @@ -124,6 +123,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression +import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase @@ -256,10 +256,12 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() { override fun visitThrowExpression(throwExpression: FirThrowExpression) = visitExpression(throwExpression) - override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) = visitQualifiedAccess(variableAssignment) + override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) = visitStatement(variableAssignment) override fun visitWhenSubjectExpression(whenSubjectExpression: FirWhenSubjectExpression) = visitExpression(whenSubjectExpression) + override fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression) = visitExpression(desugaredAssignmentValueReferenceExpression) + override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) = visitWrappedExpression(wrappedDelegateExpression) override fun visitNamedReference(namedReference: FirNamedReference) = visitReference(namedReference) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt index 1cf9fe521aa..6e8eff1dc3c 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt @@ -86,7 +86,6 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirContextReceiverArgumentListOwner -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirElvisExpression import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall @@ -124,6 +123,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression +import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase @@ -479,10 +479,6 @@ abstract class FirTransformer : FirVisitor() { return transformElement(contextReceiverArgumentListOwner, data) } - open fun transformQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: D): FirStatement { - return transformElement(qualifiedAccess, data) - } - open fun transformCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: D): FirStatement { return transformElement(checkNotNullCall, data) } @@ -631,6 +627,10 @@ abstract class FirTransformer : FirVisitor() { return transformElement(whenSubjectExpression, data) } + open fun transformDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, data: D): FirStatement { + return transformElement(desugaredAssignmentValueReferenceExpression, data) + } + open fun transformWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): FirStatement { return transformElement(wrappedDelegateExpression, data) } @@ -1055,10 +1055,6 @@ abstract class FirTransformer : FirVisitor() { return transformContextReceiverArgumentListOwner(contextReceiverArgumentListOwner, data) } - final override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: D): FirStatement { - return transformQualifiedAccess(qualifiedAccess, data) - } - final override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: D): FirStatement { return transformCheckNotNullCall(checkNotNullCall, data) } @@ -1207,6 +1203,10 @@ abstract class FirTransformer : FirVisitor() { return transformWhenSubjectExpression(whenSubjectExpression, data) } + final override fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, data: D): FirStatement { + return transformDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression, data) + } + final override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): FirStatement { return transformWrappedDelegateExpression(wrappedDelegateExpression, data) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt index 57151b30029..cb7a56992e6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt @@ -86,7 +86,6 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirContextReceiverArgumentListOwner -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirElvisExpression import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall @@ -124,6 +123,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression +import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase @@ -318,8 +318,6 @@ abstract class FirVisitor { open fun visitContextReceiverArgumentListOwner(contextReceiverArgumentListOwner: FirContextReceiverArgumentListOwner, data: D): R = visitElement(contextReceiverArgumentListOwner, data) - open fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: D): R = visitElement(qualifiedAccess, data) - open fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: D): R = visitElement(checkNotNullCall, data) open fun visitElvisExpression(elvisExpression: FirElvisExpression, data: D): R = visitElement(elvisExpression, data) @@ -394,6 +392,8 @@ abstract class FirVisitor { open fun visitWhenSubjectExpression(whenSubjectExpression: FirWhenSubjectExpression, data: D): R = visitElement(whenSubjectExpression, data) + open fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, data: D): R = visitElement(desugaredAssignmentValueReferenceExpression, data) + open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitElement(wrappedDelegateExpression, data) open fun visitNamedReference(namedReference: FirNamedReference, data: D): R = visitElement(namedReference, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt index a186ebdcddf..f9ab7719e16 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt @@ -86,7 +86,6 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenBranch import org.jetbrains.kotlin.fir.expressions.FirContextReceiverArgumentListOwner -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall import org.jetbrains.kotlin.fir.expressions.FirElvisExpression import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall @@ -124,6 +123,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression +import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase @@ -478,10 +478,6 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(contextReceiverArgumentListOwner) } - open fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) { - visitElement(qualifiedAccess) - } - open fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) { visitElement(checkNotNullCall) } @@ -630,6 +626,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(whenSubjectExpression) } + open fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression) { + visitElement(desugaredAssignmentValueReferenceExpression) + } + open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) { visitElement(wrappedDelegateExpression) } @@ -1054,10 +1054,6 @@ abstract class FirVisitorVoid : FirVisitor() { visitContextReceiverArgumentListOwner(contextReceiverArgumentListOwner) } - final override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: Nothing?) { - visitQualifiedAccess(qualifiedAccess) - } - final override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Nothing?) { visitCheckNotNullCall(checkNotNullCall) } @@ -1206,6 +1202,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitWhenSubjectExpression(whenSubjectExpression) } + final override fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression, data: Nothing?) { + visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression) + } + final override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: Nothing?) { visitWrappedDelegateExpression(wrappedDelegateExpression) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt index afd8f1e29d7..d3185478755 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression import org.jetbrains.kotlin.fir.expressions.builder.buildErrorLoop import org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl +import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.references.FirReference @@ -68,9 +69,13 @@ fun FirExpression.toResolvedCallableReference(): FirResolvedNamedReference? { } fun FirExpression.toReference(): FirReference? { - if (this is FirWrappedArgumentExpression) return expression.toResolvedCallableReference() - if (this is FirSmartCastExpression) return originalExpression.toReference() - return (this as? FirResolvable)?.calleeReference + return when (this) { + is FirWrappedArgumentExpression -> expression.toResolvedCallableReference() + is FirSmartCastExpression -> originalExpression.toReference() + is FirDesugaredAssignmentValueReferenceExpression -> expressionRef.value.toReference() + is FirResolvable -> calleeReference + else -> null + } } fun FirExpression.toResolvedCallableSymbol(): FirCallableSymbol<*>? { @@ -122,3 +127,22 @@ fun FirBlock.replaceFirstStatement(factory: (T) -> FirStateme } fun FirExpression.unwrapArgument(): FirExpression = (this as? FirWrappedArgumentExpression)?.expression ?: this + +val FirVariableAssignment.explicitReceiver: FirExpression? get() = unwrapLValue()?.explicitReceiver + +val FirVariableAssignment.dispatchReceiver: FirExpression get() = unwrapLValue()?.dispatchReceiver ?: FirNoReceiverExpression + +val FirVariableAssignment.extensionReceiver: FirExpression get() = unwrapLValue()?.extensionReceiver ?: FirNoReceiverExpression + +val FirVariableAssignment.calleeReference: FirReference? get() = lValue.toReference() + +val FirVariableAssignment.contextReceiverArguments: List get() = unwrapLValue()?.contextReceiverArguments ?: emptyList() + +fun FirVariableAssignment.unwrapLValue(): FirQualifiedAccessExpression? { + val lValue = lValue + return lValue as? FirQualifiedAccessExpression + ?: (lValue as? FirDesugaredAssignmentValueReferenceExpression)?.expressionRef?.value as? FirQualifiedAccessExpression +} + +val FirElement.calleeReference: FirReference? + get() = (this as? FirResolvable)?.calleeReference ?: (this as? FirVariableAssignment)?.calleeReference diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index 19183e95804..338024b6976 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -886,7 +886,7 @@ class FirRenderer( } } - override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) { + private fun visitQualifiedAccessExpressionReceivers(qualifiedAccess: FirQualifiedAccessExpression) { val explicitReceiver = qualifiedAccess.explicitReceiver val dispatchReceiver = qualifiedAccess.dispatchReceiver val extensionReceiver = qualifiedAccess.extensionReceiver @@ -940,7 +940,7 @@ class FirRenderer( override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) { annotationRenderer?.render(qualifiedAccessExpression) - visitQualifiedAccess(qualifiedAccessExpression) + visitQualifiedAccessExpressionReceivers(qualifiedAccessExpression) qualifiedAccessExpression.calleeReference.accept(this) qualifiedAccessExpression.typeArguments.renderTypeArguments() } @@ -957,9 +957,12 @@ class FirRenderer( smartCastExpression.originalExpression.accept(this) } + override fun visitDesugaredAssignmentValueReferenceExpression(desugaredAssignmentValueReferenceExpression: FirDesugaredAssignmentValueReferenceExpression) { + desugaredAssignmentValueReferenceExpression.expressionRef.value.accept(this) + } + override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) { annotationRenderer?.render(variableAssignment) - visitQualifiedAccess(variableAssignment) variableAssignment.lValue.accept(this) print(" ") print(FirOperation.ASSIGN.operator) @@ -980,7 +983,7 @@ class FirRenderer( override fun visitFunctionCall(functionCall: FirFunctionCall) { annotationRenderer?.render(functionCall) - visitQualifiedAccess(functionCall) + visitQualifiedAccessExpressionReceivers(functionCall) functionCall.calleeReference.accept(this) functionCall.typeArguments.renderTypeArguments() visitCall(functionCall) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt index 0fd658beb1e..46b1e023d03 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt @@ -45,8 +45,8 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree withCopy() } - val qualifiedAccessBuilder by builder { - fields from qualifiedAccess without "calleeReference" + val qualifiedAccessExpressionBuilder by builder { + fields from qualifiedAccessExpression without "calleeReference" } val callBuilder by builder { @@ -79,7 +79,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree } val abstractFunctionCallBuilder by builder { - parents += qualifiedAccessBuilder + parents += qualifiedAccessExpressionBuilder parents += callBuilder fields from functionCall } @@ -152,12 +152,12 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree } builder(propertyAccessExpression) { - parents += qualifiedAccessBuilder + parents += qualifiedAccessExpressionBuilder defaultNoReceivers() } builder(callableReferenceAccess) { - parents += qualifiedAccessBuilder + parents += qualifiedAccessExpressionBuilder defaultNull("explicitReceiver") defaultNoReceivers() defaultFalse("hasQuestionMarkAtLHS") @@ -245,7 +245,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree } builder(thisReceiverExpression) { - parents += qualifiedAccessBuilder + parents += qualifiedAccessExpressionBuilder default("isImplicit", "false") } @@ -257,11 +257,6 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree default("contextReceiverNumber", "-1") } - builder(variableAssignment) { - parents += qualifiedAccessBuilder - defaultNoReceivers() - } - builder(anonymousFunction) { parents += functionBuilder defaultNull("invocationKind", "label", "body", "controlFlowGraphReference") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt index 9bf095af447..76bdd0a25e6 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt @@ -108,7 +108,6 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val whenExpression by element(Expression, expression, resolvable) val whenBranch by element(Expression) val contextReceiverArgumentListOwner by element(Expression) - val qualifiedAccess by element(Expression, resolvable, statement, contextReceiverArgumentListOwner) val checkNotNullCall by element(Expression, expression, call, resolvable) val elvisExpression by element(Expression, expression, resolvable) @@ -119,7 +118,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val errorFunction by element(Declaration, function, diagnosticHolder) val errorProperty by element(Declaration, variable, diagnosticHolder) val danglingModifierList by element(Declaration, declaration, diagnosticHolder) - val qualifiedAccessExpression by element(Expression, expression, qualifiedAccess) + val qualifiedAccessExpression by element(Expression, expression, resolvable, contextReceiverArgumentListOwner) val qualifiedErrorAccessExpression by element(Expression, expression, diagnosticHolder) val propertyAccessExpression by element(Expression, qualifiedAccessExpression) val functionCall by element(Expression, qualifiedAccessExpression, call) @@ -147,8 +146,9 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val returnExpression by element(Expression, jump) val stringConcatenationCall by element(Expression, call, expression) val throwExpression by element(Expression, expression) - val variableAssignment by element(Expression, qualifiedAccess) + val variableAssignment by element(Expression, statement) val whenSubjectExpression by element(Expression, expression) + val desugaredAssignmentValueReferenceExpression by element(Expression, expression) val wrappedDelegateExpression by element(Expression, wrappedExpression) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 5f2ca281f8e..a5671079971 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -354,13 +354,6 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() publicImplementation() } - impl(variableAssignment) { - default("lValue") { - value = "calleeReference" - customSetter = "calleeReference = value" - } - } - impl(anonymousFunction) { default("resolvePhase", "FirResolvePhase.DECLARATIONS") } @@ -392,6 +385,10 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() useTypes(whenExpression) } + impl(desugaredAssignmentValueReferenceExpression) { + useTypes(expression) + } + impl(wrappedDelegateExpression) { default("typeRef") { delegate = "expression" diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index da30eb1e38d..ddcdb7af929 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -205,7 +205,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +fieldList("contextReceiverArguments", expression, useMutableOrEmpty = true, withReplace = true) } - qualifiedAccess.configure { + qualifiedAccessExpression.configure { +typeArguments.withTransform() +receivers +field("source", sourceElementType, nullable = true, withReplace = true) @@ -563,7 +563,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild } checkedSafeCallSubject.configure { - +field("originalReceiverRef", safeCallOriginalReceiverReferenceType) + +field("originalReceiverRef", referenceToSimpleExpressionType) } callableReferenceAccess.configure { @@ -611,8 +611,7 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild } variableAssignment.configure { - +field("lValue", reference) - +field("lValueTypeRef", typeRef).withReplace() + +field("lValue", expression).withTransform().withReplace() +field("rValue", expression).withTransform() } @@ -620,6 +619,10 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("whenRef", whenRefType) } + desugaredAssignmentValueReferenceExpression.configure { + +field("expressionRef", referenceToSimpleExpressionType) + } + wrappedExpression.configure { +field(expression).withReplace() } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt index 7e948e4658f..1485d5b5e3f 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/Types.kt @@ -46,7 +46,7 @@ val coneKotlinTypeType = type(ConeKotlinType::class) val coneSimpleKotlinTypeType = type(ConeSimpleKotlinType::class) val whenRefType = generatedType("", "FirExpressionRef") -val safeCallOriginalReceiverReferenceType = generatedType("", "FirExpressionRef") +val referenceToSimpleExpressionType = generatedType("", "FirExpressionRef") val safeCallCheckedSubjectReferenceType = generatedType("", "FirExpressionRef") val firModuleDataType = type("fir", "FirModuleData") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt index d645d727d0a..e60ba698360 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/printer/element.kt @@ -106,7 +106,8 @@ fun SmartPrinter.printElement(element: Element) { } allFields.filter { it.withReplace }.forEach { - val override = overridenFields[it, it] && !(it.name == "source" && fullQualifiedName.endsWith("FirQualifiedAccess")) + val override = overridenFields[it, it] && + !(it.name == "source" && fullQualifiedName.endsWith("FirQualifiedAccessExpression")) it.replaceDeclaration(override, forceNullable = it.useNullableForReplace) for (overridenType in it.overridenTypes) { it.replaceDeclaration(true, overridenType) diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt index 1ebc2b6ace6..6963eb072e4 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/LightTreePositioningStrategies.kt @@ -950,33 +950,6 @@ object LightTreePositioningStrategies { } } - val ASSIGNMENT_LHS: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { - override fun mark( - node: LighterASTNode, - startOffset: Int, - endOffset: Int, - tree: FlyweightCapableTreeStructure - ): List { - if ((node.tokenType == KtNodeTypes.BINARY_EXPRESSION && - tree.findDescendantByTypes(node, KtTokens.ALL_ASSIGNMENTS) != null) || - ((node.tokenType == KtNodeTypes.PREFIX_EXPRESSION || node.tokenType == KtNodeTypes.POSTFIX_EXPRESSION) && - tree.findDescendantByTypes(node, KtTokens.INCREMENT_AND_DECREMENT) != null) - ) { - val lhs = if (node.tokenType == KtNodeTypes.PREFIX_EXPRESSION) { - tree.lastChildExpression(node) - } else { - tree.firstChildExpression(node) - } - lhs?.let { - tree.unwrapParenthesesLabelsAndAnnotations(it).let { unwrapped -> - return markElement(unwrapped, startOffset, endOffset, tree, node) - } - } - } - return super.mark(node, startOffset, endOffset, tree) - } - } - val ANNOTATION_USE_SITE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { override fun mark( node: LighterASTNode, @@ -1426,7 +1399,7 @@ fun FlyweightCapableTreeStructure.selector(node: LighterASTNode) dotOrDoubleColonFound = true continue } - if (dotOrDoubleColonFound && (tokenType == KtNodeTypes.CALL_EXPRESSION || tokenType == KtNodeTypes.REFERENCE_EXPRESSION)) { + if (dotOrDoubleColonFound && child.isExpression()) { return child } } diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 6722699735e..d2aaef3fa33 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -944,18 +944,6 @@ object PositioningStrategies { } } - val ASSIGNMENT_LHS: PositioningStrategy = object : PositioningStrategy() { - override fun mark(element: PsiElement): List { - if (element is KtBinaryExpression && element.operationToken in KtTokens.ALL_ASSIGNMENTS) { - element.left.let { left -> left.unwrapParenthesesLabelsAndAnnotations()?.let { return markElement(it) } } - } - if (element is KtUnaryExpression && element.operationToken in KtTokens.INCREMENT_AND_DECREMENT) { - element.baseExpression.let { arg -> arg.unwrapParenthesesLabelsAndAnnotations()?.let { return markElement(it) } } - } - return super.mark(element) - } - } - val IMPORT_LAST_NAME: PositioningStrategy = object : PositioningStrategy() { override fun isValid(element: PsiElement): Boolean { diff --git a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt index 27edf1346ac..7b4956dfcd6 100644 --- a/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/frontend.common-psi/src/org/jetbrains/kotlin/diagnostics/SourceElementPositioningStrategies.kt @@ -263,11 +263,6 @@ object SourceElementPositioningStrategies { PositioningStrategies.ANNOTATION_USE_SITE ) - val ASSIGNMENT_LHS = SourceElementPositioningStrategy( - LightTreePositioningStrategies.ASSIGNMENT_LHS, - PositioningStrategies.ASSIGNMENT_LHS - ) - val IMPORT_LAST_NAME = SourceElementPositioningStrategy( LightTreePositioningStrategies.IMPORT_LAST_NAME, PositioningStrategies.IMPORT_LAST_NAME diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt index 420454a5501..410c5b024f7 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt @@ -240,6 +240,9 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() { // for all implicit receivers (now used for qualifiers only) object ImplicitReceiver : KtFakeSourceElementKind() + + // for when on the LHS of an assignment an error expression appears + object AssignmentLValueError : KtFakeSourceElementKind() } sealed class AbstractKtSourceElement { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index fb85f4b26e8..6f604986d05 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -167,7 +167,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes private fun reportDynamic(element: FirResolvable) { val calleeDeclaration = element.calleeReference.toResolvedCallableSymbol() ?: return val isInvokeCallWithDynamicReceiver = calleeDeclaration.name == OperatorNameConventions.INVOKE - && element is FirQualifiedAccess + && element is FirQualifiedAccessExpression && element.dispatchReceiver.typeRef.isFunctionTypeWithDynamicReceiver(firFile.moduleData.session) if (calleeDeclaration.origin !is FirDeclarationOrigin.DynamicScope && !isInvokeCallWithDynamicReceiver) { @@ -207,7 +207,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) { val selector = safeCallExpression.selector - if (selector is FirQualifiedAccess) { + if (selector is FirQualifiedAccessExpression) { val reference = selector.calleeReference as FirNamedReference consumer.reportCallDiagnostic(safeCallExpression, reference) consumer.reportContainingClassDiagnostic(safeCallExpression, reference) diff --git a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt index ae6594b26af..6fa33bb1ac4 100644 --- a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt +++ b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt @@ -243,7 +243,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { } else -> { expression.allOfTypeWithLocalReplace(operation) { this.calleeReference.name.asString() } - ?: expression.firstOfTypeWithLocalReplace(operation) { this.lValue.toString() } + ?: expression.firstOfTypeWithLocalReplace(operation) { this.calleeReference.toString() } super.visitBinaryExpression(expression) } }