Do not report redeclaration when outer class and default object's members clash
Previously we prohibited classes and properties with the same name (now it's unnecessary) Add test for backends that they support qualified (by default object name) member references inside class body
This commit is contained in:
@@ -58,24 +58,10 @@ public class DeclarationResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun checkRedeclarationsInInnerClassNames(c: TopDownAnalysisContext) {
|
public fun checkRedeclarations(c: TopDownAnalysisContext) {
|
||||||
for (classDescriptor in c.getDeclaredClasses().values()) {
|
for (classDescriptor in c.getDeclaredClasses().values()) {
|
||||||
if (DescriptorUtils.isDefaultObject(classDescriptor)) {
|
|
||||||
// Default objects should be considered during analysing redeclarations in classes
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors()
|
|
||||||
val defaultObject = classDescriptor.getDefaultObjectDescriptor()
|
|
||||||
if (defaultObject != null) {
|
|
||||||
val descriptorsFromDefaultObject = defaultObject.getScopeForMemberLookup().getOwnDeclaredDescriptors()
|
|
||||||
if (descriptorsFromDefaultObject.isNotEmpty()) {
|
|
||||||
allDescriptors = allDescriptors + descriptorsFromDefaultObject
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val descriptorMap = HashMultimap.create<Name, DeclarationDescriptor>()
|
val descriptorMap = HashMultimap.create<Name, DeclarationDescriptor>()
|
||||||
for (desc in allDescriptors) {
|
for (desc in classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors()) {
|
||||||
if (desc is ClassDescriptor || desc is PropertyDescriptor) {
|
if (desc is ClassDescriptor || desc is PropertyDescriptor) {
|
||||||
descriptorMap.put(desc.getName(), desc)
|
descriptorMap.put(desc.getName(), desc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public class LazyTopDownAnalyzer {
|
|||||||
resolveAllHeadersInClasses(c);
|
resolveAllHeadersInClasses(c);
|
||||||
|
|
||||||
declarationResolver.checkRedeclarationsInPackages(topLevelDescriptorProvider, topLevelFqNames);
|
declarationResolver.checkRedeclarationsInPackages(topLevelDescriptorProvider, topLevelFqNames);
|
||||||
declarationResolver.checkRedeclarationsInInnerClassNames(c);
|
declarationResolver.checkRedeclarations(c);
|
||||||
|
|
||||||
ResolveUtilPackage.checkTraitRequirements(c.getDeclaredClasses(), trace);
|
ResolveUtilPackage.checkTraitRequirements(c.getDeclaredClasses(), trace);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class A {
|
||||||
|
private val p: Int
|
||||||
|
get() = 4
|
||||||
|
|
||||||
|
default object B {
|
||||||
|
val p: Int
|
||||||
|
get() = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
fun a() = p + B.p
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (A().a() != 10) return "Fail"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+10
-4
@@ -1,9 +1,15 @@
|
|||||||
class C {
|
class B {
|
||||||
default <!REDECLARATION!>object<!> {
|
default object <!REDECLARATION!>A<!> {
|
||||||
val <!REDECLARATION!>Default<!> = this
|
}
|
||||||
|
|
||||||
|
val <!REDECLARATION!>A<!> = this
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
default <!CONFLICTING_JVM_DECLARATIONS!>object A<!> {
|
||||||
|
<!CONFLICTING_JVM_DECLARATIONS!>val A<!> = this
|
||||||
}
|
}
|
||||||
|
|
||||||
val <!REDECLARATION!>Default<!> = C
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class D {
|
class D {
|
||||||
|
|||||||
+20
-6
@@ -1,15 +1,29 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
internal final class C {
|
internal final class B {
|
||||||
public constructor C()
|
public constructor B()
|
||||||
internal final val Default: C.Default
|
internal final val A: B
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
internal default object Default {
|
internal default object A {
|
||||||
private constructor Default()
|
private constructor A()
|
||||||
internal final val Default: C.Default
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal final class C {
|
||||||
|
public constructor C()
|
||||||
|
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
|
||||||
|
|
||||||
|
internal default object A {
|
||||||
|
private constructor A()
|
||||||
|
internal final val A: C.A
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
class A {
|
class A {
|
||||||
enum class <!REDECLARATION!>E<!> {
|
enum class E {
|
||||||
ENTRY
|
ENTRY
|
||||||
}
|
}
|
||||||
|
|
||||||
default object {
|
default object {
|
||||||
enum class <!REDECLARATION!>E<!> {
|
enum class E {
|
||||||
ENTRY2
|
ENTRY2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
enum class E {
|
|
||||||
<!REDECLARATION!>FIRST<!>
|
|
||||||
|
|
||||||
<!REDECLARATION!>SECOND<!>
|
|
||||||
|
|
||||||
default object {
|
|
||||||
class <!REDECLARATION!>FIRST<!>
|
|
||||||
|
|
||||||
val <!REDECLARATION!>SECOND<!> = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package kt2247
|
||||||
|
|
||||||
|
class B {
|
||||||
|
default object {
|
||||||
|
class Y {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Y {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
enum class E {
|
||||||
|
FIRST
|
||||||
|
|
||||||
|
SECOND
|
||||||
|
|
||||||
|
default object {
|
||||||
|
class FIRST
|
||||||
|
|
||||||
|
val SECOND = this
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class A {
|
||||||
|
default object B {
|
||||||
|
class <!REDECLARATION!>G<!>
|
||||||
|
val <!REDECLARATION!>G<!> = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal 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
|
||||||
|
|
||||||
|
internal default object B {
|
||||||
|
private constructor B()
|
||||||
|
internal final val G: kotlin.Int = 1
|
||||||
|
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
|
||||||
|
|
||||||
|
internal final class G {
|
||||||
|
public constructor G()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
//KT-2247 Report name clashes between inner classes and members of default object
|
|
||||||
|
|
||||||
package kt2247
|
|
||||||
|
|
||||||
class B {
|
|
||||||
default object {
|
|
||||||
class <!REDECLARATION!>Y<!> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class <!REDECLARATION!>Y<!> {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9195,18 +9195,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("EnumEntriesAndClassObjectMembers.kt")
|
|
||||||
public void testEnumEntriesAndClassObjectMembers() throws Exception {
|
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.kt");
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("kt2247.kt")
|
|
||||||
public void testKt2247() throws Exception {
|
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/kt2247.kt");
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("kt2418.kt")
|
@TestMetadata("kt2418.kt")
|
||||||
public void testKt2418() throws Exception {
|
public void testKt2418() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/kt2418.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/kt2418.kt");
|
||||||
@@ -9231,6 +9219,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NoRedeclarationForClassesInDefaultObject.kt")
|
||||||
|
public void testNoRedeclarationForClassesInDefaultObject() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt")
|
||||||
|
public void testNoRedeclarationForEnumEntriesAndDefaultObjectMembers() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("PropertyAndFunInClass.kt")
|
@TestMetadata("PropertyAndFunInClass.kt")
|
||||||
public void testPropertyAndFunInClass() throws Exception {
|
public void testPropertyAndFunInClass() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/PropertyAndFunInClass.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/PropertyAndFunInClass.kt");
|
||||||
@@ -9243,6 +9243,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("RedeclarationInDefaultObject.kt")
|
||||||
|
public void testRedeclarationInDefaultObject() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("RedeclarationInMultiFile.kt")
|
@TestMetadata("RedeclarationInMultiFile.kt")
|
||||||
public void testRedeclarationInMultiFile() throws Exception {
|
public void testRedeclarationInMultiFile() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.kt");
|
||||||
|
|||||||
+6
@@ -1007,6 +1007,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaultObjectSameNamesAsInOuter.kt")
|
||||||
|
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/defaultObjectSameNamesAsInOuter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("delegation2.kt")
|
@TestMetadata("delegation2.kt")
|
||||||
public void testDelegation2() throws Exception {
|
public void testDelegation2() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/delegation2.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/delegation2.kt");
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
class C {
|
class B {
|
||||||
default <error>object</error> {
|
default object <error>A</error> {
|
||||||
val <error>Default</error> = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val <error>Default</error> = C
|
val <error>A</error> = this
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
default <error>object A</error> {
|
||||||
|
<error>val A</error> = this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class D {
|
||||||
|
default <error>object A</error> {
|
||||||
|
<error>val `OBJECT$`</error> = this
|
||||||
|
}
|
||||||
|
|
||||||
|
val `OBJECT$` = D
|
||||||
}
|
}
|
||||||
@@ -47,4 +47,8 @@ public final class ClassObjectTest extends SingleFileTranslationTest {
|
|||||||
public void testNamedClassObject() throws Exception {
|
public void testNamedClassObject() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDefaultObjectSameNamesAsInOuter() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private val p: Int
|
||||||
|
get() = 4
|
||||||
|
|
||||||
|
default object B {
|
||||||
|
val p: Int
|
||||||
|
get() = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
fun a() = p + B.p
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (A().a() != 10) return "Fail"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user