Refactoring. Remove ResolutionCandidateStatus.

Use diagnostics directly.
Also TowerCandidate since now know only about applicability
and not about diagnostics itself.
This commit is contained in:
Stanislav Erokhin
2017-08-15 11:55:48 +03:00
parent aca21c847d
commit 6b8293ae5b
11 changed files with 86 additions and 92 deletions
@@ -347,7 +347,7 @@ class KotlinToResolvedCallTransformer(
val newContext = context.replaceBindingTrace(trackingTrace)
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCall.kotlinCall.psiKotlinCall)
for (diagnostic in completedCall.resolutionStatus.diagnostics) {
for (diagnostic in completedCall.diagnostics) {
trackingTrace.reported = false
diagnostic.report(diagnosticReporter)
@@ -464,7 +464,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
): NewAbstractResolvedCall<D>() {
override val kotlinCall: KotlinCall get() = completedCall.kotlinCall
override fun getStatus(): ResolutionStatus = completedCall.resolutionStatus.resultingApplicability.toResolutionStatus()
override fun getStatus(): ResolutionStatus = completedCall.resultingApplicability.toResolutionStatus()
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
get() = completedCall.argumentMappingByOriginal
@@ -496,7 +496,7 @@ class NewVariableAsFunctionResolvedCallImpl(
): VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall
class StubOnlyResolvedCall<D : CallableDescriptor>(val candidate: SimpleKotlinResolutionCandidate): NewAbstractResolvedCall<D>() {
override fun getStatus() = candidate.status.resultingApplicability.toResolutionStatus()
override fun getStatus() = candidate.resultingApplicability.toResolutionStatus()
override fun getCandidateDescriptor(): D = candidate.candidateDescriptor as D
override fun getResultingDescriptor(): D = candidate.descriptorWithFreshTypes as D
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallKind
import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator
@@ -38,9 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
import org.jetbrains.kotlin.resolve.calls.context.*
import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSupport
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
@@ -176,7 +173,7 @@ class NewResolutionOldInference(
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
candidates.all { it.candidateStatus.resultingApplicability.isInapplicable }
candidates.all { it.resultingApplicability.isInapplicable }
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
@@ -204,7 +201,7 @@ class NewResolutionOldInference(
val resolvedCall = ResolvedCallImpl.create(candidate, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments)
if (candidate.descriptor.isHiddenInResolution(languageVersionSettings, basicCallContext.isSuperCall)) {
return@map MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), resolvedCall)
return@map MyCandidate(listOf(HiddenDescriptor), resolvedCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
@@ -214,16 +211,16 @@ class NewResolutionOldInference(
candidateResolver.performResolutionForCandidateCall(callCandidateResolutionContext, basicCallContext.checkArguments) // todo
val diagnostics = listOfNotNull(createPreviousResolveError(resolvedCall.status))
MyCandidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
MyCandidate(diagnostics, resolvedCall)
}
if (basicCallContext.collectAllCandidates) {
val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false)
TowerResolver.AllCandidatesCollector(), useOrder = false)
return allCandidatesResult(allCandidates)
}
val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true)
TowerResolver.SuccessfulResultCollector(), useOrder = true)
return convertToOverloadResults(processedCandidates, tracing, basicCallContext, languageVersionSettings)
}
@@ -240,7 +237,7 @@ class NewResolutionOldInference(
languageVersionSettings: LanguageVersionSettings
): OverloadResolutionResultsImpl<D> {
val resolvedCalls = candidates.map {
val (status, resolvedCall) = it
val (diagnostics, resolvedCall) = it
if (resolvedCall is VariableAsFunctionResolvedCallImpl) {
// todo hacks
tracing.bindReference(resolvedCall.variableCall.trace, resolvedCall.variableCall)
@@ -256,7 +253,7 @@ class NewResolutionOldInference(
}
if (resolvedCall.status.possibleTransformToSuccess()) {
for (error in status.diagnostics) {
for (error in diagnostics) {
when (error) {
is UnsupportedInnerClassCall -> resolvedCall.trace.report(Errors.UNSUPPORTED.on(resolvedCall.call.callElement, error.message))
is NestedClassViaInstanceReference -> tracing.nestedClassAccessViaInstanceReference(resolvedCall.trace, error.classDescriptor, resolvedCall.explicitReceiverKind)
@@ -317,13 +314,11 @@ class NewResolutionOldInference(
}
internal data class MyCandidate(
val candidateStatus: ResolutionCandidateStatus,
val diagnostics: List<KotlinCallDiagnostic>,
val resolvedCall: MutableResolvedCall<*>
) : Candidate {
override val isSuccessful: Boolean
get() = candidateStatus.resultingApplicability.isSuccess
override val status: ResolutionCandidateStatus
get() = candidateStatus
override val resultingApplicability: ResolutionCandidateApplicability = getResultApplicability(diagnostics)
override val isSuccessful get() = resultingApplicability.isSuccess
}
private inner class CandidateFactoryImpl(
@@ -358,12 +353,12 @@ class NewResolutionOldInference(
if (parameterIsDynamic != argumentIsDynamic ||
(parameterIsDynamic && !towerCandidate.descriptor.hasDynamicExtensionAnnotation())
) {
return MyCandidate(ResolutionCandidateStatus(listOf(HiddenExtensionRelatedToDynamicTypes)), candidateCall)
return MyCandidate(listOf(HiddenExtensionRelatedToDynamicTypes), candidateCall)
}
}
if (towerCandidate.descriptor.isHiddenInResolution(languageVersionSettings, basicCallContext.isSuperCall)) {
return MyCandidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall)
return MyCandidate(listOf(HiddenDescriptor), candidateCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
@@ -375,7 +370,7 @@ class NewResolutionOldInference(
val diagnostics = (towerCandidate.diagnostics +
checkInfixAndOperator(basicCallContext.call, towerCandidate.descriptor) +
createPreviousResolveError(candidateCall.status)).filterNotNull() // todo
return MyCandidate(ResolutionCandidateStatus(diagnostics), candidateCall)
return MyCandidate(diagnostics, candidateCall)
}
private fun checkInfixAndOperator(call: Call, descriptor: CallableDescriptor): List<ResolutionDiagnostic> {
@@ -403,11 +398,11 @@ class NewResolutionOldInference(
invoke.resolvedCall as MutableResolvedCall<FunctionDescriptor>,
variable.resolvedCall as MutableResolvedCall<VariableDescriptor>
)
assert(variable.candidateStatus.resultingApplicability.isSuccess) {
assert(variable.resultingApplicability.isSuccess) {
"Variable call must be success: $variable"
}
return MyCandidate(ResolutionCandidateStatus(variable.candidateStatus.diagnostics + invoke.candidateStatus.diagnostics), resolvedCallImpl)
return MyCandidate(variable.diagnostics + invoke.diagnostics, resolvedCallImpl)
}
override fun factoryForVariable(stripExplicitReceiver: Boolean): CandidateFactory<MyCandidate> {
@@ -179,7 +179,7 @@ class PSICallResolver(
1 -> {
val singleCandidate = result.single()
val isInapplicableReceiver = singleCandidate.currentStatus.resultingApplicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
val isInapplicableReceiver = singleCandidate.resultingApplicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
val resolvedCall = kotlinToResolvedCallTransformer.transformAndReport<D>(singleCandidate, context, trace.takeUnless { isInapplicableReceiver })
@@ -211,12 +211,12 @@ class PSICallResolver(
private fun Collection<ResolvedKotlinCall>.areAllCompletedAndFailed() =
all {
it is ResolvedKotlinCall.CompletedResolvedKotlinCall &&
!it.completedCall.resolutionStatus.resultingApplicability.isSuccess
!it.completedCall.resultingApplicability.isSuccess
}
private fun Collection<ResolvedKotlinCall>.areAllCompletedAndInapplicable() =
all {
val applicability = it.currentStatus.resultingApplicability
val applicability = it.resultingApplicability
applicability == ResolutionCandidateApplicability.INAPPLICABLE ||
applicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER ||
applicability == ResolutionCandidateApplicability.HIDDEN
@@ -82,7 +82,7 @@ class KotlinCallResolver(
)
}
val candidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolutionCandidates),
TowerResolver.SuccessfulResultCollector { it.status },
TowerResolver.SuccessfulResultCollector(),
useOrder = true)
return choseMostSpecific(resolutionCallbacks, expectedType, candidates)
}
@@ -42,7 +42,7 @@ class AdditionalDiagnosticReporter {
}
private fun reportSmartCastOnReceiver(
candidate: KotlinResolutionCandidate,
candidate: SimpleKotlinResolutionCandidate,
receiver: SimpleKotlinCallArgument?,
parameter: ReceiverParameterDescriptor?
): SmartCastDiagnostic? {
@@ -53,11 +53,11 @@ class AdditionalDiagnosticReporter {
// todo may be we have smart cast to Int?
return smartCastDiagnostic.takeIf {
candidate.status.diagnostics.filterIsInstance<UnsafeCallError>().none {
candidate.getCandidateDiagnostics().filterIsInstance<UnsafeCallError>().none {
it.receiver == receiver
}
&&
candidate.status.diagnostics.filterIsInstance<UnstableSmartCast>().none {
candidate.getCandidateDiagnostics().filterIsInstance<UnstableSmartCast>().none {
it.argument == receiver
}
}
@@ -72,7 +72,7 @@ class AdditionalDiagnosticReporter {
for (argument in candidate.argumentMappingByOriginal[parameter.original]?.arguments ?: continue) {
val smartCastDiagnostic = createSmartCastDiagnostic(argument, argument.getExpectedType(parameter)) ?: continue
val thereIsUnstableSmartCastError = candidate.status.diagnostics.filterIsInstance<UnstableSmartCast>().any {
val thereIsUnstableSmartCastError = candidate.getCandidateDiagnostics().filterIsInstance<UnstableSmartCast>().any {
it.argument == argument
}
@@ -68,9 +68,10 @@ class CallableReferenceCandidate(
val explicitReceiverKind: ExplicitReceiverKind,
val reflectionCandidateType: UnwrappedType,
val numDefaults: Int,
override val status: ResolutionCandidateStatus
val diagnostics: List<KotlinCallDiagnostic>
) : Candidate {
override val isSuccessful get() = status.resultingApplicability.isSuccess
override val resultingApplicability = getResultApplicability(diagnostics)
override val isSuccessful get() = resultingApplicability.isSuccess
}
/**
@@ -184,9 +185,9 @@ class CallableReferencesCandidateFactory(
}
if (candidateDescriptor !is CallableMemberDescriptor) {
val status = ResolutionCandidateStatus(listOf(NotCallableMemberReference(argument, candidateDescriptor)))
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults, status)
explicitReceiverKind, reflectionCandidateType, defaults,
listOf(NotCallableMemberReference(argument, candidateDescriptor)))
}
diagnostics.addAll(towerCandidate.diagnostics)
@@ -205,7 +206,7 @@ class CallableReferencesCandidateFactory(
}
return CallableReferenceCandidate(candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver,
explicitReceiverKind, reflectionCandidateType, defaults, ResolutionCandidateStatus(diagnostics))
explicitReceiverKind, reflectionCandidateType, defaults, diagnostics)
}
private fun getArgumentAndReturnTypeUseMappingByExpectedType(
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
import org.jetbrains.kotlin.resolve.calls.inference.substituteAndApproximateCapturedTypes
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
import org.jetbrains.kotlin.types.TypeApproximator
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.TypeUtils
@@ -104,9 +103,9 @@ class KotlinCallCompleter(
resolutionCallbacks: KotlinResolutionCallbacks
): ResolvedKotlinCall.CompletedResolvedKotlinCall {
val currentSubstitutor = c.buildResultingSubstitutor()
val completedCall = candidate.toCompletedCall(currentSubstitutor)
val completedCall = candidate.toCompletedCall(currentSubstitutor, isTopLevel = true)
val competedCalls = c.innerCalls.map {
it.candidate.toCompletedCall(currentSubstitutor)
it.candidate.toCompletedCall(currentSubstitutor, isTopLevel = false)
}
for (postponedArgument in c.postponedArguments) {
when (postponedArgument) {
@@ -125,17 +124,17 @@ class KotlinCallCompleter(
return ResolvedKotlinCall.CompletedResolvedKotlinCall(completedCall, competedCalls, c.lambdaArguments)
}
private fun KotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall {
private fun KotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor, isTopLevel: Boolean): CompletedKotlinCall {
if (this is VariableAsFunctionKotlinResolutionCandidate) {
val variable = resolvedVariable.toCompletedCall(substitutor)
val invoke = invokeCandidate.toCompletedCall(substitutor)
val variable = resolvedVariable.toCompletedCall(substitutor, isTopLevel = false)
val invoke = invokeCandidate.toCompletedCall(substitutor, isTopLevel)
return CompletedKotlinCall.VariableAsFunction(kotlinCall, variable, invoke)
}
return (this as SimpleKotlinResolutionCandidate).toCompletedCall(substitutor)
return (this as SimpleKotlinResolutionCandidate).toCompletedCall(substitutor, isTopLevel)
}
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor): CompletedKotlinCall.Simple {
private fun SimpleKotlinResolutionCandidate.toCompletedCall(substitutor: NewTypeSubstitutor, isTopLevel: Boolean): CompletedKotlinCall.Simple {
val containsCapturedTypes = descriptorWithFreshTypes.returnType?.contains { it is NewCapturedType } ?: false
val resultingDescriptor = when {
descriptorWithFreshTypes is FunctionDescriptor ||
@@ -152,15 +151,22 @@ class KotlinCallCompleter(
TypeApproximator().approximateToSuperType(substituted, TypeApproximatorConfiguration.CapturedTypesApproximation) ?: substituted
}
val status = computeStatus(this, resultingDescriptor)
return CompletedKotlinCall.Simple(kotlinCall, candidateDescriptor, resultingDescriptor, status, explicitReceiverKind,
val diagnostics = computeDiagnostics(this, resultingDescriptor, isTopLevel)
return CompletedKotlinCall.Simple(kotlinCall, candidateDescriptor, resultingDescriptor, diagnostics, explicitReceiverKind,
dispatchReceiverArgument?.receiver, extensionReceiver?.receiver, typeArguments, argumentMappingByOriginal)
}
private fun computeStatus(candidate: SimpleKotlinResolutionCandidate, resultingDescriptor: CallableDescriptor): ResolutionCandidateStatus {
val smartCasts = additionalDiagnosticReporter.createAdditionalDiagnostics(candidate, resultingDescriptor).takeIf { it.isNotEmpty() } ?:
return candidate.status
return ResolutionCandidateStatus(candidate.status.diagnostics + smartCasts)
private fun computeDiagnostics(
candidate: SimpleKotlinResolutionCandidate,
resultingDescriptor: CallableDescriptor,
isTopLevel: Boolean
): List<KotlinCallDiagnostic> {
var diagnostics = candidate.getCandidateDiagnostics()
if (isTopLevel) {
diagnostics += candidate.constraintSystem.diagnostics
}
diagnostics += additionalDiagnosticReporter.createAdditionalDiagnostics(candidate, resultingDescriptor)
return diagnostics
}
// true if we should complete this call
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.Candidate
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.types.TypeSubstitutor
import java.util.*
@@ -49,8 +46,8 @@ class VariableAsFunctionKotlinResolutionCandidate(
val invokeCandidate: SimpleKotlinResolutionCandidate
) : KotlinResolutionCandidate() {
override val isSuccessful: Boolean get() = resolvedVariable.isSuccessful && invokeCandidate.isSuccessful
override val status: ResolutionCandidateStatus
get() = ResolutionCandidateStatus(resolvedVariable.status.diagnostics + invokeCandidate.status.diagnostics)
override val resultingApplicability: ResolutionCandidateApplicability
get() = maxOf(resolvedVariable.resultingApplicability, invokeCandidate.resultingApplicability)
override val lastCall: SimpleKotlinResolutionCandidate get() = invokeCandidate
}
@@ -65,15 +62,10 @@ sealed class AbstractSimpleKotlinResolutionCandidate(
return !hasErrors
}
private var _status: ResolutionCandidateStatus? = null
override val status: ResolutionCandidateStatus
override val resultingApplicability: ResolutionCandidateApplicability
get() {
if (_status == null) {
process(stopOnFirstError = false)
_status = ResolutionCandidateStatus(diagnostics + constraintSystem.diagnostics)
}
return _status!!
process(stopOnFirstError = false)
return getResultApplicability(diagnostics + constraintSystem.diagnostics)
}
private val diagnostics = ArrayList<KotlinCallDiagnostic>()
@@ -100,6 +92,7 @@ sealed class AbstractSimpleKotlinResolutionCandidate(
addDiagnostics(initialDiagnostics)
}
fun getCandidateDiagnostics(): List<KotlinCallDiagnostic> = diagnostics
abstract val resolutionSequence: List<ResolutionPart>
}
@@ -19,49 +19,50 @@ package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.getResultApplicability
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType
sealed class ResolvedKotlinCall {
abstract val currentStatus: ResolutionCandidateStatus
abstract val resultingApplicability: ResolutionCandidateApplicability
class CompletedResolvedKotlinCall(
val completedCall: CompletedKotlinCall,
val allInnerCalls: Collection<CompletedKotlinCall>,
val lambdaArguments: List<PostponedLambdaArgument>
): ResolvedKotlinCall() {
override val currentStatus get() = completedCall.resolutionStatus
override val resultingApplicability get() = completedCall.resultingApplicability
}
class OnlyResolvedKotlinCall(val candidate: KotlinResolutionCandidate) : ResolvedKotlinCall() {
override val currentStatus get() = candidate.status
override val resultingApplicability get() = candidate.resultingApplicability
}
}
sealed class CompletedKotlinCall {
abstract val resolutionStatus: ResolutionCandidateStatus
abstract val resultingApplicability: ResolutionCandidateApplicability
class Simple(
val kotlinCall: KotlinCall,
val candidateDescriptor: CallableDescriptor,
val resultingDescriptor: CallableDescriptor,
override val resolutionStatus: ResolutionCandidateStatus,
val diagnostics: List<KotlinCallDiagnostic>,
val explicitReceiverKind: ExplicitReceiverKind,
val dispatchReceiver: ReceiverValueWithSmartCastInfo?,
val extensionReceiver: ReceiverValueWithSmartCastInfo?,
val typeArguments: List<UnwrappedType>,
val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
): CompletedKotlinCall()
): CompletedKotlinCall() {
override val resultingApplicability = getResultApplicability(diagnostics)
}
class VariableAsFunction(
val kotlinCall: KotlinCall,
val variableCall: Simple,
val invokeCall: Simple
): CompletedKotlinCall() {
override val resolutionStatus: ResolutionCandidateStatus =
ResolutionCandidateStatus(variableCall.resolutionStatus.diagnostics + invokeCall.resolutionStatus.diagnostics)
override val resultingApplicability get() = maxOf(variableCall.resultingApplicability, invokeCall.resultingApplicability)
}
}
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -60,10 +60,8 @@ interface CandidateWithBoundDispatchReceiver {
val dispatchReceiver: ReceiverValueWithSmartCastInfo?
}
data class ResolutionCandidateStatus(val diagnostics: List<KotlinCallDiagnostic>) {
val resultingApplicability: ResolutionCandidateApplicability = diagnostics.asSequence().map { it.candidateApplicability }.max()
?: RESOLVED
}
fun getResultApplicability(diagnostics: List<KotlinCallDiagnostic>) = diagnostics.maxBy { it.candidateApplicability }?.candidateApplicability
?: RESOLVED
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
@@ -28,7 +28,7 @@ interface Candidate {
// this operation should be very fast
val isSuccessful: Boolean
val status: ResolutionCandidateStatus
val resultingApplicability: ResolutionCandidateApplicability
}
interface CandidateFactory<out C: Candidate> {
@@ -75,13 +75,13 @@ class TowerResolver {
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>,
useOrder: Boolean
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector { it.status }, useOrder)
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder)
fun <C: Candidate> collectAllCandidates(
scopeTower: ImplicitScopeTower,
processor: ScopeTowerProcessor<C>
): Collection<C>
= scopeTower.run(processor, AllCandidatesCollector { it.status }, false)
= scopeTower.run(processor, AllCandidatesCollector(), false)
private fun ImplicitScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>()
@@ -100,7 +100,7 @@ class TowerResolver {
return result
}
private fun <C> ImplicitScopeTower.run(
private fun <C : Candidate> ImplicitScopeTower.run(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
@@ -173,13 +173,13 @@ class TowerResolver {
return resultCollector.getFinalCandidates()
}
fun <C> runWithEmptyTowerData(
fun <C : Candidate> runWithEmptyTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> = processTowerData(processor, resultCollector, useOrder, TowerData.Empty) ?: resultCollector.getFinalCandidates()
private fun <C> processTowerData(
private fun <C : Candidate> processTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
@@ -203,14 +203,14 @@ class TowerResolver {
}
abstract class ResultCollector<C>(protected val getStatus: (C) -> ResolutionCandidateStatus) {
abstract class ResultCollector<C : Candidate> {
abstract fun getSuccessfulCandidates(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
fun pushCandidates(candidates: Collection<C>) {
val filteredCandidates = candidates.filter {
getStatus(it).resultingApplicability != ResolutionCandidateApplicability.HIDDEN
it.resultingApplicability != ResolutionCandidateApplicability.HIDDEN
}
if (filteredCandidates.isNotEmpty()) addCandidates(filteredCandidates)
}
@@ -218,7 +218,7 @@ class TowerResolver {
protected abstract fun addCandidates(candidates: Collection<C>)
}
class AllCandidatesCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
class AllCandidatesCollector<C : Candidate>: ResultCollector<C>() {
private val allCandidates = ArrayList<C>()
override fun getSuccessfulCandidates(): Collection<C>? = null
@@ -230,7 +230,7 @@ class TowerResolver {
}
}
class SuccessfulResultCollector<C>(getStatus: (C) -> ResolutionCandidateStatus): ResultCollector<C>(getStatus) {
class SuccessfulResultCollector<C : Candidate>: ResultCollector<C>() {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
@@ -247,10 +247,10 @@ class TowerResolver {
override fun getFinalCandidates() = getResolved() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList()
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!!
val minimalLevel = candidates.map { it.resultingApplicability }.min()!!
if (currentLevel == null || currentLevel!! > minimalLevel) {
currentLevel = minimalLevel
currentCandidates = candidates.filter { getStatus(it).resultingApplicability == minimalLevel }
currentCandidates = candidates.filter { it.resultingApplicability == minimalLevel }
}
}
}