From 694f5690f92ec5175ca26556060c641a0faa4cf6 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 14 Feb 2018 05:18:48 +0300 Subject: [PATCH] [NI] Improve diagnostic about unresolved receiver for many candidates --- .../resolve/calls/tower/PSICallResolver.kt | 59 +++++++++++-------- ...ReferenceWrongReceiverForManyCandidates.kt | 8 +++ ...eferenceWrongReceiverForManyCandidates.txt | 19 ++++++ ...functionExpectedWhenSeveralInvokesExist.kt | 6 +- .../manyInapplicableCandidatesWithLambdas.kt | 29 +++++---- .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../DiagnosticsUsingJavacTestGenerated.java | 6 ++ 7 files changed, 89 insertions(+), 44 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt create mode 100644 compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 07f872c1dab..d1970f025f2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2000-2018 JetBrains s.r.o. 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.tower @@ -201,19 +190,7 @@ class PSICallResolver( } result.diagnostics.firstIsInstanceOrNull()?.let { - val resolvedCalls = it.candidates.map { kotlinToResolvedCallTransformer.onlyTransform(it.resolvedCall, emptyList()) } - if (it.candidates.areAllFailed()) { - tracingStrategy.noneApplicable(trace, resolvedCalls) - tracingStrategy.recordAmbiguity(trace, resolvedCalls) - } else { - tracingStrategy.recordAmbiguity(trace, resolvedCalls) - if (resolvedCalls.first().status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) { - tracingStrategy.cannotCompleteResolve(trace, resolvedCalls) - } else { - tracingStrategy.ambiguity(trace, resolvedCalls) - } - } - return ManyCandidates(resolvedCalls) + return transformManyCandidatesAndRecordTrace(it, tracingStrategy, trace) } val isInapplicableReceiver = @@ -235,6 +212,31 @@ class PSICallResolver( return SingleOverloadResolutionResult(resolvedCall) } + private fun transformManyCandidatesAndRecordTrace( + diagnostic: ManyCandidatesCallDiagnostic, + tracingStrategy: TracingStrategy, + trace: BindingTrace + ): ManyCandidates { + val resolvedCalls = diagnostic.candidates.map { kotlinToResolvedCallTransformer.onlyTransform(it.resolvedCall, emptyList()) } + + if (diagnostic.candidates.areAllFailed()) { + if (diagnostic.candidates.areAllFailedWithInapplicableWrongReceiver()) { + tracingStrategy.unresolvedReferenceWrongReceiver(trace, resolvedCalls) + } else { + tracingStrategy.noneApplicable(trace, resolvedCalls) + tracingStrategy.recordAmbiguity(trace, resolvedCalls) + } + } else { + tracingStrategy.recordAmbiguity(trace, resolvedCalls) + if (resolvedCalls.first().status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) { + tracingStrategy.cannotCompleteResolve(trace, resolvedCalls) + } else { + tracingStrategy.ambiguity(trace, resolvedCalls) + } + } + return ManyCandidates(resolvedCalls) + } + private fun ResolvedCall<*>.recordEffects(trace: BindingTrace) { val moduleDescriptor = DescriptorUtils.getContainingModule(this.resultingDescriptor?.containingDeclaration ?: return) recordLambdasInvocations(trace, moduleDescriptor) @@ -259,6 +261,11 @@ class PSICallResolver( !it.resultingApplicability.isSuccess } + private fun Collection.areAllFailedWithInapplicableWrongReceiver() = + all { + it.resultingApplicability == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER + } + private fun CallResolutionResult.areAllInapplicable(): Boolean { val manyCandidates = diagnostics.firstIsInstanceOrNull()?.candidates if (manyCandidates != null) { diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt new file mode 100644 index 00000000000..1bbfca02be7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt @@ -0,0 +1,8 @@ +fun test() { + val a = -false +} + +operator fun A.unaryMinus() {} +operator fun B.unaryMinus() {} +class A +class B \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.txt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.txt new file mode 100644 index 00000000000..fd49f803067 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.txt @@ -0,0 +1,19 @@ +package + +public fun test(): kotlin.Unit +public operator fun A.unaryMinus(): kotlin.Unit +public operator fun B.unaryMinus(): kotlin.Unit + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/functionExpectedWhenSeveralInvokesExist.kt b/compiler/testData/diagnostics/tests/resolve/invoke/functionExpectedWhenSeveralInvokesExist.kt index 54f271c4dbf..b258c97d2d1 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/functionExpectedWhenSeveralInvokesExist.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/functionExpectedWhenSeveralInvokesExist.kt @@ -7,8 +7,8 @@ fun Int.invoke(a: Int, b: Int) {} class SomeClass fun test(identifier: SomeClass, fn: String.() -> Unit) { - identifier() - identifier(123) - identifier(1, 2) + identifier() + identifier(123) + identifier(1, 2) 1.fn() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt index 0dd8d8451e2..d04bdf6472d 100644 --- a/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt +++ b/compiler/testData/diagnostics/tests/resolve/nestedCalls/manyInapplicableCandidatesWithLambdas.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // !DIAGNOSTICS: -UNUSED_PARAMETER class A @@ -20,20 +19,20 @@ class E { // `bar` calls are inapplicable since both E nor D aren't proper receivers // But prior to this change, every lambda was analyzed repeatedly for every candidate // Thus, the resulting time was exponential - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { - bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { + bar { } } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 2a637e94326..7eaa70c99cd 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -11365,6 +11365,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("reportUnresolvedReferenceWrongReceiverForManyCandidates.kt") + public void testReportUnresolvedReferenceWrongReceiverForManyCandidates() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt"); + doTest(fileName); + } + @TestMetadata("subtypeForInvariantWithErrorGenerics.kt") public void testSubtypeForInvariantWithErrorGenerics() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/reportingImprovements/subtypeForInvariantWithErrorGenerics.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 4bcf461ad6e..a692add89a1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -11365,6 +11365,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("reportUnresolvedReferenceWrongReceiverForManyCandidates.kt") + public void testReportUnresolvedReferenceWrongReceiverForManyCandidates() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/reportingImprovements/reportUnresolvedReferenceWrongReceiverForManyCandidates.kt"); + doTest(fileName); + } + @TestMetadata("subtypeForInvariantWithErrorGenerics.kt") public void testSubtypeForInvariantWithErrorGenerics() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/reportingImprovements/subtypeForInvariantWithErrorGenerics.kt");