[NI] Make model more robust: remove diagnostics from resolution atoms
Currently there are two major phases in NI that report diagnostics: resolution parts and completion. They connected in method `KotlinCallCompleter.runCompletion` and previously diagnostics were collected in several places, from resolution atoms, partly from constraint system and partly from `CallResolutionResult`, some of them were lost. To mitigate this problem, now diagnostics are not bind to the intermediate candidate, only to the result resolution candidate (overloaded or usual one). And all diagnostics are now collected in method `runCompletion`
This commit is contained in:
+1
-2
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
|||||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallAtom
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||||
@@ -145,7 +144,7 @@ class KotlinResolutionCallbacksImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) {
|
override fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) {
|
||||||
kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(candidate, trace)
|
kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(candidate, trace, emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createReceiverWithSmartCastInfo(resolvedAtom: ResolvedCallAtom): ReceiverValueWithSmartCastInfo? {
|
override fun createReceiverWithSmartCastInfo(resolvedAtom: ResolvedCallAtom): ReceiverValueWithSmartCastInfo? {
|
||||||
|
|||||||
+60
-28
@@ -77,8 +77,9 @@ class KotlinToResolvedCallTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> onlyTransform(
|
fun <D : CallableDescriptor> onlyTransform(
|
||||||
resolvedCallAtom: ResolvedCallAtom
|
resolvedCallAtom: ResolvedCallAtom,
|
||||||
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null)
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
|
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
|
||||||
|
|
||||||
fun <D : CallableDescriptor> transformAndReport(
|
fun <D : CallableDescriptor> transformAndReport(
|
||||||
baseResolvedCall: CallResolutionResult,
|
baseResolvedCall: CallResolutionResult,
|
||||||
@@ -95,7 +96,7 @@ class KotlinToResolvedCallTransformer(
|
|||||||
|
|
||||||
context.trace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, baseResolvedCall)
|
context.trace.record(BindingContext.ONLY_RESOLVED_CALL, psiCall, baseResolvedCall)
|
||||||
|
|
||||||
return createStubResolvedCallAndWriteItToTrace(candidate, context.trace)
|
return createStubResolvedCallAndWriteItToTrace(candidate, context.trace, baseResolvedCall.diagnostics)
|
||||||
}
|
}
|
||||||
CallResolutionResult.Type.ERROR, CallResolutionResult.Type.COMPLETED -> {
|
CallResolutionResult.Type.ERROR, CallResolutionResult.Type.COMPLETED -> {
|
||||||
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor()
|
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor()
|
||||||
@@ -107,14 +108,18 @@ class KotlinToResolvedCallTransformer(
|
|||||||
ktPrimitiveCompleter.completeAll(subKtPrimitive)
|
ktPrimitiveCompleter.completeAll(subKtPrimitive)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ktPrimitiveCompleter.completeResolvedCall(candidate) as ResolvedCall<D>
|
return ktPrimitiveCompleter.completeResolvedCall(candidate, baseResolvedCall.diagnostics) as ResolvedCall<D>
|
||||||
}
|
}
|
||||||
CallResolutionResult.Type.ALL_CANDIDATES -> error("Cannot transform result for ALL_CANDIDATES mode")
|
CallResolutionResult.Type.ALL_CANDIDATES -> error("Cannot transform result for ALL_CANDIDATES mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> createStubResolvedCallAndWriteItToTrace(candidate: ResolvedCallAtom, trace: BindingTrace): ResolvedCall<D> {
|
fun <D : CallableDescriptor> createStubResolvedCallAndWriteItToTrace(
|
||||||
val result = transformToResolvedCall<D>(candidate, trace)
|
candidate: ResolvedCallAtom,
|
||||||
|
trace: BindingTrace,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
|
): ResolvedCall<D> {
|
||||||
|
val result = transformToResolvedCall<D>(candidate, trace, null, diagnostics)
|
||||||
val psiKotlinCall = candidate.atom.psiKotlinCall
|
val psiKotlinCall = candidate.atom.psiKotlinCall
|
||||||
val tracing = psiKotlinCall.safeAs<PSIKotlinCallForInvoke>()?.baseCall?.tracingStrategy ?: psiKotlinCall.tracingStrategy
|
val tracing = psiKotlinCall.safeAs<PSIKotlinCallForInvoke>()?.baseCall?.tracingStrategy ?: psiKotlinCall.tracingStrategy
|
||||||
|
|
||||||
@@ -126,35 +131,38 @@ class KotlinToResolvedCallTransformer(
|
|||||||
fun <D : CallableDescriptor> transformToResolvedCall(
|
fun <D : CallableDescriptor> transformToResolvedCall(
|
||||||
completedCallAtom: ResolvedCallAtom,
|
completedCallAtom: ResolvedCallAtom,
|
||||||
trace: BindingTrace?,
|
trace: BindingTrace?,
|
||||||
resultSubstitutor: NewTypeSubstitutor? = null // if substitutor is not null, it means that this call is completed
|
resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
): ResolvedCall<D> {
|
): ResolvedCall<D> {
|
||||||
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
|
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
|
||||||
return if (psiKotlinCall is PSIKotlinCallForInvoke) {
|
return if (psiKotlinCall is PSIKotlinCallForInvoke) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
NewVariableAsFunctionResolvedCallImpl(
|
NewVariableAsFunctionResolvedCallImpl(
|
||||||
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor),
|
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics),
|
||||||
createOrGet(completedCallAtom, trace, resultSubstitutor)
|
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
|
||||||
) as ResolvedCall<D>
|
) as ResolvedCall<D>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
createOrGet(completedCallAtom, trace, resultSubstitutor)
|
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> createOrGet(
|
private fun <D : CallableDescriptor> createOrGet(
|
||||||
completedSimpleAtom: ResolvedCallAtom,
|
completedSimpleAtom: ResolvedCallAtom,
|
||||||
trace: BindingTrace?,
|
trace: BindingTrace?,
|
||||||
resultSubstitutor: NewTypeSubstitutor?
|
resultSubstitutor: NewTypeSubstitutor?,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
): NewResolvedCallImpl<D> {
|
): NewResolvedCallImpl<D> {
|
||||||
if (trace != null) {
|
if (trace != null) {
|
||||||
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext)?.
|
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext)?.
|
||||||
safeAs<NewResolvedCallImpl<D>>()
|
safeAs<NewResolvedCallImpl<D>>()
|
||||||
if (storedResolvedCall != null) {
|
if (storedResolvedCall != null) {
|
||||||
storedResolvedCall.setResultingSubstitutor(resultSubstitutor)
|
storedResolvedCall.setResultingSubstitutor(resultSubstitutor)
|
||||||
|
storedResolvedCall.updateDiagnostics(diagnostics)
|
||||||
return storedResolvedCall
|
return storedResolvedCall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NewResolvedCallImpl(completedSimpleAtom, resultSubstitutor)
|
return NewResolvedCallImpl(completedSimpleAtom, resultSubstitutor, diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) {
|
fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) {
|
||||||
@@ -289,44 +297,63 @@ class KotlinToResolvedCallTransformer(
|
|||||||
return expressionType != null && TypeUtils.isNullableType(expressionType)
|
return expressionType != null && TypeUtils.isNullableType(expressionType)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun bindAndReport(context: BasicCallResolutionContext, trace: BindingTrace, resolvedCall: ResolvedCall<*>) {
|
internal fun bindAndReport(
|
||||||
resolvedCall.safeAs<NewResolvedCallImpl<*>>()?.let { bindAndReport(context, trace, it) }
|
context: BasicCallResolutionContext,
|
||||||
resolvedCall.safeAs<NewVariableAsFunctionResolvedCallImpl>()?.let { bindAndReport(context, trace, it) }
|
trace: BindingTrace,
|
||||||
|
resolvedCall: ResolvedCall<*>,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
|
) {
|
||||||
|
resolvedCall.safeAs<NewResolvedCallImpl<*>>()?.let { bindAndReport(context, trace, it, diagnostics) }
|
||||||
|
resolvedCall.safeAs<NewVariableAsFunctionResolvedCallImpl>()?.let { bindAndReport(context, trace, it, diagnostics) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindAndReport(context: BasicCallResolutionContext, trace: BindingTrace, simpleResolvedCall: NewResolvedCallImpl<*>) {
|
private fun bindAndReport(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
trace: BindingTrace,
|
||||||
|
simpleResolvedCall: NewResolvedCallImpl<*>,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
|
) {
|
||||||
val tracing = simpleResolvedCall.resolvedCallAtom.atom.psiKotlinCall.tracingStrategy
|
val tracing = simpleResolvedCall.resolvedCallAtom.atom.psiKotlinCall.tracingStrategy
|
||||||
|
|
||||||
tracing.bindReference(trace, simpleResolvedCall)
|
tracing.bindReference(trace, simpleResolvedCall)
|
||||||
tracing.bindResolvedCall(trace, simpleResolvedCall)
|
tracing.bindResolvedCall(trace, simpleResolvedCall)
|
||||||
|
|
||||||
reportCallDiagnostic(context, trace, simpleResolvedCall.resolvedCallAtom, simpleResolvedCall.resultingDescriptor)
|
reportCallDiagnostic(context, trace, simpleResolvedCall.resolvedCallAtom, simpleResolvedCall.resultingDescriptor, diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindAndReport(context: BasicCallResolutionContext, trace: BindingTrace, variableAsFunction: NewVariableAsFunctionResolvedCallImpl) {
|
private fun bindAndReport(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
trace: BindingTrace,
|
||||||
|
variableAsFunction: NewVariableAsFunctionResolvedCallImpl,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
|
) {
|
||||||
val outerTracingStrategy = variableAsFunction.baseCall.tracingStrategy
|
val outerTracingStrategy = variableAsFunction.baseCall.tracingStrategy
|
||||||
outerTracingStrategy.bindReference(trace, variableAsFunction.variableCall)
|
val variableCall = variableAsFunction.variableCall
|
||||||
outerTracingStrategy.bindResolvedCall(trace, variableAsFunction)
|
val functionCall = variableAsFunction.functionCall
|
||||||
variableAsFunction.functionCall.kotlinCall.psiKotlinCall.tracingStrategy.bindReference(trace, variableAsFunction.functionCall)
|
|
||||||
|
|
||||||
reportCallDiagnostic(context, trace, variableAsFunction.variableCall.resolvedCallAtom, variableAsFunction.variableCall.resultingDescriptor)
|
outerTracingStrategy.bindReference(trace, variableCall)
|
||||||
reportCallDiagnostic(context, trace, variableAsFunction.functionCall.resolvedCallAtom, variableAsFunction.functionCall.resultingDescriptor)
|
outerTracingStrategy.bindResolvedCall(trace, variableAsFunction)
|
||||||
|
functionCall.kotlinCall.psiKotlinCall.tracingStrategy.bindReference(trace, functionCall)
|
||||||
|
|
||||||
|
reportCallDiagnostic(context, trace, variableCall.resolvedCallAtom, variableCall.resultingDescriptor, diagnostics)
|
||||||
|
reportCallDiagnostic(context, trace, functionCall.resolvedCallAtom, functionCall.resultingDescriptor, emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reportCallDiagnostic(
|
private fun reportCallDiagnostic(
|
||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
completedCallAtom: ResolvedCallAtom,
|
completedCallAtom: ResolvedCallAtom,
|
||||||
resultingDescriptor: CallableDescriptor
|
resultingDescriptor: CallableDescriptor,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
) {
|
) {
|
||||||
val trackingTrace = TrackingBindingTrace(trace)
|
val trackingTrace = TrackingBindingTrace(trace)
|
||||||
val newContext = context.replaceBindingTrace(trackingTrace)
|
val newContext = context.replaceBindingTrace(trackingTrace)
|
||||||
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall)
|
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall)
|
||||||
|
|
||||||
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
||||||
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder)
|
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
|
||||||
|
|
||||||
for (diagnostic in completedCallAtom.diagnostics + diagnosticHolder.getDiagnostics()) {
|
for (diagnostic in diagnostics + diagnosticHolder.getDiagnostics()) {
|
||||||
trackingTrace.reported = false
|
trackingTrace.reported = false
|
||||||
diagnostic.report(diagnosticReporter)
|
diagnostic.report(diagnosticReporter)
|
||||||
|
|
||||||
@@ -445,7 +472,8 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>(): ResolvedCall<D>
|
|||||||
|
|
||||||
class NewResolvedCallImpl<D : CallableDescriptor>(
|
class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||||
val resolvedCallAtom: ResolvedCallAtom,
|
val resolvedCallAtom: ResolvedCallAtom,
|
||||||
substitutor: NewTypeSubstitutor?
|
substitutor: NewTypeSubstitutor?,
|
||||||
|
private var diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
): NewAbstractResolvedCall<D>() {
|
): NewAbstractResolvedCall<D>() {
|
||||||
var isCompleted = false
|
var isCompleted = false
|
||||||
private set
|
private set
|
||||||
@@ -458,7 +486,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
|||||||
|
|
||||||
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
|
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
|
||||||
|
|
||||||
override fun getStatus(): ResolutionStatus = getResultApplicability(resolvedCallAtom.diagnostics).toResolutionStatus()
|
override fun getStatus(): ResolutionStatus = getResultApplicability(diagnostics).toResolutionStatus()
|
||||||
|
|
||||||
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||||
get() = resolvedCallAtom.argumentMappingByOriginal
|
get() = resolvedCallAtom.argumentMappingByOriginal
|
||||||
@@ -489,6 +517,10 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
|||||||
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType
|
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateDiagnostics(completedDiagnostics: Collection<KotlinCallDiagnostic>) {
|
||||||
|
diagnostics = completedDiagnostics
|
||||||
|
}
|
||||||
|
|
||||||
fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
|
fun setResultingSubstitutor(substitutor: NewTypeSubstitutor?) {
|
||||||
//clear cached values
|
//clear cached values
|
||||||
argumentToParameterMap = null
|
argumentToParameterMap = null
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class PSICallResolver(
|
|||||||
if (result.type == CallResolutionResult.Type.ALL_CANDIDATES) {
|
if (result.type == CallResolutionResult.Type.ALL_CANDIDATES) {
|
||||||
val resolvedCalls = result.allCandidates?.map {
|
val resolvedCalls = result.allCandidates?.map {
|
||||||
val resultingSubstitutor = it.getSystem().asReadOnlyStorage().buildResultingSubstitutor()
|
val resultingSubstitutor = it.getSystem().asReadOnlyStorage().buildResultingSubstitutor()
|
||||||
kotlinToResolvedCallTransformer.transformToResolvedCall<D>(it.resolvedCall, null, resultingSubstitutor)
|
kotlinToResolvedCallTransformer.transformToResolvedCall<D>(it.resolvedCall, null, resultingSubstitutor, result.diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
return AllCandidates(resolvedCalls ?: emptyList())
|
return AllCandidates(resolvedCalls ?: emptyList())
|
||||||
@@ -193,7 +193,7 @@ class PSICallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.let {
|
result.diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.let {
|
||||||
val resolvedCalls = it.candidates.map { kotlinToResolvedCallTransformer.onlyTransform<D>(it.resolvedCall) }
|
val resolvedCalls = it.candidates.map { kotlinToResolvedCallTransformer.onlyTransform<D>(it.resolvedCall, emptyList()) }
|
||||||
if (it.candidates.areAllFailed()) {
|
if (it.candidates.areAllFailed()) {
|
||||||
tracingStrategy.noneApplicable(trace, resolvedCalls)
|
tracingStrategy.noneApplicable(trace, resolvedCalls)
|
||||||
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
tracingStrategy.recordAmbiguity(trace, resolvedCalls)
|
||||||
@@ -210,11 +210,11 @@ class PSICallResolver(
|
|||||||
return ManyCandidates(resolvedCalls)
|
return ManyCandidates(resolvedCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
val singleCandidate = result.resultCallAtom ?: error("Should be not null for result: $result")
|
val isInapplicableReceiver = getResultApplicability(result.diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
|
||||||
val isInapplicableReceiver = getResultApplicability(singleCandidate.diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
|
|
||||||
|
|
||||||
val resolvedCall = if (isInapplicableReceiver) {
|
val resolvedCall = if (isInapplicableReceiver) {
|
||||||
kotlinToResolvedCallTransformer.onlyTransform<D>(singleCandidate).also {
|
val singleCandidate = result.resultCallAtom ?: error("Should be not null for result: $result")
|
||||||
|
kotlinToResolvedCallTransformer.onlyTransform<D>(singleCandidate, result.diagnostics).also {
|
||||||
tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it))
|
tracingStrategy.unresolvedReferenceWrongReceiver(trace, listOf(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,15 +233,15 @@ class PSICallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun CallResolutionResult.areAllInapplicable(): Boolean {
|
private fun CallResolutionResult.areAllInapplicable(): Boolean {
|
||||||
val candidates = diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.candidates?.map { it.resolvedCall }
|
val manyCandidates = diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.candidates
|
||||||
?: listOfNotNull(resultCallAtom)
|
if (manyCandidates != null) {
|
||||||
|
return manyCandidates.areAllFailed()
|
||||||
return candidates.all {
|
|
||||||
val applicability = getResultApplicability(it.diagnostics)
|
|
||||||
applicability == ResolutionCandidateApplicability.INAPPLICABLE ||
|
|
||||||
applicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER ||
|
|
||||||
applicability == ResolutionCandidateApplicability.HIDDEN
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val applicability = getResultApplicability(diagnostics)
|
||||||
|
return applicability == ResolutionCandidateApplicability.INAPPLICABLE ||
|
||||||
|
applicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER ||
|
||||||
|
applicability == ResolutionCandidateApplicability.HIDDEN
|
||||||
}
|
}
|
||||||
|
|
||||||
// true if we found something
|
// true if we found something
|
||||||
|
|||||||
+6
-6
@@ -60,12 +60,12 @@ class ResolvedAtomCompleter(
|
|||||||
) {
|
) {
|
||||||
private val callCheckerContext = CallCheckerContext(topLevelCallContext, languageVersionSettings, deprecationResolver)
|
private val callCheckerContext = CallCheckerContext(topLevelCallContext, languageVersionSettings, deprecationResolver)
|
||||||
|
|
||||||
fun completeAndReport(resolvedAtom: ResolvedAtom) {
|
private fun complete(resolvedAtom: ResolvedAtom) {
|
||||||
when (resolvedAtom) {
|
when (resolvedAtom) {
|
||||||
is ResolvedCollectionLiteralAtom -> completeCollectionLiteralCalls(resolvedAtom)
|
is ResolvedCollectionLiteralAtom -> completeCollectionLiteralCalls(resolvedAtom)
|
||||||
is ResolvedCallableReferenceAtom -> completeCallableReference(resolvedAtom)
|
is ResolvedCallableReferenceAtom -> completeCallableReference(resolvedAtom)
|
||||||
is ResolvedLambdaAtom -> completeLambda(resolvedAtom)
|
is ResolvedLambdaAtom -> completeLambda(resolvedAtom)
|
||||||
is ResolvedCallAtom -> completeResolvedCall(resolvedAtom)
|
is ResolvedCallAtom -> completeResolvedCall(resolvedAtom, emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,14 +73,14 @@ class ResolvedAtomCompleter(
|
|||||||
for (subKtPrimitive in resolvedAtom.subResolvedAtoms) {
|
for (subKtPrimitive in resolvedAtom.subResolvedAtoms) {
|
||||||
completeAll(subKtPrimitive)
|
completeAll(subKtPrimitive)
|
||||||
}
|
}
|
||||||
completeAndReport(resolvedAtom)
|
complete(resolvedAtom)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom): ResolvedCall<*>? {
|
fun completeResolvedCall(resolvedCallAtom: ResolvedCallAtom, diagnostics: Collection<KotlinCallDiagnostic>): ResolvedCall<*>? {
|
||||||
if (resolvedCallAtom.atom.psiKotlinCall is PSIKotlinCallForVariable) return null
|
if (resolvedCallAtom.atom.psiKotlinCall is PSIKotlinCallForVariable) return null
|
||||||
|
|
||||||
val resolvedCall = kotlinToResolvedCallTransformer.transformToResolvedCall<CallableDescriptor>(resolvedCallAtom, trace, resultSubstitutor)
|
val resolvedCall = kotlinToResolvedCallTransformer.transformToResolvedCall<CallableDescriptor>(resolvedCallAtom, trace, resultSubstitutor, diagnostics)
|
||||||
kotlinToResolvedCallTransformer.bindAndReport(topLevelCallContext, trace, resolvedCall)
|
kotlinToResolvedCallTransformer.bindAndReport(topLevelCallContext, trace, resolvedCall, diagnostics)
|
||||||
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
|
kotlinToResolvedCallTransformer.runCallCheckers(resolvedCall, callCheckerContext)
|
||||||
|
|
||||||
val lastCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.functionCall else resolvedCall
|
val lastCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.functionCall else resolvedCall
|
||||||
|
|||||||
+16
-9
@@ -31,9 +31,10 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
|
|||||||
fun reportAdditionalDiagnostics(
|
fun reportAdditionalDiagnostics(
|
||||||
candidate: ResolvedCallAtom,
|
candidate: ResolvedCallAtom,
|
||||||
resultingDescriptor: CallableDescriptor,
|
resultingDescriptor: CallableDescriptor,
|
||||||
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder
|
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
) {
|
) {
|
||||||
reportSmartCasts(candidate, resultingDescriptor, kotlinDiagnosticsHolder)
|
reportSmartCasts(candidate, resultingDescriptor, kotlinDiagnosticsHolder, diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSmartCastDiagnostic(
|
private fun createSmartCastDiagnostic(
|
||||||
@@ -51,7 +52,8 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
|
|||||||
private fun reportSmartCastOnReceiver(
|
private fun reportSmartCastOnReceiver(
|
||||||
candidate: ResolvedCallAtom,
|
candidate: ResolvedCallAtom,
|
||||||
receiver: SimpleKotlinCallArgument?,
|
receiver: SimpleKotlinCallArgument?,
|
||||||
parameter: ReceiverParameterDescriptor?
|
parameter: ReceiverParameterDescriptor?,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
): SmartCastDiagnostic? {
|
): SmartCastDiagnostic? {
|
||||||
if (receiver == null || parameter == null) return null
|
if (receiver == null || parameter == null) return null
|
||||||
val expectedType = parameter.type.unwrap().let { if (receiver.isSafeCall) it.makeNullableAsSpecified(true) else it }
|
val expectedType = parameter.type.unwrap().let { if (receiver.isSafeCall) it.makeNullableAsSpecified(true) else it }
|
||||||
@@ -60,11 +62,11 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
|
|||||||
|
|
||||||
// todo may be we have smart cast to Int?
|
// todo may be we have smart cast to Int?
|
||||||
return smartCastDiagnostic.takeIf {
|
return smartCastDiagnostic.takeIf {
|
||||||
candidate.diagnostics.filterIsInstance<UnsafeCallError>().none {
|
diagnostics.filterIsInstance<UnsafeCallError>().none {
|
||||||
it.receiver == receiver
|
it.receiver == receiver
|
||||||
}
|
}
|
||||||
&&
|
&&
|
||||||
candidate.diagnostics.filterIsInstance<UnstableSmartCast>().none {
|
diagnostics.filterIsInstance<UnstableSmartCast>().none {
|
||||||
it.argument == receiver
|
it.argument == receiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,17 +75,22 @@ class AdditionalDiagnosticReporter(private val languageVersionSettings: Language
|
|||||||
private fun reportSmartCasts(
|
private fun reportSmartCasts(
|
||||||
candidate: ResolvedCallAtom,
|
candidate: ResolvedCallAtom,
|
||||||
resultingDescriptor: CallableDescriptor,
|
resultingDescriptor: CallableDescriptor,
|
||||||
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder
|
kotlinDiagnosticsHolder: KotlinDiagnosticsHolder,
|
||||||
|
diagnostics: Collection<KotlinCallDiagnostic>
|
||||||
) {
|
) {
|
||||||
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(reportSmartCastOnReceiver(candidate, candidate.extensionReceiverArgument, resultingDescriptor.extensionReceiverParameter))
|
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(
|
||||||
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(reportSmartCastOnReceiver(candidate, candidate.dispatchReceiverArgument, resultingDescriptor.dispatchReceiverParameter))
|
reportSmartCastOnReceiver(candidate, candidate.extensionReceiverArgument, resultingDescriptor.extensionReceiverParameter, diagnostics)
|
||||||
|
)
|
||||||
|
kotlinDiagnosticsHolder.addDiagnosticIfNotNull(
|
||||||
|
reportSmartCastOnReceiver(candidate, candidate.dispatchReceiverArgument, resultingDescriptor.dispatchReceiverParameter, diagnostics)
|
||||||
|
)
|
||||||
|
|
||||||
for (parameter in resultingDescriptor.valueParameters) {
|
for (parameter in resultingDescriptor.valueParameters) {
|
||||||
for (argument in candidate.argumentMappingByOriginal[parameter.original]?.arguments ?: continue) {
|
for (argument in candidate.argumentMappingByOriginal[parameter.original]?.arguments ?: continue) {
|
||||||
val effectiveExpectedType = argument.getExpectedType(parameter, languageVersionSettings)
|
val effectiveExpectedType = argument.getExpectedType(parameter, languageVersionSettings)
|
||||||
val smartCastDiagnostic = createSmartCastDiagnostic(candidate, argument, effectiveExpectedType) ?: continue
|
val smartCastDiagnostic = createSmartCastDiagnostic(candidate, argument, effectiveExpectedType) ?: continue
|
||||||
|
|
||||||
val thereIsUnstableSmartCastError = candidate.diagnostics.filterIsInstance<UnstableSmartCast>().any {
|
val thereIsUnstableSmartCastError = diagnostics.filterIsInstance<UnstableSmartCast>().any {
|
||||||
it.argument == argument
|
it.argument == argument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-9
@@ -29,8 +29,6 @@ import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
|
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
|
|
||||||
|
|
||||||
class CallableReferenceOverloadConflictResolver(
|
class CallableReferenceOverloadConflictResolver(
|
||||||
@@ -62,7 +60,8 @@ class CallableReferenceResolver(
|
|||||||
|
|
||||||
fun processCallableReferenceArgument(
|
fun processCallableReferenceArgument(
|
||||||
csBuilder: ConstraintSystemBuilder,
|
csBuilder: ConstraintSystemBuilder,
|
||||||
resolvedAtom: ResolvedCallableReferenceAtom
|
resolvedAtom: ResolvedCallableReferenceAtom,
|
||||||
|
diagnosticsHolder: KotlinDiagnosticsHolder
|
||||||
) {
|
) {
|
||||||
val argument = resolvedAtom.atom
|
val argument = resolvedAtom.atom
|
||||||
val expectedType = resolvedAtom.expectedType?.let { csBuilder.buildCurrentSubstitutor().safeSubstitute(it) }
|
val expectedType = resolvedAtom.expectedType?.let { csBuilder.buildCurrentSubstitutor().safeSubstitute(it) }
|
||||||
@@ -71,30 +70,28 @@ class CallableReferenceResolver(
|
|||||||
val candidates = runRHSResolution(scopeTower, argument, expectedType) { checkCallableReference ->
|
val candidates = runRHSResolution(scopeTower, argument, expectedType) { checkCallableReference ->
|
||||||
csBuilder.runTransaction { checkCallableReference(this); false }
|
csBuilder.runTransaction { checkCallableReference(this); false }
|
||||||
}
|
}
|
||||||
val diagnostics = SmartList<KotlinCallDiagnostic>()
|
|
||||||
|
|
||||||
val chosenCandidate = candidates.singleOrNull()
|
val chosenCandidate = candidates.singleOrNull()
|
||||||
if (chosenCandidate != null) {
|
if (chosenCandidate != null) {
|
||||||
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
|
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
|
||||||
csBuilder.checkCallableReference(argument, dispatchReceiver, extensionReceiver, candidate,
|
csBuilder.checkCallableReference(argument, dispatchReceiver, extensionReceiver, candidate,
|
||||||
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor)
|
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor)
|
||||||
}
|
}
|
||||||
diagnostics.addIfNotNull(diagnostic)
|
diagnosticsHolder.addDiagnosticIfNotNull(diagnostic)
|
||||||
chosenCandidate.freshSubstitutor = toFreshSubstitutor
|
chosenCandidate.freshSubstitutor = toFreshSubstitutor
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (candidates.isEmpty()) {
|
if (candidates.isEmpty()) {
|
||||||
diagnostics.add(NoneCallableReferenceCandidates(argument))
|
diagnosticsHolder.addDiagnostic(NoneCallableReferenceCandidates(argument))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
diagnostics.add(CallableReferenceCandidatesAmbiguity(argument, candidates))
|
diagnosticsHolder.addDiagnostic(CallableReferenceCandidatesAmbiguity(argument, candidates))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo -- create this inside CallableReferencesCandidateFactory
|
// todo -- create this inside CallableReferencesCandidateFactory
|
||||||
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
|
val subKtArguments = listOfNotNull(buildResolvedKtArgument(argument.lhsResult))
|
||||||
|
|
||||||
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments, diagnostics)
|
resolvedAtom.setAnalyzedResults(chosenCandidate, subKtArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
|
private fun buildResolvedKtArgument(lhsResult: LHSResult): ResolvedAtom? {
|
||||||
|
|||||||
+26
-4
@@ -49,13 +49,20 @@ class KotlinCallCompleter(
|
|||||||
// this is needed at least for non-local return checker, because when we analyze lambda we should already bind descriptor for outer call
|
// 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) }
|
candidate?.resolvedCall?.let { resolutionCallbacks.bindStubResolvedCallForCandidate(it) }
|
||||||
|
|
||||||
|
val diagnosticsFromResolutionParts = candidate?.diagnosticsFromResolutionParts ?: emptyList<KotlinCallDiagnostic>()
|
||||||
|
|
||||||
if (candidate == null || candidate.csBuilder.hasContradiction) {
|
if (candidate == null || candidate.csBuilder.hasContradiction) {
|
||||||
val candidateForCompletion = candidate ?: factory.createErrorCandidate().forceResolution()
|
val candidateForCompletion = candidate ?: factory.createErrorCandidate().forceResolution()
|
||||||
candidateForCompletion.prepareForCompletion(expectedType, resolutionCallbacks)
|
candidateForCompletion.prepareForCompletion(expectedType, resolutionCallbacks)
|
||||||
runCompletion(candidateForCompletion.resolvedCall, ConstraintSystemCompletionMode.FULL, diagnosticHolder, candidateForCompletion.getSystem(), resolutionCallbacks)
|
runCompletion(candidateForCompletion.resolvedCall, ConstraintSystemCompletionMode.FULL, diagnosticHolder, candidateForCompletion.getSystem(), resolutionCallbacks)
|
||||||
|
|
||||||
val systemStorage = candidate?.getSystem()?.asReadOnlyStorage() ?: ConstraintStorage.Empty
|
val systemStorage = candidate?.getSystem()?.asReadOnlyStorage() ?: ConstraintStorage.Empty
|
||||||
return CallResolutionResult(CallResolutionResult.Type.ERROR, candidate?.resolvedCall, diagnosticHolder.getDiagnostics(), systemStorage)
|
return CallResolutionResult(
|
||||||
|
CallResolutionResult.Type.ERROR,
|
||||||
|
candidate?.resolvedCall,
|
||||||
|
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
|
||||||
|
systemStorage
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val completionType = candidate.prepareForCompletion(expectedType, resolutionCallbacks)
|
val completionType = candidate.prepareForCompletion(expectedType, resolutionCallbacks)
|
||||||
@@ -63,10 +70,20 @@ class KotlinCallCompleter(
|
|||||||
runCompletion(candidate.resolvedCall, completionType, diagnosticHolder, constraintSystem, resolutionCallbacks)
|
runCompletion(candidate.resolvedCall, completionType, diagnosticHolder, constraintSystem, resolutionCallbacks)
|
||||||
|
|
||||||
return if (completionType == ConstraintSystemCompletionMode.FULL) {
|
return if (completionType == ConstraintSystemCompletionMode.FULL) {
|
||||||
CallResolutionResult(CallResolutionResult.Type.COMPLETED, candidate.resolvedCall, diagnosticHolder.getDiagnostics(), constraintSystem.asReadOnlyStorage())
|
CallResolutionResult(
|
||||||
|
CallResolutionResult.Type.COMPLETED,
|
||||||
|
candidate.resolvedCall,
|
||||||
|
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
|
||||||
|
constraintSystem.asReadOnlyStorage()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CallResolutionResult(CallResolutionResult.Type.PARTIAL, candidate.resolvedCall, diagnosticHolder.getDiagnostics(), constraintSystem.asReadOnlyStorage())
|
CallResolutionResult(
|
||||||
|
CallResolutionResult.Type.PARTIAL,
|
||||||
|
candidate.resolvedCall,
|
||||||
|
diagnosticHolder.getDiagnostics() + diagnosticsFromResolutionParts,
|
||||||
|
constraintSystem.asReadOnlyStorage()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +117,12 @@ class KotlinCallCompleter(
|
|||||||
val returnType = resolvedCallAtom.freshReturnType ?: constraintSystem.builtIns.unitType
|
val returnType = resolvedCallAtom.freshReturnType ?: constraintSystem.builtIns.unitType
|
||||||
kotlinConstraintSystemCompleter.runCompletion(constraintSystem.asConstraintSystemCompleterContext(), completionMode, resolvedCallAtom, returnType) {
|
kotlinConstraintSystemCompleter.runCompletion(constraintSystem.asConstraintSystemCompleterContext(), completionMode, resolvedCallAtom, returnType) {
|
||||||
if (!skipPostponedArguments) {
|
if (!skipPostponedArguments) {
|
||||||
postponedArgumentsAnalyzer.analyze(constraintSystem.asPostponedArgumentsAnalyzerContext(), resolutionCallbacks, it)
|
postponedArgumentsAnalyzer.analyze(
|
||||||
|
constraintSystem.asPostponedArgumentsAnalyzerContext(),
|
||||||
|
resolutionCallbacks,
|
||||||
|
it,
|
||||||
|
diagnosticsHolder
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-8
@@ -39,17 +39,24 @@ class PostponedArgumentsAnalyzer(
|
|||||||
fun getBuilder(): ConstraintSystemBuilder
|
fun getBuilder(): ConstraintSystemBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
fun analyze(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, argument: ResolvedAtom) {
|
fun analyze(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, argument: ResolvedAtom, diagnosticsHolder: KotlinDiagnosticsHolder) {
|
||||||
when (argument) {
|
when (argument) {
|
||||||
is ResolvedLambdaAtom -> analyzeLambda(c, resolutionCallbacks, argument)
|
is ResolvedLambdaAtom ->
|
||||||
is LambdaWithTypeVariableAsExpectedTypeAtom -> analyzeLambda(c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()))
|
analyzeLambda(c, resolutionCallbacks, argument, diagnosticsHolder)
|
||||||
is ResolvedCallableReferenceAtom -> callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument)
|
|
||||||
|
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
||||||
|
analyzeLambda(c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder)
|
||||||
|
|
||||||
|
is ResolvedCallableReferenceAtom ->
|
||||||
|
callableReferenceResolver.processCallableReferenceArgument(c.getBuilder(), argument, diagnosticsHolder)
|
||||||
|
|
||||||
is ResolvedCollectionLiteralAtom -> TODO("Not supported")
|
is ResolvedCollectionLiteralAtom -> TODO("Not supported")
|
||||||
|
|
||||||
else -> error("Unexpected resolved primitive: ${argument.javaClass.canonicalName}")
|
else -> error("Unexpected resolved primitive: ${argument.javaClass.canonicalName}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: ResolvedLambdaAtom) {
|
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: ResolvedLambdaAtom, diagnosticHolder: KotlinDiagnosticsHolder) {
|
||||||
val currentSubstitutor = c.buildCurrentSubstitutor()
|
val currentSubstitutor = c.buildCurrentSubstitutor()
|
||||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
||||||
|
|
||||||
@@ -61,8 +68,6 @@ class PostponedArgumentsAnalyzer(
|
|||||||
|
|
||||||
resultArguments.forEach { c.addSubsystemForArgument(it) }
|
resultArguments.forEach { c.addSubsystemForArgument(it) }
|
||||||
|
|
||||||
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
|
|
||||||
|
|
||||||
val subResolvedKtPrimitives = resultArguments.map {
|
val subResolvedKtPrimitives = resultArguments.map {
|
||||||
checkSimpleArgument(c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false)
|
checkSimpleArgument(c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false)
|
||||||
}
|
}
|
||||||
@@ -72,6 +77,6 @@ class PostponedArgumentsAnalyzer(
|
|||||||
c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda))
|
c.getBuilder().addSubtypeConstraint(lambda.returnType.let(::substitute), unitType, LambdaArgumentConstraintPosition(lambda))
|
||||||
}
|
}
|
||||||
|
|
||||||
lambda.setAnalyzedResults(resultArguments, subResolvedKtPrimitives, diagnosticHolder.getDiagnostics())
|
lambda.setAnalyzedResults(resultArguments, subResolvedKtPrimitives)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+10
-15
@@ -46,10 +46,8 @@ sealed class ResolvedAtom {
|
|||||||
|
|
||||||
lateinit var subResolvedAtoms: List<ResolvedAtom>
|
lateinit var subResolvedAtoms: List<ResolvedAtom>
|
||||||
private set
|
private set
|
||||||
lateinit var diagnostics: Collection<KotlinCallDiagnostic>
|
|
||||||
private set
|
|
||||||
|
|
||||||
protected open fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>, diagnostics: Collection<KotlinCallDiagnostic>) {
|
protected open fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) {
|
||||||
assert(!analyzed) {
|
assert(!analyzed) {
|
||||||
"Already analyzed: $this"
|
"Already analyzed: $this"
|
||||||
}
|
}
|
||||||
@@ -57,7 +55,6 @@ sealed class ResolvedAtom {
|
|||||||
analyzed = true
|
analyzed = true
|
||||||
|
|
||||||
this.subResolvedAtoms = subResolvedAtoms
|
this.subResolvedAtoms = subResolvedAtoms
|
||||||
this.diagnostics = diagnostics
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +71,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
|||||||
|
|
||||||
class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) : ResolvedAtom() {
|
class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) : ResolvedAtom() {
|
||||||
init {
|
init {
|
||||||
setAnalyzedResults(listOf(), listOf())
|
setAnalyzedResults(listOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sealed class PostponedResolvedAtom : ResolvedAtom() {
|
sealed class PostponedResolvedAtom : ResolvedAtom() {
|
||||||
@@ -90,7 +87,7 @@ class LambdaWithTypeVariableAsExpectedTypeAtom(
|
|||||||
override val outputType: UnwrappedType? get() = null
|
override val outputType: UnwrappedType? get() = null
|
||||||
|
|
||||||
fun setAnalyzed(resolvedLambdaAtom: ResolvedLambdaAtom) {
|
fun setAnalyzed(resolvedLambdaAtom: ResolvedLambdaAtom) {
|
||||||
setAnalyzedResults(listOf(resolvedLambdaAtom), listOf())
|
setAnalyzedResults(listOf(resolvedLambdaAtom))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +104,10 @@ class ResolvedLambdaAtom(
|
|||||||
|
|
||||||
fun setAnalyzedResults(
|
fun setAnalyzedResults(
|
||||||
resultArguments: List<KotlinCallArgument>,
|
resultArguments: List<KotlinCallArgument>,
|
||||||
subResolvedAtoms: List<ResolvedAtom>,
|
subResolvedAtoms: List<ResolvedAtom>
|
||||||
diagnostics: Collection<KotlinCallDiagnostic>
|
|
||||||
) {
|
) {
|
||||||
this.resultArguments = resultArguments
|
this.resultArguments = resultArguments
|
||||||
setAnalyzedResults(subResolvedAtoms, diagnostics)
|
setAnalyzedResults(subResolvedAtoms)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val inputTypes: Collection<UnwrappedType> get() = receiver?.let { parameters + it } ?: parameters
|
override val inputTypes: Collection<UnwrappedType> get() = receiver?.let { parameters + it } ?: parameters
|
||||||
@@ -127,11 +123,10 @@ class ResolvedCallableReferenceAtom(
|
|||||||
|
|
||||||
fun setAnalyzedResults(
|
fun setAnalyzedResults(
|
||||||
candidate: CallableReferenceCandidate?,
|
candidate: CallableReferenceCandidate?,
|
||||||
subResolvedAtoms: List<ResolvedAtom>,
|
subResolvedAtoms: List<ResolvedAtom>
|
||||||
diagnostics: Collection<KotlinCallDiagnostic>
|
|
||||||
) {
|
) {
|
||||||
this.candidate = candidate
|
this.candidate = candidate
|
||||||
setAnalyzedResults(subResolvedAtoms, diagnostics)
|
setAnalyzedResults(subResolvedAtoms)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val inputTypes: Collection<UnwrappedType>
|
override val inputTypes: Collection<UnwrappedType>
|
||||||
@@ -154,14 +149,14 @@ class ResolvedCollectionLiteralAtom(
|
|||||||
val expectedType: UnwrappedType?
|
val expectedType: UnwrappedType?
|
||||||
) : ResolvedAtom() {
|
) : ResolvedAtom() {
|
||||||
init {
|
init {
|
||||||
setAnalyzedResults(listOf(), listOf())
|
setAnalyzedResults(listOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallResolutionResult(
|
class CallResolutionResult(
|
||||||
val type: Type,
|
val type: Type,
|
||||||
val resultCallAtom: ResolvedCallAtom?,
|
val resultCallAtom: ResolvedCallAtom?,
|
||||||
diagnostics: List<KotlinCallDiagnostic>,
|
val diagnostics: List<KotlinCallDiagnostic>,
|
||||||
val constraintSystem: ConstraintStorage,
|
val constraintSystem: ConstraintStorage,
|
||||||
val allCandidates: Collection<KotlinResolutionCandidate>? = null
|
val allCandidates: Collection<KotlinResolutionCandidate>? = null
|
||||||
) : ResolvedAtom() {
|
) : ResolvedAtom() {
|
||||||
@@ -175,7 +170,7 @@ class CallResolutionResult(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setAnalyzedResults(listOfNotNull(resultCallAtom), diagnostics)
|
setAnalyzedResults(listOfNotNull(resultCallAtom))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = "$type, resultCallAtom = $resultCallAtom, (${diagnostics.joinToString()})"
|
override fun toString() = "$type, resultCallAtom = $resultCallAtom, (${diagnostics.joinToString()})"
|
||||||
|
|||||||
+5
-5
@@ -68,8 +68,8 @@ class KotlinResolutionCandidate(
|
|||||||
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
|
val knownTypeParametersResultingSubstitutor: TypeSubstitutor? = null,
|
||||||
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
|
private val resolutionSequence: List<ResolutionPart> = resolvedCall.atom.callKind.resolutionSequence
|
||||||
) : Candidate, KotlinDiagnosticsHolder {
|
) : Candidate, KotlinDiagnosticsHolder {
|
||||||
|
val diagnosticsFromResolutionParts = arrayListOf<KotlinCallDiagnostic>() // TODO: this is mutable list, take diagnostics only once!
|
||||||
private var newSystem: NewConstraintSystemImpl? = null
|
private var newSystem: NewConstraintSystemImpl? = null
|
||||||
private val diagnostics = arrayListOf<KotlinCallDiagnostic>()
|
|
||||||
private var currentApplicability = ResolutionCandidateApplicability.RESOLVED
|
private var currentApplicability = ResolutionCandidateApplicability.RESOLVED
|
||||||
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
|
private var subResolvedAtoms: MutableList<ResolvedAtom> = arrayListOf()
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class KotlinResolutionCandidate(
|
|||||||
internal val csBuilder get() = getSystem().getBuilder()
|
internal val csBuilder get() = getSystem().getBuilder()
|
||||||
|
|
||||||
override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
|
override fun addDiagnostic(diagnostic: KotlinCallDiagnostic) {
|
||||||
diagnostics.add(diagnostic)
|
diagnosticsFromResolutionParts.add(diagnostic)
|
||||||
currentApplicability = maxOf(diagnostic.candidateApplicability, currentApplicability)
|
currentApplicability = maxOf(diagnostic.candidateApplicability, currentApplicability)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ class KotlinResolutionCandidate(
|
|||||||
partIndex++
|
partIndex++
|
||||||
}
|
}
|
||||||
if (step == stepCount) {
|
if (step == stepCount) {
|
||||||
resolvedCall.setAnalyzedResults(subResolvedAtoms, diagnostics + getSystem().diagnostics)
|
resolvedCall.setAnalyzedResults(subResolvedAtoms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,8 +176,8 @@ class MutableResolvedCallAtom(
|
|||||||
override lateinit var substitutor: FreshVariableNewTypeSubstitutor
|
override lateinit var substitutor: FreshVariableNewTypeSubstitutor
|
||||||
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
|
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
|
||||||
|
|
||||||
override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>, diagnostics: Collection<KotlinCallDiagnostic>) {
|
override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) {
|
||||||
super.setAnalyzedResults(subResolvedAtoms, diagnostics)
|
super.setAnalyzedResults(subResolvedAtoms)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "$atom, candidate = $candidateDescriptor"
|
override fun toString(): String = "$atom, candidate = $candidateDescriptor"
|
||||||
|
|||||||
Reference in New Issue
Block a user