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:
committed by
Space Team
parent
e9b8d6db80
commit
ace47c06a5
+2
-2
@@ -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(
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
+71
-44
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+3
-3
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+8
-2
@@ -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(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
-1
@@ -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")
|
||||
|
||||
+5
-5
@@ -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> {
|
||||
|
||||
-1
@@ -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,
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ object JsExpressionCheckers : ExpressionCheckers() {
|
||||
FirJsQualifierChecker,
|
||||
)
|
||||
|
||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||
get() = setOf(
|
||||
FirJsDefinedExternallyCallChecker,
|
||||
FirJsDefinedExternallyCallChecker
|
||||
)
|
||||
}
|
||||
|
||||
+9
-6
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
)
|
||||
|
||||
+15
-10
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
-4
@@ -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
|
||||
|
||||
+7
-9
@@ -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 }
|
||||
|
||||
-2
@@ -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>
|
||||
|
||||
+5
-5
@@ -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>()
|
||||
|
||||
+2
-5
@@ -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
|
||||
|
||||
+9
-7
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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)
|
||||
}
|
||||
|
||||
+3
-7
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+5
-5
@@ -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,
|
||||
|
||||
+8
-8
@@ -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,
|
||||
|
||||
+1
-1
@@ -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() =
|
||||
|
||||
+15
-10
@@ -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
|
||||
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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 ->
|
||||
|
||||
+8
-8
@@ -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(
|
||||
|
||||
+19
-15
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-17
@@ -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.
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-2
@@ -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()
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+3
-3
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
|
||||
+2
-1
@@ -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 })
|
||||
) {
|
||||
|
||||
+5
-5
@@ -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 }
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+5
-1
@@ -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)
|
||||
}
|
||||
|
||||
+4
-11
@@ -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()
|
||||
|
||||
-4
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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(
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+4
-1
@@ -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
|
||||
|
||||
+20
-17
@@ -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 =
|
||||
|
||||
+4
-4
@@ -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))
|
||||
|
||||
+4
-9
@@ -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) {
|
||||
|
||||
+28
-57
@@ -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
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+20
-12
@@ -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())
|
||||
}
|
||||
|
||||
+2
-1
@@ -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) {
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -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)
|
||||
|
||||
+4
-27
@@ -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)
|
||||
|
||||
+7
@@ -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
|
||||
|
||||
+2
-3
@@ -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")
|
||||
|
||||
+107
-72
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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)
|
||||
}
|
||||
|
||||
+5
-4
@@ -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) {
|
||||
|
||||
+2
-4
@@ -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 ||
|
||||
|
||||
-4
@@ -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 {
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+36
@@ -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)
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+4
-4
@@ -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
|
||||
}
|
||||
+15
-15
@@ -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
|
||||
}
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+5
-35
@@ -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
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+4
-4
@@ -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,
|
||||
)
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+59
@@ -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()
|
||||
}
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+2
-2
@@ -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,
|
||||
)
|
||||
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+4
-4
@@ -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(),
|
||||
)
|
||||
}
|
||||
|
||||
+5
-3
@@ -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
|
||||
}
|
||||
+4
-4
@@ -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,
|
||||
)
|
||||
|
||||
+5
-22
@@ -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
Reference in New Issue
Block a user