From 14eec6cfc01eece9dbb2f339469ffba916dc3f72 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 22 Feb 2022 12:23:20 +0300 Subject: [PATCH] FE 1.0: implement typed this label resolve warning for KT-51433 #KT-51433 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 +++ .../kotlin/types/expressions/LabelResolver.kt | 37 +++++++++++++------ .../testsWithStdLib/labelClashes.kt | 2 +- .../labelClashesWithContextReceivers.fir.kt | 14 +++++++ .../labelClashesWithContextReceivers.kt | 14 +++++++ .../labelClashesWithContextReceivers.txt | 10 +++++ .../test/runners/DiagnosticTestGenerated.java | 6 +++ 9 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.txt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 4ac13545af8..201480b6c8a 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -33575,6 +33575,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt"); } + @Test + @TestMetadata("labelClashesWithContextReceivers.kt") + public void testLabelClashesWithContextReceivers() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt"); + } + @Test @TestMetadata("outstar.kt") public void testOutstar() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 328436aeb37..72a20f5b7ba 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -33575,6 +33575,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt"); } + @Test + @TestMetadata("labelClashesWithContextReceivers.kt") + public void testLabelClashesWithContextReceivers() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt"); + } + @Test @TestMetadata("outstar.kt") public void testOutstar() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 5053f193540..7d3a0dd4d39 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -33575,6 +33575,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt"); } + @Test + @TestMetadata("labelClashesWithContextReceivers.kt") + public void testLabelClashesWithContextReceivers() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt"); + } + @Test @TestMetadata("outstar.kt") public void testOutstar() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt index b0adfd1dbe9..c5192aacd9e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt @@ -36,17 +36,24 @@ object LabelResolver { labelName: Name, labelExpression: KtSimpleNameExpression, classNameLabelsEnabled: Boolean - ): Set { + ): Pair, KtCallableDeclaration?> { val elements = linkedSetOf() + var typedElement: KtCallableDeclaration? = null var parent: PsiElement? = labelExpression.parent while (parent != null) { val names = getLabelNamesIfAny(parent, classNameLabelsEnabled) if (names.contains(labelName)) { elements.add(getExpressionUnderLabel(parent as KtExpression)) + } else if (parent is KtCallableDeclaration && typedElement == null) { + val receiverTypeReference = parent.receiverTypeReference + val nameForReceiverLabel = receiverTypeReference?.nameForReceiverLabel() + if (nameForReceiverLabel == labelName.asString()) { + typedElement = parent + } } parent = if (parent is KtCodeFragment) parent.context else parent.parent } - return elements + return elements to typedElement } fun getLabelNamesIfAny(element: PsiElement, addClassNameLabels: Boolean): List { @@ -123,7 +130,7 @@ object LabelResolver { val labelName = expression.getLabelNameAsName() if (labelElement == null || labelName == null) return null - return resolveNamedLabel(labelName, labelElement, context.trace, false) ?: run { + return resolveNamedLabel(labelName, labelElement, context.trace) ?: run { context.trace.report(UNRESOLVED_REFERENCE.on(labelElement, labelElement)) null } @@ -132,10 +139,9 @@ object LabelResolver { private fun resolveNamedLabel( labelName: Name, labelExpression: KtSimpleNameExpression, - trace: BindingTrace, - classNameLabelsEnabled: Boolean + trace: BindingTrace ): KtElement? { - val list = getElementsByLabelName(labelName, labelExpression, classNameLabelsEnabled) + val list = getElementsByLabelName(labelName, labelExpression, classNameLabelsEnabled = false).first if (list.isEmpty()) return null if (list.size > 1) { @@ -155,7 +161,7 @@ object LabelResolver { val scope = context.scope val declarationsByLabel = scope.getDeclarationsByLabel(labelName) - val elementsByLabel = getElementsByLabelName( + val (elementsByLabel, typedElement) = getElementsByLabelName( labelName, targetLabelExpression, classNameLabelsEnabled = expression is KtThisExpression && context.languageVersionSettings.supportsFeature(ContextReceivers) ) @@ -176,7 +182,13 @@ object LabelResolver { trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor) val closestElement = elementsByLabel.firstOrNull() if (closestElement != null && declarationElement in closestElement.parents) { - reportLabelResolveWillChange(trace, targetLabelExpression, declarationElement, closestElement) + reportLabelResolveWillChange( + trace, targetLabelExpression, declarationElement, closestElement, isForExtensionReceiver = false + ) + } else if (typedElement != null && declarationElement in typedElement.parents) { + reportLabelResolveWillChange( + trace, targetLabelExpression, declarationElement, typedElement, isForExtensionReceiver = true + ) } if (declarationDescriptor is ClassDescriptor) { @@ -229,12 +241,15 @@ object LabelResolver { trace: BindingTrace, target: KtSimpleNameExpression, declarationElement: PsiElement, - closestElement: KtElement + closestElement: KtElement, + isForExtensionReceiver: Boolean ) { + fun suffix() = if (isForExtensionReceiver) "extension receiver" else "context receiver" + val closestDescription = when (closestElement) { is KtFunctionLiteral -> "anonymous function" - is KtNamedFunction -> "function ${closestElement.name} context receiver" - is KtPropertyAccessor -> "property ${closestElement.property.name} context receiver" + is KtNamedFunction -> "function ${closestElement.name} ${suffix()}" + is KtPropertyAccessor -> "property ${closestElement.property.name} ${suffix()}" else -> "???" } val declarationDescription = when (declarationElement) { diff --git a/compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt b/compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt index fb1bee7efde..f0920ec1605 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt @@ -32,7 +32,7 @@ private typealias Extension = TypedThis class TypedThis { fun TypedThis.baz() { - this@TypedThis + this@TypedThis } fun Extension.bar() { diff --git a/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt new file mode 100644 index 00000000000..3e1552315a8 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.fir.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +ContextReceivers + +class Some { + context(Some, String) + fun foo() { + this@foo + this@Some + this@String + } + + context(Some) + val self: Some + get() = this@Some +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt new file mode 100644 index 00000000000..6a76c4f0e54 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +ContextReceivers + +class Some { + context(Some, String) + fun foo() { + this@foo + this@Some + this@String + } + + context(Some) + val self: Some + get() = this@Some +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.txt b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.txt new file mode 100644 index 00000000000..6887c62862d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.txt @@ -0,0 +1,10 @@ +package + +public final class Some { + public constructor Some() + context(Some) public final val self: Some + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + context(Some, kotlin.String) public final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index ca73c6f2fb7..ffb22485d27 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -33665,6 +33665,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashes.kt"); } + @Test + @TestMetadata("labelClashesWithContextReceivers.kt") + public void testLabelClashesWithContextReceivers() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/labelClashesWithContextReceivers.kt"); + } + @Test @TestMetadata("outstar.kt") public void testOutstar() throws Exception {