[NI] Refactor: create separate method for candidate preparation

This commit is contained in:
Mikhail Zarechenskiy
2018-03-15 10:11:50 +03:00
parent 8c44d44e78
commit 2235f5eb48
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
@@ -33,26 +34,24 @@ class KotlinCallCompleter(
if (candidates.size > 1) { if (candidates.size > 1) {
diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates)) diagnosticHolder.addDiagnostic(ManyCandidatesCallDiagnostic(factory.kotlinCall, candidates))
} }
val candidate = candidates.singleOrNull()
// this is needed at least for non-local return checker, because when we analyze lambda we should already bind descriptor for outer call val candidate = prepareCandidateForCompletion(factory, candidates, resolutionCallbacks)
candidate?.resolvedCall?.let { resolutionCallbacks.bindStubResolvedCallForCandidate(it) } val completionType = candidate.prepareForCompletion(expectedType, resolutionCallbacks)
if (candidate == null || candidate.csBuilder.hasContradiction) { if (ErrorUtils.isError(candidate.resolvedCall.candidateDescriptor) ||
val candidateForCompletion = candidate ?: factory.createErrorCandidate().forceResolution() candidate.csBuilder.hasContradiction
candidateForCompletion.prepareForCompletion(expectedType, resolutionCallbacks) ) {
runCompletion( runCompletion(
candidateForCompletion.resolvedCall, candidate.resolvedCall,
ConstraintSystemCompletionMode.FULL, ConstraintSystemCompletionMode.FULL,
diagnosticHolder, diagnosticHolder,
candidateForCompletion.getSystem(), candidate.getSystem(),
resolutionCallbacks resolutionCallbacks
) )
return candidate.asCallResolutionResult(CallResolutionResult.Type.ERROR, diagnosticHolder) return candidate.asCallResolutionResult(CallResolutionResult.Type.ERROR, diagnosticHolder)
} }
val completionType = candidate.prepareForCompletion(expectedType, resolutionCallbacks)
val constraintSystem = candidate.getSystem() val constraintSystem = candidate.getSystem()
runCompletion(candidate.resolvedCall, completionType, diagnosticHolder, constraintSystem, resolutionCallbacks) runCompletion(candidate.resolvedCall, completionType, diagnosticHolder, constraintSystem, resolutionCallbacks)
@@ -114,6 +113,18 @@ class KotlinCallCompleter(
constraintSystem.diagnostics.forEach(diagnosticsHolder::addDiagnostic) constraintSystem.diagnostics.forEach(diagnosticsHolder::addDiagnostic)
} }
private fun prepareCandidateForCompletion(
factory: SimpleCandidateFactory,
candidates: Collection<KotlinResolutionCandidate>,
resolutionCallbacks: KotlinResolutionCallbacks
): KotlinResolutionCandidate {
val candidate = candidates.singleOrNull()
// this is needed at least for non-local return checker, because when we analyze lambda we should already bind descriptor for outer call
candidate?.resolvedCall?.let { resolutionCallbacks.bindStubResolvedCallForCandidate(it) }
return candidate ?: factory.createErrorCandidate().forceResolution()
}
// true if we should complete this call // true if we should complete this call
private fun KotlinResolutionCandidate.prepareForCompletion( private fun KotlinResolutionCandidate.prepareForCompletion(