FIR: Make LHS of FirVariableAssignment a FirExpression

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

^KT-54648 Fixed
This commit is contained in:
Kirill Rakhman
2023-01-16 09:54:31 +01:00
committed by Space Team
parent e9b8d6db80
commit ace47c06a5
128 changed files with 950 additions and 935 deletions
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
import org.jetbrains.kotlin.fir.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(
@@ -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
@@ -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 <T> transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
fun <T> transformErrorReference(call: FirElement, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
val diagnostic = calleeReference.diagnostic
val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
@@ -199,16 +199,16 @@ internal class KtFirCallResolver(
val candidateCalls = mutableListOf<KtCall>()
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<KtBinaryExpression>() ?: return null
if (deparenthesize(binaryExpression.left) != lhs || binaryExpression.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
if (binaryExpression.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
val leftOfBinary = deparenthesize(binaryExpression.left)
if (leftOfBinary != lhs && !(leftOfBinary is KtDotQualifiedExpression && leftOfBinary.selectorExpression == lhs)) return null
val firBinaryExpression = binaryExpression.getOrBuildFir(analysisSession.firResolveSession)
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<KtVariableLikeSymbol>,
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<KtFunctionSymbol>? {
// 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<KtVariableLikeSymbol>? {
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<KtVariableLikeSymbol> =
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSignature(this)
private fun FirQualifiedAccess.toTypeArgumentsMapping(
private fun FirQualifiedAccessExpression.toTypeArgumentsMapping(
partiallyAppliedSymbol: KtPartiallyAppliedSymbol<*, *>
): Map<KtTypeParameterSymbol, KtType> {
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<FirCallableSymbol<*>>()?.name
getCandidateSymbols().firstOrNull()?.safeAs<FirCallableSymbol<*>>()?.name
}
}
}
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.constructFunctionalType
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.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
@@ -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
}
@@ -309,7 +309,7 @@ internal object FirReferenceResolveHelper {
symbolBuilder: KtSymbolByFirBuilder,
): Collection<KtSymbol> {
if (expression is KtNameReferenceExpression) {
return fir.calleeReference.toTargetSymbol(session, symbolBuilder)
return fir.calleeReference?.toTargetSymbol(session, symbolBuilder) ?: emptyList()
}
val assignmentRValue = fir.rValue
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLoc
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
import org.jetbrains.kotlin.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(
}
}
}
}
}
@@ -63,7 +63,8 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: MutableMap<KtElement, FirElement>) {
cacheElement(variableAssignment.lValue, data) // FirReference is not cached by default
// For the LHS of the assignment, record the assignment itself
(variableAssignment.lValue.source?.psi as? KtElement)?.let { cache(it, variableAssignment, data) }
visitElement(variableAssignment, data)
}
@@ -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
@@ -31,7 +31,6 @@ fun main(args: Array<String>) {
val expressionPackage = "$basePackage.checkers.expression"
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
alias<FirStatement>("BasicExpressionChecker")
alias<FirQualifiedAccess>("QualifiedAccessChecker")
alias<FirQualifiedAccessExpression>("QualifiedAccessExpressionChecker")
alias<FirCall>("CallChecker")
alias<FirFunctionCall>("FunctionCallChecker")
@@ -64,7 +64,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error<PsiElement>()
val NOT_A_LOOP_LABEL by error<PsiElement>()
val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error<KtExpressionWithLabel>()
val VARIABLE_EXPECTED by error<PsiElement>(PositioningStrategy.ASSIGNMENT_LHS)
val VARIABLE_EXPECTED by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
val DELEGATION_IN_INTERFACE by error<PsiElement>()
val DELEGATION_NOT_TO_INTERFACE by error<PsiElement>()
val NESTED_CLASS_NOT_ALLOWED by error<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
@@ -91,7 +91,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error<KtParameter>(PositioningStrategy.VAL_OR_VAR_NODE) {
parameter<KtKeywordToken>("valOrVar")
}
val INVISIBLE_SETTER by error<PsiElement>(PositioningStrategy.ASSIGNMENT_LHS) {
val INVISIBLE_SETTER by error<PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirPropertySymbol>("property")
parameter<Visibility>("visibility")
parameter<CallableId>("callableId")
@@ -1135,10 +1135,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNINITIALIZED_ENUM_COMPANION by error<KtExpression>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<FirRegularClassSymbol>("enumClass")
}
val VAL_REASSIGNMENT by error<KtExpression> {
val VAL_REASSIGNMENT by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirVariableSymbol<*>>("variable")
}
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError<KtExpression>(LanguageFeature.RestrictionOfValReassignmentViaBackingField) {
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError<KtExpression>(LanguageFeature.RestrictionOfValReassignmentViaBackingField, PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirBackingFieldSymbol>("property")
}
val CAPTURED_VAL_INITIALIZATION by error<KtExpression> {
@@ -1147,7 +1147,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val CAPTURED_MEMBER_VAL_INITIALIZATION by error<KtExpression> {
parameter<FirPropertySymbol>("property")
}
val SETTER_PROJECTED_OUT by error<KtBinaryExpression>(PositioningStrategy.ASSIGNMENT_LHS) {
val SETTER_PROJECTED_OUT by error<KtBinaryExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirPropertySymbol>("property")
}
val WRONG_INVOCATION_KIND by warning<PsiElement> {
@@ -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,
@@ -14,8 +14,8 @@ object JsExpressionCheckers : ExpressionCheckers() {
FirJsQualifierChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf(
FirJsDefinedExternallyCallChecker,
FirJsDefinedExternallyCallChecker
)
}
@@ -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
@@ -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<FirQualifiedAccessChecker>
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf(
FirJvmProtectedInSuperClassCompanionCallChecker
)
@@ -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)
}
}
}
@@ -28,7 +28,7 @@ object FirJvmSuspensionPointInsideMutexLockChecker : FirFunctionCallChecker() {
if (!symbol.isSuspend) return
val closestAnonymousFunction = context.findClosest<FirAnonymousFunction>() ?: 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) {
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
class ComposedExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = _basicExpressionCheckers
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = _qualifiedAccessCheckers
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker>
get() = _qualifiedAccessExpressionCheckers
override val callCheckers: Set<FirCallChecker>
@@ -81,7 +79,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _classReferenceExpressionCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
private val _qualifiedAccessExpressionCheckers: MutableSet<FirQualifiedAccessExpressionChecker> = mutableSetOf()
private val _callCheckers: MutableSet<FirCallChecker> = mutableSetOf()
private val _functionCallCheckers: MutableSet<FirFunctionCallChecker> = 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
@@ -18,7 +18,6 @@ abstract class ExpressionCheckers {
}
open val basicExpressionCheckers: Set<FirBasicExpressionChecker> = emptySet()
open val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = emptySet()
open val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> = emptySet()
open val callCheckers: Set<FirCallChecker> = emptySet()
open val functionCallCheckers: Set<FirFunctionCallChecker> = emptySet()
@@ -52,13 +51,12 @@ abstract class ExpressionCheckers {
open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> by lazy { basicExpressionCheckers }
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> by lazy { qualifiedAccessCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allCallCheckers: Set<FirCallChecker> by lazy { callCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers }
@CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker> by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set<FirIntegerLiteralOperatorCallChecker> by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers + callCheckers }
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> by lazy { variableAssignmentCheckers + qualifiedAccessCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> by lazy { functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allPropertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker> by lazy { propertyAccessExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allIntegerLiteralOperatorCallCheckers: Set<FirIntegerLiteralOperatorCallChecker> by lazy { integerLiteralOperatorCallCheckers + functionCallCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> by lazy { variableAssignmentCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> by lazy { tryExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> by lazy { whenExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allLoopExpressionCheckers: Set<FirLoopExpressionChecker> by lazy { loopExpressionCheckers + basicExpressionCheckers }
@@ -77,8 +75,8 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allTypeOperatorCallCheckers: Set<FirTypeOperatorCallChecker> by lazy { typeOperatorCallCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allResolvedQualifierCheckers: Set<FirResolvedQualifierChecker> by lazy { resolvedQualifierCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allConstExpressionCheckers: Set<FirConstExpressionChecker> by lazy { constExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allWhileLoopCheckers: Set<FirWhileLoopChecker> by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allThrowExpressionCheckers: Set<FirThrowExpressionChecker> by lazy { throwExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.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<FirStatement>
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccess>
typealias FirQualifiedAccessExpressionChecker = FirExpressionChecker<FirQualifiedAccessExpression>
typealias FirCallChecker = FirExpressionChecker<FirCall>
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
@@ -123,7 +123,7 @@ object FirErrors {
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<PsiElement>()
val NOT_A_LOOP_LABEL by error0<PsiElement>()
val BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY by error0<KtExpressionWithLabel>()
val VARIABLE_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.ASSIGNMENT_LHS)
val VARIABLE_EXPECTED by error0<PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val DELEGATION_IN_INTERFACE by error0<PsiElement>()
val DELEGATION_NOT_TO_INTERFACE by error0<PsiElement>()
val NESTED_CLASS_NOT_ALLOWED by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -140,7 +140,7 @@ object FirErrors {
val VAL_OR_VAR_ON_FUN_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val VAL_OR_VAR_ON_CATCH_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.ASSIGNMENT_LHS)
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Unresolved
val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -607,11 +607,11 @@ object FirErrors {
val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirValueParameterSymbol>()
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirEnumEntrySymbol>()
val UNINITIALIZED_ENUM_COMPANION by error1<KtExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>()
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField)
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val VAL_REASSIGNMENT_VIA_BACKING_FIELD by deprecationError1<KtExpression, FirBackingFieldSymbol>(RestrictionOfValReassignmentViaBackingField, SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val CAPTURED_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
val CAPTURED_MEMBER_VAL_INITIALIZATION by error1<KtExpression, FirPropertySymbol>()
val SETTER_PROJECTED_OUT by error1<KtBinaryExpression, FirPropertySymbol>(SourceElementPositioningStrategies.ASSIGNMENT_LHS)
val SETTER_PROJECTED_OUT by error1<KtBinaryExpression, FirPropertySymbol>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val WRONG_INVOCATION_KIND by warning3<PsiElement, FirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
val LEAKED_IN_PLACE_LAMBDA by warning1<PsiElement, FirBasedSymbol<*>>()
val WRONG_IMPLIES_CONDITION by warning0<PsiElement>()
@@ -22,11 +22,8 @@ import org.jetbrains.kotlin.fir.contracts.effects
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.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
@@ -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<FirPropertySymbol, FirDeclaration?>,
) {
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)
}
}
@@ -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)
}
@@ -22,7 +22,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirUnderscoreChecker,
FirExpressionAnnotationChecker,
FirDeprecationChecker,
FirRecursiveProblemChecker
FirRecursiveProblemChecker,
FirOptInUsageAccessChecker,
)
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
@@ -30,11 +31,6 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirThrowExpressionTypeChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = setOf(
FirOptInUsageAccessChecker,
)
override val qualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker>
get() = setOf(
FirCallableReferenceChecker,
@@ -83,7 +79,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
get() = setOf(
FirReassignmentAndInvisibleSetterChecker,
FirAssignmentTypeMismatchChecker
FirAssignmentTypeMismatchChecker,
)
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
@@ -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
}
@@ -31,7 +31,7 @@ abstract class CheckerContext : MutableDiagnosticContext() {
// Context
abstract val implicitReceiverStack: ImplicitReceiverStack
abstract val containingDeclarations: List<FirDeclaration>
abstract val qualifiedAccessOrAnnotationCalls: List<FirStatement>
abstract val qualifiedAccessOrAssignmentsOrAnnotationCalls: List<FirStatement>
abstract val getClassCalls: List<FirGetClassCall>
abstract val annotationContainers: List<FirAnnotationContainer>
abstract val isContractBody: Boolean
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.name.Name
class MutableCheckerContext private constructor(
override val implicitReceiverStack: PersistentImplicitReceiverStack,
override val containingDeclarations: MutableList<FirDeclaration>,
override val qualifiedAccessOrAnnotationCalls: MutableList<FirStatement>,
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: MutableList<FirStatement>,
override val getClassCalls: MutableList<FirGetClassCall>,
override val annotationContainers: MutableList<FirAnnotationContainer>,
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,
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.Name
class PersistentCheckerContext private constructor(
override val implicitReceiverStack: PersistentImplicitReceiverStack,
override val containingDeclarations: PersistentList<FirDeclaration>,
override val qualifiedAccessOrAnnotationCalls: PersistentList<FirStatement>,
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement>,
override val getClassCalls: PersistentList<FirGetClassCall>,
override val annotationContainers: PersistentList<FirAnnotationContainer>,
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,
@@ -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() =
@@ -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
@@ -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)
}
@@ -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,
@@ -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 ->
@@ -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(
@@ -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)
}
}
}
@@ -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<FirPropertyAccessor> { 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.
@@ -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
@@ -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()
@@ -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
@@ -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
}
}
}
@@ -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
@@ -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 })
) {
@@ -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 }
}
@@ -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)
@@ -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)
}
@@ -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()
@@ -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())
@@ -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)
}
}
@@ -78,7 +78,14 @@ internal fun <T : IrElement> KtSourceElement?.convertWithOffsets(
return f(startOffset, endOffset)
}
internal fun <T : IrElement> FirQualifiedAccess.convertWithOffsets(
internal fun <T : IrElement> FirQualifiedAccessExpression.convertWithOffsets(
f: (startOffset: Int, endOffset: Int) -> T
): T {
return convertWithOffsets(this.calleeReference, f)
}
internal fun <T : IrElement> FirStatement.convertWithOffsets(
calleeReference: FirReference,
f: (startOffset: Int, endOffset: Int) -> T
): 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) {
@@ -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(
@@ -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
@@ -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
@@ -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
@@ -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 =
@@ -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()
}
/**
@@ -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))
@@ -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) {
@@ -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<T>(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<T>(val baseSession: FirSession, val context: Conte
* }
*
*/
@OptIn(FirContractViolation::class)
private fun generateIncrementOrDecrementBlockForQualifiedAccess(
wholeExpression: T,
operationReference: T?,
@@ -708,7 +710,7 @@ abstract class BaseFirBuilder<T>(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<T>(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<T>(val baseSession: FirSession, val context: Conte
if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements
statements += buildVariableAssignment {
source = desugaredSource
lValue = buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().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<T>(val baseSession: FirSession, val context: Conte
}
}
private fun FirQualifiedAccessBuilder.initializeLValue(
left: T?,
convertQualified: T.() -> FirQualifiedAccess?
): FirReference {
val tokenType = left?.elementType
if (left != null) {
when (tokenType) {
REFERENCE_EXPRESSION -> {
return buildSimpleNamedReference {
source = left.toFirSourceElement()
name = left.getReferencedNameAsName()
}
}
THIS_EXPRESSION -> {
return buildExplicitThisReference {
source = left.toFirSourceElement()
labelName = left.getLabelName()
}
}
DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> {
val firMemberAccess = left.convertQualified()
return if (firMemberAccess != null) {
explicitReceiver = firMemberAccess.explicitReceiver
firMemberAccess.calleeReference
} else {
buildErrorNamedReference {
source = left.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported qualified LValue: ${left.asText}", DiagnosticKind.Syntax)
}
}
}
}
}
return buildErrorNamedReference {
source = left?.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported LValue: $tokenType", DiagnosticKind.VariableExpected)
}
}
// T is a PSI or a light-tree node
@OptIn(FirContractViolation::class)
fun T?.generateAssignment(
baseSource: KtSourceElement?,
arrayAccessSource: KtSourceElement?,
@@ -1010,10 +974,18 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
val assignmentLValue = unwrappedLhs.convert()
return buildVariableAssignment {
source = baseSource
lValue = if (baseSource?.kind == KtFakeSourceElementKind.DesugaredIncrementOrDecrement) {
buildDesugaredAssignmentValueReferenceExpression {
expressionRef = FirExpressionRef<FirExpression>().apply { bind(assignmentLValue) }
source = assignmentLValue.source?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
}
} else {
assignmentLValue
}
rValue = rhsExpression
calleeReference = initializeLValue(unwrappedLhs) { convert() as? FirQualifiedAccess }
this.annotations += annotations
}
}
@@ -1025,13 +997,12 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
rhsExpression: FirExpression,
annotations: List<FirAnnotation>
): 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<T>(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
@@ -531,7 +531,7 @@ private fun FirExpression.checkReceiver(name: String?): Boolean {
// this = .f(...)
// receiver = <expr>
// Returns safe call <expr>?.{ 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<FirExpression>().apply {
@@ -555,7 +555,7 @@ fun FirQualifiedAccess.createSafeCall(receiver: FirExpression, source: KtSourceE
// Turns (a?.b).f(...) to a?.{ b.f(...) ) -- for any qualified access `.f(...)`
// 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
@@ -121,8 +121,8 @@ class FirCallResolver(
)
/** WARNING: This function is public for the analysis API and should only be used there. */
fun <T : FirQualifiedAccess> collectAllCandidates(
qualifiedAccess: T,
fun collectAllCandidates(
qualifiedAccess: FirQualifiedAccessExpression,
name: Name,
containingDeclarations: List<FirDeclaration> = 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 <T : FirQualifiedAccess> collectCandidates(
qualifiedAccess: T,
private fun collectCandidates(
qualifiedAccess: FirQualifiedAccessExpression,
name: Name,
forceCallKind: CallKind? = null,
origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular,
containingDeclarations: List<FirDeclaration> = 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 <T : FirQualifiedAccess> 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 <T : FirQualifiedAccess> resolveVariableAccessAndSelectCandidateImpl(
qualifiedAccess: T,
private fun resolveVariableAccessAndSelectCandidateImpl(
qualifiedAccess: FirQualifiedAccessExpression,
isUsedAsReceiver: Boolean,
acceptCandidates: (Collection<Candidate>) -> Boolean
callSite: FirElement = qualifiedAccess,
acceptCandidates: (Collection<Candidate>) -> 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
}
@@ -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
@@ -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 <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
return when (val newCallee = access.calleeReference) {
val calleeReference = access.calleeReference
return typeFromCallee(access, calleeReference)
}
fun BodyResolveComponents.typeFromCallee(access: FirElement, calleeReference: FirReference): FirResolvedTypeRef {
return when (calleeReference) {
is FirErrorNamedReference ->
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 <T : FirResolvable> 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 <T : FirExpression> BodyResolveComponents.transformExpressionUsingSmartcastInfo(
expression: T,
stability: PropertyStability,
@@ -528,22 +531,15 @@ fun FirAnnotation.getCorrespondingClassSymbolOrNull(session: FirSession): FirReg
}
}
fun <T> BodyResolveComponents.initialTypeOfCandidate(
candidate: Candidate,
call: T
): ConeKotlinType where T : FirResolvable, T : FirStatement {
return initialTypeOfCandidate(candidate, typeFromCallee(call))
}
fun BodyResolveComponents.initialTypeOfCandidate(candidate: Candidate): ConeKotlinType {
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? =
@@ -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<FirTypeRef>,
containingCall: FirQualifiedAccess,
containingCall: FirQualifiedAccessExpression,
): List<ConeKotlinType> {
val supertypes = superTypeRefs.map { (it as FirResolvedTypeRef).type }
val isMethodOfAny = containingCall is FirFunctionCall && isCallingMethodOfAny(containingCall)
@@ -794,9 +794,17 @@ abstract class FirDataFlowAnalyzer(
graphBuilder.exitStringConcatenationCall(call).mergeIncomingFlow()
}
private fun FirQualifiedAccess.orderedArguments(callee: FirFunction): Array<out FirExpression?>? {
val receiver = extensionReceiver.takeIf { it != FirNoReceiverExpression }
?: dispatchReceiver.takeIf { it != FirNoReceiverExpression }
private fun FirStatement.orderedArguments(callee: FirFunction): Array<out FirExpression?>? {
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())
}
@@ -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) {
@@ -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)
@@ -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)
}
@@ -81,7 +81,8 @@ class FirCallCompleter(
)
private fun <T> 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)
@@ -83,7 +83,7 @@ class FirCallCompletionResultsWriterTransformer(
}
}
private fun <T : FirQualifiedAccess> prepareQualifiedTransform(
private fun <T : FirQualifiedAccessExpression> 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<FirTypeProjection> {
val typeArguments = computeTypeArgumentTypes(candidate)
@@ -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
@@ -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")
@@ -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 <Q : FirQualifiedAccess> transformExplicitReceiver(qualifiedAccessExpression: Q): Q {
fun <Q : FirQualifiedAccessExpression> 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<FirExpression>().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 <T> 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)
}
}
}
@@ -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)
}
@@ -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<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
when (val receiverFir = receiverSymbol.fir) {
@@ -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)}"
@@ -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 ||
@@ -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 {
@@ -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<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
@@ -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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -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<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection>
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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirDesugaredAssignmentValueReferenceExpression : FirExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract val expressionRef: FirExpressionRef<FirExpression>
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDesugaredAssignmentValueReferenceExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformDesugaredAssignmentValueReferenceExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirDesugaredAssignmentValueReferenceExpression
}
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/
abstract class FirFunctionCall : FirQualifiedAccessExpression(), FirCall {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
@@ -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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -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<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
@@ -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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -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<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection>
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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -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<FirAnnotation>
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<ConeDiagnostic>
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitPropertyAccessExpression(this, data)
@@ -37,9 +37,6 @@ abstract class FirPropertyAccessExpression : FirQualifiedAccessExpression() {
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
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<FirAnnotation>)
@@ -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<ConeDiagnostic>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirPropertyAccessExpression
@@ -1,60 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.FirImplementationDetail
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
interface FirQualifiedAccess : FirResolvable, FirStatement, FirContextReceiverArgumentListOwner {
override val calleeReference: FirReference
override val annotations: List<FirAnnotation>
override val contextReceiverArguments: List<FirExpression>
val typeArguments: List<FirTypeProjection>
val explicitReceiver: FirExpression?
val dispatchReceiver: FirExpression
val extensionReceiver: FirExpression
override val source: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedAccess(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformQualifiedAccess(this, data) as E
override fun replaceCalleeReference(newCalleeReference: FirReference)
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>)
fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
fun replaceSource(newSource: KtSourceElement?)
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
}
@@ -18,16 +18,16 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
* DO NOT MODIFY IT MANUALLY
*/
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<FirAnnotation>
abstract override val calleeReference: FirReference
abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract val typeArguments: List<FirTypeProjection>
abstract val explicitReceiver: FirExpression?
abstract val dispatchReceiver: FirExpression
abstract val extensionReceiver: FirExpression
abstract override val source: KtSourceElement?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitQualifiedAccessExpression(this, data)
@@ -35,9 +35,6 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -46,19 +43,22 @@ abstract class FirQualifiedAccessExpression : FirExpression(), FirQualifiedAcces
abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract override fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
abstract fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
abstract fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract fun replaceSource(newSource: KtSourceElement?)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
abstract fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirQualifiedAccessExpression
}
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.FirImplementationDetail
*/
abstract class FirThisReceiverExpression : FirQualifiedAccessExpression() {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
@@ -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 <E : FirElement, D> transform(transformer: FirTransformer<D>, 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<FirAnnotation>)
@@ -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)
@@ -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<FirAnnotation>
abstract override val contextReceiverArguments: List<FirExpression>
abstract override val typeArguments: List<FirTypeProjection>
abstract override val explicitReceiver: FirExpression?
abstract override val dispatchReceiver: FirExpression
abstract override val extensionReceiver: FirExpression
abstract class FirVariableAssignment : FirPureAbstractElement(), FirStatement {
abstract override val source: KtSourceElement?
abstract val lValue: FirReference
abstract val lValueTypeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract val lValue: FirExpression
abstract val rValue: FirExpression
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitVariableAssignment(this, data)
@@ -38,32 +27,13 @@ abstract class FirVariableAssignment : FirPureAbstractElement(), FirQualifiedAcc
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformVariableAssignment(this, data) as E
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun replaceContextReceiverArguments(newContextReceiverArguments: List<FirExpression>)
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
abstract override fun replaceDispatchReceiver(newDispatchReceiver: FirExpression)
abstract override fun replaceExtensionReceiver(newExtensionReceiver: FirExpression)
@FirImplementationDetail
abstract override fun replaceSource(newSource: KtSourceElement?)
abstract fun replaceLValueTypeRef(newLValueTypeRef: FirTypeRef)
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract fun replaceLValue(newLValue: FirExpression)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract fun <D> transformLValue(transformer: FirTransformer<D>, data: D): FirVariableAssignment
abstract fun <D> transformRValue(transformer: FirTransformer<D>, data: D): FirVariableAssignment
}
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.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<FirAnnotation>
abstract override val contextReceiverArguments: MutableList<FirExpression>
abstract override val typeArguments: MutableList<FirTypeProjection>
@@ -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
@@ -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<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = 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,
)
@@ -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<FirAnnotation> = mutableListOf()
val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
val typeArguments: MutableList<FirTypeProjection> = 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<Int>()
override fun build(): FirComponentCall {
return FirComponentCallImpl(
source,
annotations.toMutableOrEmpty(),
contextReceiverArguments.toMutableOrEmpty(),
typeArguments.toMutableOrEmpty(),
dispatchReceiver,
extensionReceiver,
source,
argumentList,
explicitReceiver,
componentIndex,
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirDesugaredAssignmentValueReferenceExpressionImpl
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirDesugaredAssignmentValueReferenceExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var expressionRef: FirExpressionRef<FirExpression>
override fun build(): FirDesugaredAssignmentValueReferenceExpression {
return FirDesugaredAssignmentValueReferenceExpressionImpl(
source,
annotations.toMutableOrEmpty(),
expressionRef,
)
}
@Deprecated("Modification of 'typeRef' has no impact for FirDesugaredAssignmentValueReferenceExpressionBuilder", level = DeprecationLevel.HIDDEN)
override var typeRef: FirTypeRef
get() = throw IllegalStateException()
set(_) {
throw IllegalStateException()
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildDesugaredAssignmentValueReferenceExpression(init: FirDesugaredAssignmentValueReferenceExpressionBuilder.() -> Unit): FirDesugaredAssignmentValueReferenceExpression {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirDesugaredAssignmentValueReferenceExpressionBuilder().apply(init).build()
}
@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.fir.visitors.*
@FirBuilderDsl
open class FirFunctionCallBuilder : FirAbstractFunctionCallBuilder, FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val annotations: MutableList<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = 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,
@@ -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<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression
override var source: KtSourceElement? = null
override var 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,
)
@@ -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<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = 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,
@@ -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<FirAnnotation> = 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<ConeDiagnostic> = 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(),
)
}
@@ -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<FirAnnotation>
abstract val contextReceiverArguments: MutableList<FirExpression>
abstract val typeArguments: MutableList<FirTypeProjection>
@@ -29,5 +31,5 @@ interface FirQualifiedAccessBuilder {
abstract var dispatchReceiver: FirExpression
abstract var extensionReceiver: FirExpression
abstract var source: KtSourceElement?
fun build(): FirQualifiedAccess
fun build(): FirQualifiedAccessExpression
}
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.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<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = 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,
)
@@ -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<FirAnnotation> = mutableListOf()
override val contextReceiverArguments: MutableList<FirExpression> = mutableListOf()
override val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
override var explicitReceiver: FirExpression? = null
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
override var extensionReceiver: FirExpression = FirNoReceiverExpression
class FirVariableAssignmentBuilder : FirAnnotationContainerBuilder {
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = 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,
)
}

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