FE 1.0: implement typed this label resolve warning for KT-51433

#KT-51433 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-02-22 12:23:20 +03:00
committed by Space
parent b5e2c492c6
commit 14eec6cfc0
9 changed files with 89 additions and 12 deletions
@@ -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 {
@@ -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 {
@@ -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 {
@@ -36,17 +36,24 @@ object LabelResolver {
labelName: Name,
labelExpression: KtSimpleNameExpression,
classNameLabelsEnabled: Boolean
): Set<KtElement> {
): Pair<Set<KtElement>, KtCallableDeclaration?> {
val elements = linkedSetOf<KtElement>()
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<Name> {
@@ -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) {
@@ -32,7 +32,7 @@ private typealias Extension = TypedThis
class TypedThis {
fun TypedThis.baz() {
this@TypedThis
this<!LABEL_RESOLVE_WILL_CHANGE("class TypedThis; function baz extension receiver")!>@TypedThis<!>
}
fun Extension.bar() {
@@ -0,0 +1,14 @@
// !LANGUAGE: +ContextReceivers
class Some {
context(Some, String)
fun foo() {
this<!UNRESOLVED_LABEL!>@foo<!>
this@Some
this<!UNRESOLVED_LABEL!>@String<!>
}
context(Some)
val self: Some
get() = this@Some
}
@@ -0,0 +1,14 @@
// !LANGUAGE: +ContextReceivers
class Some {
context(Some, String)
fun foo() {
<!NO_THIS!>this@foo<!>
this<!LABEL_RESOLVE_WILL_CHANGE("class Some; function foo context receiver")!>@Some<!>
this@String
}
context(Some)
val self: Some
get() = this<!LABEL_RESOLVE_WILL_CHANGE("class Some; property self context receiver")!>@Some<!>
}
@@ -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
}
@@ -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 {