Extract KotlinResolutionCandidate into separate file
This commit is contained in:
+133
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.resolve.calls.model
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.Candidate
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* baseSystem contains all information from arguments, i.e. it is union of all system of arguments
|
||||||
|
* Also by convention we suppose that baseSystem has no contradiction
|
||||||
|
*/
|
||||||
|
class KotlinResolutionCandidate(
|
||||||
|
val callComponents: KotlinCallComponents,
|
||||||
|
val resolutionCallbacks: KotlinResolutionCallbacks,
|
||||||
|
val callableReferenceResolver: CallableReferenceResolver,
|
||||||
|
val scopeTower: ImplicitScopeTower,
|
||||||
|
private val baseSystem: ConstraintStorage,
|
||||||
|
val resolvedCall: MutableResolvedCallAtom,
|
||||||
|
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
|
||||||
|
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
|
||||||
|
) : Candidate, KotlinDiagnosticsHolder {
|
||||||
|
val diagnosticsFromResolutionParts = arrayListOf<KotlinCallDiagnostic>() // TODO: this is mutable list, take diagnostics only once!
|
||||||
|
private var newSystem: NewConstraintSystemImpl? = null
|
||||||
|
private var currentApplicability = CandidateApplicability.RESOLVED
|
||||||
|
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
|
||||||
|
|
||||||
|
private val stepCount = resolutionSequence.sumOf { it.run { workCount() } }
|
||||||
|
private var step = 0
|
||||||
|
|
||||||
|
fun getSystem(): NewConstraintSystem {
|
||||||
|
if (newSystem == null) {
|
||||||
|
newSystem =
|
||||||
|
NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns, callComponents.kotlinTypeRefiner)
|
||||||
|
newSystem!!.addOtherSystem(baseSystem)
|
||||||
|
}
|
||||||
|
return newSystem!!
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val csBuilder get() = getSystem().getBuilder()
|
||||||
|
|
||||||
|
override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
|
||||||
|
diagnosticsFromResolutionParts.add(diagnostic)
|
||||||
|
currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSubResolvedAtoms(): List<ResolvedAtom> = subResolvedAtoms
|
||||||
|
|
||||||
|
fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) {
|
||||||
|
subResolvedAtoms.add(resolvedAtom)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processParts(stopOnFirstError: Boolean) {
|
||||||
|
if (stopOnFirstError && step > 0) return // error already happened
|
||||||
|
if (step == stepCount) return
|
||||||
|
|
||||||
|
var partIndex = 0
|
||||||
|
var workStep = step
|
||||||
|
while (workStep > 0) {
|
||||||
|
val workCount = resolutionSequence[partIndex].run { workCount() }
|
||||||
|
if (workStep >= workCount) {
|
||||||
|
partIndex++
|
||||||
|
workStep -= workCount
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (partIndex < resolutionSequence.size) {
|
||||||
|
if (processPart(resolutionSequence[partIndex], stopOnFirstError, workStep)) return
|
||||||
|
partIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
while (partIndex < resolutionSequence.size) {
|
||||||
|
if (processPart(resolutionSequence[partIndex], stopOnFirstError)) return
|
||||||
|
partIndex++
|
||||||
|
}
|
||||||
|
if (step == stepCount) {
|
||||||
|
resolvedCall.setAnalyzedResults(subResolvedAtoms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// true if part was interrupted
|
||||||
|
private fun processPart(part: ResolutionPart, stopOnFirstError: Boolean, startWorkIndex: Int = 0): Boolean {
|
||||||
|
for (workIndex in startWorkIndex until (part.run { workCount() })) {
|
||||||
|
if (stopOnFirstError && !currentApplicability.isSuccess) return true
|
||||||
|
|
||||||
|
part.run { process(workIndex) }
|
||||||
|
step++
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val variableCandidateIfInvoke: KotlinResolutionCandidate?
|
||||||
|
get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom)
|
||||||
|
|
||||||
|
private val variableApplicability
|
||||||
|
get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED
|
||||||
|
|
||||||
|
override val isSuccessful: Boolean
|
||||||
|
get() {
|
||||||
|
processParts(stopOnFirstError = true)
|
||||||
|
return currentApplicability.isSuccess && variableApplicability.isSuccess && !getSystem().hasContradiction
|
||||||
|
}
|
||||||
|
|
||||||
|
override val resultingApplicability: CandidateApplicability
|
||||||
|
get() {
|
||||||
|
processParts(stopOnFirstError = false)
|
||||||
|
|
||||||
|
val systemApplicability = getResultApplicability(getSystem().errors)
|
||||||
|
return minOf(currentApplicability, systemApplicability, variableApplicability)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addCompatibilityWarning(other: Candidate) {
|
||||||
|
if (this !== other && other is KotlinResolutionCandidate) {
|
||||||
|
addDiagnostic(CompatibilityWarning(other.resolvedCall.candidateDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
|
||||||
|
val okOrFail = if (currentApplicability.isSuccess) "OK" else "FAIL"
|
||||||
|
val step = "$step/$stepCount"
|
||||||
|
return "$okOrFail($step): $descriptor"
|
||||||
|
}
|
||||||
|
}
|
||||||
-117
@@ -68,123 +68,6 @@ fun KotlinDiagnosticsHolder.addError(error: ConstraintSystemError) {
|
|||||||
addDiagnostic(error.asDiagnostic())
|
addDiagnostic(error.asDiagnostic())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* baseSystem contains all information from arguments, i.e. it is union of all system of arguments
|
|
||||||
* Also by convention we suppose that baseSystem has no contradiction
|
|
||||||
*/
|
|
||||||
class KotlinResolutionCandidate(
|
|
||||||
val callComponents: KotlinCallComponents,
|
|
||||||
val resolutionCallbacks: KotlinResolutionCallbacks,
|
|
||||||
val callableReferenceResolver: CallableReferenceResolver,
|
|
||||||
val scopeTower: ImplicitScopeTower,
|
|
||||||
private val baseSystem: ConstraintStorage,
|
|
||||||
val resolvedCall: MutableResolvedCallAtom,
|
|
||||||
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
|
|
||||||
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
|
|
||||||
) : Candidate, KotlinDiagnosticsHolder {
|
|
||||||
val diagnosticsFromResolutionParts = arrayListOf<KotlinCallDiagnostic>() // TODO: this is mutable list, take diagnostics only once!
|
|
||||||
private var newSystem: NewConstraintSystemImpl? = null
|
|
||||||
private var currentApplicability = CandidateApplicability.RESOLVED
|
|
||||||
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
|
|
||||||
|
|
||||||
private val stepCount = resolutionSequence.sumOf { it.run { workCount() } }
|
|
||||||
private var step = 0
|
|
||||||
|
|
||||||
fun getSystem(): NewConstraintSystem {
|
|
||||||
if (newSystem == null) {
|
|
||||||
newSystem = NewConstraintSystemImpl(callComponents.constraintInjector, callComponents.builtIns, callComponents.kotlinTypeRefiner)
|
|
||||||
newSystem!!.addOtherSystem(baseSystem)
|
|
||||||
}
|
|
||||||
return newSystem!!
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val csBuilder get() = getSystem().getBuilder()
|
|
||||||
|
|
||||||
override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
|
|
||||||
diagnosticsFromResolutionParts.add(diagnostic)
|
|
||||||
currentApplicability = minOf(diagnostic.candidateApplicability, currentApplicability)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSubResolvedAtoms(): List<ResolvedAtom> = subResolvedAtoms
|
|
||||||
|
|
||||||
fun addResolvedKtPrimitive(resolvedAtom: ResolvedAtom) {
|
|
||||||
subResolvedAtoms.add(resolvedAtom)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processParts(stopOnFirstError: Boolean) {
|
|
||||||
if (stopOnFirstError && step > 0) return // error already happened
|
|
||||||
if (step == stepCount) return
|
|
||||||
|
|
||||||
var partIndex = 0
|
|
||||||
var workStep = step
|
|
||||||
while (workStep > 0) {
|
|
||||||
val workCount = resolutionSequence[partIndex].run { workCount() }
|
|
||||||
if (workStep >= workCount) {
|
|
||||||
partIndex++
|
|
||||||
workStep -= workCount
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (partIndex < resolutionSequence.size) {
|
|
||||||
if (processPart(resolutionSequence[partIndex], stopOnFirstError, workStep)) return
|
|
||||||
partIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
while (partIndex < resolutionSequence.size) {
|
|
||||||
if (processPart(resolutionSequence[partIndex], stopOnFirstError)) return
|
|
||||||
partIndex++
|
|
||||||
}
|
|
||||||
if (step == stepCount) {
|
|
||||||
resolvedCall.setAnalyzedResults(subResolvedAtoms)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// true if part was interrupted
|
|
||||||
private fun processPart(part: ResolutionPart, stopOnFirstError: Boolean, startWorkIndex: Int = 0): Boolean {
|
|
||||||
for (workIndex in startWorkIndex until (part.run { workCount() })) {
|
|
||||||
if (stopOnFirstError && !currentApplicability.isSuccess) return true
|
|
||||||
|
|
||||||
part.run { process(workIndex) }
|
|
||||||
step++
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val variableCandidateIfInvoke: KotlinResolutionCandidate?
|
|
||||||
get() = callComponents.statelessCallbacks.getVariableCandidateIfInvoke(resolvedCall.atom)
|
|
||||||
|
|
||||||
private val variableApplicability
|
|
||||||
get() = variableCandidateIfInvoke?.resultingApplicability ?: CandidateApplicability.RESOLVED
|
|
||||||
|
|
||||||
override val isSuccessful: Boolean
|
|
||||||
get() {
|
|
||||||
processParts(stopOnFirstError = true)
|
|
||||||
return currentApplicability.isSuccess && variableApplicability.isSuccess && !getSystem().hasContradiction
|
|
||||||
}
|
|
||||||
|
|
||||||
override val resultingApplicability: CandidateApplicability
|
|
||||||
get() {
|
|
||||||
processParts(stopOnFirstError = false)
|
|
||||||
|
|
||||||
val systemApplicability = getResultApplicability(getSystem().errors)
|
|
||||||
return minOf(currentApplicability, systemApplicability, variableApplicability)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addCompatibilityWarning(other: Candidate) {
|
|
||||||
if (this !== other && other is KotlinResolutionCandidate) {
|
|
||||||
addDiagnostic(CompatibilityWarning(other.resolvedCall.candidateDescriptor))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
val descriptor = DescriptorRenderer.COMPACT.render(resolvedCall.candidateDescriptor)
|
|
||||||
val okOrFail = if (currentApplicability.isSuccess) "OK" else "FAIL"
|
|
||||||
val step = "$step/$stepCount"
|
|
||||||
return "$okOrFail($step): $descriptor"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MutableResolvedCallAtom(
|
class MutableResolvedCallAtom(
|
||||||
override val atom: KotlinCall,
|
override val atom: KotlinCall,
|
||||||
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
|
override val candidateDescriptor: CallableDescriptor, // original candidate descriptor
|
||||||
Reference in New Issue
Block a user