Deprecate ambiguous cases in FE 1.0: companion property vs enum entry
^KT-37591 Fixed
This commit is contained in:
committed by
TeamCityServer
parent
24bb9a4e14
commit
46b297477c
+6
@@ -23273,6 +23273,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyInCompanionOfEnum.kt")
|
||||||
|
public void testPropertyInCompanionOfEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/resolve/propertyInCompanionOfEnum.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
||||||
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
||||||
|
|||||||
+6
@@ -23273,6 +23273,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyInCompanionOfEnum.kt")
|
||||||
|
public void testPropertyInCompanionOfEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/resolve/propertyInCompanionOfEnum.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
||||||
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ public interface Errors {
|
|||||||
DiagnosticFactory3<PsiElement, DeclarationDescriptor, DescriptorVisibility, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory3.create(ERROR, CALL_ELEMENT);
|
DiagnosticFactory3<PsiElement, DeclarationDescriptor, DescriptorVisibility, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory3.create(ERROR, CALL_ELEMENT);
|
||||||
DiagnosticFactory1<KtElement, DeclarationDescriptor> DEPRECATED_ACCESS_BY_SHORT_NAME = DiagnosticFactory1.create(WARNING);
|
DiagnosticFactory1<KtElement, DeclarationDescriptor> DEPRECATED_ACCESS_BY_SHORT_NAME = DiagnosticFactory1.create(WARNING);
|
||||||
|
|
||||||
|
DiagnosticFactory1<PsiElement, PropertyDescriptor> DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY = DiagnosticFactory1.create(WARNING);
|
||||||
|
|
||||||
DiagnosticFactory1<PsiElement, ConstructorDescriptor> PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, ConstructorDescriptor> PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
// Exposed visibility group
|
// Exposed visibility group
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(INVISIBLE_REFERENCE, "Cannot access ''{0}'': it is {1} in {2}", NAME, VISIBILITY, NAME_OF_CONTAINING_DECLARATION_OR_FILE);
|
MAP.put(INVISIBLE_REFERENCE, "Cannot access ''{0}'': it is {1} in {2}", NAME, VISIBILITY, NAME_OF_CONTAINING_DECLARATION_OR_FILE);
|
||||||
MAP.put(INVISIBLE_MEMBER, "Cannot access ''{0}'': it is {1} in {2}", NAME, VISIBILITY, NAME_OF_CONTAINING_DECLARATION_OR_FILE);
|
MAP.put(INVISIBLE_MEMBER, "Cannot access ''{0}'': it is {1} in {2}", NAME, VISIBILITY, NAME_OF_CONTAINING_DECLARATION_OR_FILE);
|
||||||
MAP.put(DEPRECATED_ACCESS_BY_SHORT_NAME, "Access to this type by short name is deprecated, and soon is going to be removed. Please, add explicit qualifier or import", NAME);
|
MAP.put(DEPRECATED_ACCESS_BY_SHORT_NAME, "Access to this type by short name is deprecated, and soon is going to be removed. Please, add explicit qualifier or import", NAME);
|
||||||
|
MAP.put(DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY, "Ambiguous access to companion's property ''{0}'' in enum is deprecated. Please, add explicit Companion qualifier to the class name", NAME);
|
||||||
|
|
||||||
MAP.put(PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL, "Protected constructor ''{0}'' from other classes can only be used in super-call", Renderers.SHORT_NAMES_IN_TYPES);
|
MAP.put(PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL, "Protected constructor ''{0}'' from other classes can only be used in super-call", Renderers.SHORT_NAMES_IN_TYPES);
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ private val DEFAULT_CALL_CHECKERS = listOf(
|
|||||||
MissingDependencySupertypeChecker.ForCalls, AbstractClassInstantiationChecker, SuspendConversionCallChecker,
|
MissingDependencySupertypeChecker.ForCalls, AbstractClassInstantiationChecker, SuspendConversionCallChecker,
|
||||||
UnitConversionCallChecker, FunInterfaceConstructorReferenceChecker, NullableExtensionOperatorWithSafeCallChecker,
|
UnitConversionCallChecker, FunInterfaceConstructorReferenceChecker, NullableExtensionOperatorWithSafeCallChecker,
|
||||||
ReferencingToUnderscoreNamedParameterOfCatchBlockChecker, VarargWrongExecutionOrderChecker, SelfCallInNestedObjectConstructorChecker,
|
ReferencingToUnderscoreNamedParameterOfCatchBlockChecker, VarargWrongExecutionOrderChecker, SelfCallInNestedObjectConstructorChecker,
|
||||||
NewSchemeOfIntegerOperatorResolutionChecker
|
NewSchemeOfIntegerOperatorResolutionChecker, EnumEntryVsCompanionPriorityCallChecker,
|
||||||
)
|
)
|
||||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||||
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(
|
||||||
|
|||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* 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.checkers
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassValueReceiver
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
|
|
||||||
|
object EnumEntryVsCompanionPriorityCallChecker : CallChecker {
|
||||||
|
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||||
|
val descriptor = resolvedCall.candidateDescriptor
|
||||||
|
if (descriptor !is PropertyDescriptor) return
|
||||||
|
val propertyName = descriptor.name
|
||||||
|
|
||||||
|
val containingDescriptor = descriptor.containingDeclaration
|
||||||
|
if (containingDescriptor !is ClassDescriptor || !containingDescriptor.isCompanionObject) return
|
||||||
|
|
||||||
|
val grandParent = containingDescriptor.containingDeclaration
|
||||||
|
|
||||||
|
if (grandParent is ClassDescriptor &&
|
||||||
|
grandParent.kind == ClassKind.ENUM_CLASS &&
|
||||||
|
grandParent.containsEntryWithName(propertyName) &&
|
||||||
|
resolvedCall.dispatchReceiver.isQualifierFor(grandParent)) {
|
||||||
|
context.resolutionContext.trace.report(Errors.DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY.on(reportOn, descriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ClassDescriptor.containsEntryWithName(name: Name): Boolean {
|
||||||
|
val foundDescriptor = unsubstitutedMemberScope.getContributedClassifier(name, NoLookupLocation.FOR_ALREADY_TRACKED)
|
||||||
|
return foundDescriptor is ClassDescriptor && foundDescriptor.kind == ClassKind.ENUM_ENTRY
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ReceiverValue?.isQualifierFor(classDescriptor: ClassDescriptor): Boolean {
|
||||||
|
if (this !is ClassValueReceiver) return false
|
||||||
|
val thisClass = this.classQualifier.descriptor as? ClassDescriptor ?: return false
|
||||||
|
return thisClass.typeConstructor == classDescriptor.typeConstructor
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
package test
|
||||||
|
enum class E {
|
||||||
|
Entry;
|
||||||
|
companion object {
|
||||||
|
val Entry = ""
|
||||||
|
val NotEntry = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
import test.E.Entry
|
||||||
|
import test.E.Companion as W
|
||||||
|
import test.E as U
|
||||||
|
import test.E
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
E.Entry checkType { _<E>() }
|
||||||
|
E.Entry checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
|
E.Companion.Entry checkType { _<String>() }
|
||||||
|
E.NotEntry checkType { _<String>() }
|
||||||
|
Entry checkType { _<E>() }
|
||||||
|
|
||||||
|
W.Entry checkType { _<String>() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Aliased.kt
|
||||||
|
|
||||||
|
import test.E as U
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
U.Entry checkType { <!INAPPLICABLE_CANDIDATE!>_<!><<!UNRESOLVED_REFERENCE!>E<!>>() }
|
||||||
|
U.Entry checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
|
U.Companion.Entry checkType { _<String>() }
|
||||||
|
U.NotEntry checkType { _<String>() }
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
package test
|
||||||
|
enum class E {
|
||||||
|
Entry;
|
||||||
|
companion object {
|
||||||
|
val Entry = ""
|
||||||
|
val NotEntry = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
import test.E.Entry
|
||||||
|
import test.E.Companion as W
|
||||||
|
import test.E as U
|
||||||
|
import test.E
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
E.<!DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY!>Entry<!> checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><E>() }
|
||||||
|
E.<!DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY!>Entry<!> checkType { _<String>() }
|
||||||
|
E.Companion.Entry checkType { _<String>() }
|
||||||
|
E.NotEntry checkType { _<String>() }
|
||||||
|
Entry checkType { _<E>() }
|
||||||
|
|
||||||
|
W.Entry checkType { _<String>() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Aliased.kt
|
||||||
|
|
||||||
|
import test.E as U
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
U.<!DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY!>Entry<!> checkType { _<<!UNRESOLVED_REFERENCE!>E<!>>() }
|
||||||
|
U.<!DEPRECATED_ACCESS_TO_ENUM_COMPANION_PROPERTY!>Entry<!> checkType { _<String>() }
|
||||||
|
U.Companion.Entry checkType { _<String>() }
|
||||||
|
U.NotEntry checkType { _<String>() }
|
||||||
|
}
|
||||||
Generated
+6
@@ -23285,6 +23285,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
runTest("compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("propertyInCompanionOfEnum.kt")
|
||||||
|
public void testPropertyInCompanionOfEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/resolve/propertyInCompanionOfEnum.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
||||||
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
||||||
|
|||||||
+5
@@ -23274,6 +23274,11 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@TestMetadata("propertyInCompanionOfEnum.kt")
|
||||||
|
public void testPropertyInCompanionOfEnum() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/resolve/propertyInCompanionOfEnum.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
@TestMetadata("resolveAnnotatedLambdaArgument.kt")
|
||||||
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
public void testResolveAnnotatedLambdaArgument() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/resolve/resolveAnnotatedLambdaArgument.kt");
|
runTest("compiler/testData/diagnostics/tests/resolve/resolveAnnotatedLambdaArgument.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user