FIR: refactor FirExpressionsResolveTransformer#transformAssignmentOperatorStatement

No logic change. This commit only rearrange stuff to make it cleaner
This commit is contained in:
Tianyu Geng
2021-04-08 17:57:39 -07:00
committed by TeamCityServer
parent 861f69822b
commit c43faa2ada
@@ -25,15 +25,18 @@ import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.inference.FirStubInferenceSession
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.ConstantValueKind
@@ -374,7 +377,8 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
assignOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
}
val assignCallReference = resolvedAssignCall.calleeReference as? FirNamedReferenceWithCandidate
val assignIsError = assignCallReference?.isError ?: true
val assignIsResolvable = assignCallReference?.isError == false
// x = x + y
val simpleOperatorName = FirOperationNameConventions.ASSIGNMENTS_TO_SIMPLE_OPERATOR.getValue(assignmentOperatorStatement.operation)
val simpleOperatorCall = createFunctionCall(simpleOperatorName)
@@ -382,57 +386,66 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
simpleOperatorCall.transformSingle(this, ResolutionMode.ContextDependent)
}
val operatorCallReference = resolvedOperatorCall.calleeReference as? FirNamedReferenceWithCandidate
val operatorIsError = operatorCallReference?.isError ?: true
val operatorIsResolvable = operatorCallReference?.isError == false
val lhsReference = leftArgument.toResolvedCallableReference()
val lhsSymbol = lhsReference?.resolvedSymbol as? FirVariableSymbol<*>
val lhsVariable = lhsSymbol?.fir
val lhsIsVar = lhsVariable?.isVar == true
return when {
operatorIsError || (!lhsIsVar && !assignIsError) -> {
callCompleter.completeCall(resolvedAssignCall, noExpectedType)
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
resolvedAssignCall
}
assignIsError -> {
callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType)
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
val assignment =
buildVariableAssignment {
source = assignmentOperatorStatement.source
rValue = resolvedOperatorCall
calleeReference = when {
lhsIsVar -> lhsReference!!
else -> buildErrorNamedReference {
source = when (leftArgument) {
is FirFunctionCall -> leftArgument.source
is FirQualifiedAccess ->
leftArgument.calleeReference.source
else -> leftArgument.source
}
diagnostic = if (lhsSymbol == null) ConeVariableExpectedError() else ConeValReassignmentError(lhsSymbol)
fun chooseAssign(): FirStatement {
callCompleter.completeCall(resolvedAssignCall, noExpectedType)
dataFlowAnalyzer.exitFunctionCall(resolvedAssignCall, callCompleted = true)
return resolvedAssignCall
}
fun chooseOperator(): FirStatement {
callCompleter.completeCall(resolvedOperatorCall, lhsVariable?.returnTypeRef ?: noExpectedType)
dataFlowAnalyzer.exitFunctionCall(resolvedOperatorCall, callCompleted = true)
val assignment =
buildVariableAssignment {
source = assignmentOperatorStatement.source
rValue = resolvedOperatorCall
calleeReference = when {
lhsIsVar -> lhsReference!!
else -> buildErrorNamedReference {
source = when (leftArgument) {
is FirFunctionCall -> leftArgument.source
is FirQualifiedAccess ->
leftArgument.calleeReference.source
else -> leftArgument.source
}
}
(leftArgument as? FirQualifiedAccess)?.let {
dispatchReceiver = it.dispatchReceiver
extensionReceiver = it.extensionReceiver
diagnostic = if (lhsSymbol == null) ConeVariableExpectedError() else ConeValReassignmentError(lhsSymbol)
}
}
assignment.transform(transformer, ResolutionMode.ContextIndependent)
}
else -> {
val operatorCallSymbol = operatorCallReference?.candidateSymbol
val assignmentCallSymbol = assignCallReference?.candidateSymbol
requireNotNull(operatorCallSymbol)
requireNotNull(assignmentCallSymbol)
buildErrorExpression {
source = assignmentOperatorStatement.source
diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol))
(leftArgument as? FirQualifiedAccess)?.let {
dispatchReceiver = it.dispatchReceiver
extensionReceiver = it.extensionReceiver
}
}
return assignment.transform(transformer, ResolutionMode.ContextIndependent)
}
fun reportAmbiguity(): FirStatement {
val operatorCallSymbol = operatorCallReference?.candidateSymbol
val assignmentCallSymbol = assignCallReference?.candidateSymbol
requireNotNull(operatorCallSymbol)
requireNotNull(assignmentCallSymbol)
return buildErrorExpression {
source = assignmentOperatorStatement.source
diagnostic = ConeOperatorAmbiguityError(listOf(operatorCallSymbol, assignmentCallSymbol))
}
}
return when {
assignIsResolvable && !lhsIsVar -> chooseAssign()
!assignIsResolvable && !operatorIsResolvable -> chooseAssign()
!assignIsResolvable && operatorIsResolvable -> chooseOperator()
assignIsResolvable && !operatorIsResolvable -> chooseAssign()
else -> reportAmbiguity()
}
}
override fun transformEqualityOperatorCall(