From 2987e72d29603c7fbf6511f283569bf3d49a3e27 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 11 Mar 2015 14:05:35 +0300 Subject: [PATCH] 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 --- .../kotlin/resolve/DeclarationResolver.kt | 18 ++--------- .../kotlin/resolve/LazyTopDownAnalyzer.java | 2 +- .../defaultObjectSameNamesAsInOuter.kt | 18 +++++++++++ .../classObjectCopiedFieldObject.kt | 14 ++++++--- .../classObjectCopiedFieldObject.txt | 26 ++++++++++++---- .../enum/inner/redeclarationInClassObject.kt | 6 ++-- .../EnumEntriesAndClassObjectMembers.kt | 11 ------- ...oRedeclarationForClassesInDefaultObject.kt | 12 ++++++++ ...edeclarationForClassesInDefaultObject.txt} | 0 ...onForEnumEntriesAndDefaultObjectMembers.kt | 11 +++++++ ...ForEnumEntriesAndDefaultObjectMembers.txt} | 0 .../RedeclarationInDefaultObject.kt | 6 ++++ .../RedeclarationInDefaultObject.txt | 23 ++++++++++++++ .../tests/redeclarations/kt2247.kt | 14 --------- .../checkers/JetDiagnosticsTestGenerated.java | 30 +++++++++++-------- .../BlackBoxCodegenTestGenerated.java | 6 ++++ .../fields/classObjectCopiedFieldObject.kt | 22 +++++++++++--- .../js/test/semantics/ClassObjectTest.java | 4 +++ .../cases/defaultObjectSameNamesAsInOuter.kt | 20 +++++++++++++ 19 files changed, 172 insertions(+), 71 deletions(-) create mode 100644 compiler/testData/codegen/box/classes/defaultObjectSameNamesAsInOuter.kt delete mode 100644 compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.kt create mode 100644 compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.kt rename compiler/testData/diagnostics/tests/redeclarations/{kt2247.txt => NoRedeclarationForClassesInDefaultObject.txt} (100%) create mode 100644 compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt rename compiler/testData/diagnostics/tests/redeclarations/{EnumEntriesAndClassObjectMembers.txt => NoRedeclarationForEnumEntriesAndDefaultObjectMembers.txt} (100%) create mode 100644 compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.kt create mode 100644 compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.txt delete mode 100644 compiler/testData/diagnostics/tests/redeclarations/kt2247.kt create mode 100644 js/js.translator/testData/classObject/cases/defaultObjectSameNamesAsInOuter.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationResolver.kt index c597d289844..880909bc1f5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationResolver.kt @@ -58,24 +58,10 @@ public class DeclarationResolver { } } - public fun checkRedeclarationsInInnerClassNames(c: TopDownAnalysisContext) { + public fun checkRedeclarations(c: TopDownAnalysisContext) { 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() - for (desc in allDescriptors) { + for (desc in classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors()) { if (desc is ClassDescriptor || desc is PropertyDescriptor) { descriptorMap.put(desc.getName(), desc) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java index 5747911e686..1d86469862e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LazyTopDownAnalyzer.java @@ -292,7 +292,7 @@ public class LazyTopDownAnalyzer { resolveAllHeadersInClasses(c); declarationResolver.checkRedeclarationsInPackages(topLevelDescriptorProvider, topLevelFqNames); - declarationResolver.checkRedeclarationsInInnerClassNames(c); + declarationResolver.checkRedeclarations(c); ResolveUtilPackage.checkTraitRequirements(c.getDeclaredClasses(), trace); diff --git a/compiler/testData/codegen/box/classes/defaultObjectSameNamesAsInOuter.kt b/compiler/testData/codegen/box/classes/defaultObjectSameNamesAsInOuter.kt new file mode 100644 index 00000000000..1f8dfdcfd4e --- /dev/null +++ b/compiler/testData/codegen/box/classes/defaultObjectSameNamesAsInOuter.kt @@ -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" +} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.kt index 4853ec2023a..8dd4f8c6b1a 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.kt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.kt @@ -1,9 +1,15 @@ -class C { - default object { - val Default = this +class B { + default object A { + } + + val A = this +} + +class C { + default object A { + val A = this } - val Default = C } class D { diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.txt index a988b4d8eea..f3d32919b9b 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.txt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/specialNames/classObjectCopiedFieldObject.txt @@ -1,15 +1,29 @@ package -internal final class C { - public constructor C() - internal final val Default: C.Default +internal final class B { + public constructor B() + 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 hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - internal default object Default { - private constructor Default() - internal final val Default: C.Default + internal default object A { + private 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 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 hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.kt b/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.kt index 8d9dbfad721..f2dd8b0c906 100644 --- a/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.kt +++ b/compiler/testData/diagnostics/tests/enum/inner/redeclarationInClassObject.kt @@ -1,11 +1,11 @@ class A { - enum class E { + enum class E { ENTRY } default object { - enum class E { + enum class E { ENTRY2 } } -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.kt b/compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.kt deleted file mode 100644 index 65e45da4d37..00000000000 --- a/compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.kt +++ /dev/null @@ -1,11 +0,0 @@ -enum class E { - FIRST - - SECOND - - default object { - class FIRST - - val SECOND = this - } -} diff --git a/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.kt b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.kt new file mode 100644 index 00000000000..e8b1de01010 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.kt @@ -0,0 +1,12 @@ +package kt2247 + +class B { + default object { + class Y { + } + } + + class Y { + } + +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/kt2247.txt b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.txt similarity index 100% rename from compiler/testData/diagnostics/tests/redeclarations/kt2247.txt rename to compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForClassesInDefaultObject.txt diff --git a/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt new file mode 100644 index 00000000000..83a3eeaac99 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.kt @@ -0,0 +1,11 @@ +enum class E { + FIRST + + SECOND + + default object { + class FIRST + + val SECOND = this + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.txt b/compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.txt similarity index 100% rename from compiler/testData/diagnostics/tests/redeclarations/EnumEntriesAndClassObjectMembers.txt rename to compiler/testData/diagnostics/tests/redeclarations/NoRedeclarationForEnumEntriesAndDefaultObjectMembers.txt diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.kt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.kt new file mode 100644 index 00000000000..e0fb7f8190d --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.kt @@ -0,0 +1,6 @@ +class A { + default object B { + class G + val G = 1 + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.txt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.txt new file mode 100644 index 00000000000..7af510ead65 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInDefaultObject.txt @@ -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 + } + } +} diff --git a/compiler/testData/diagnostics/tests/redeclarations/kt2247.kt b/compiler/testData/diagnostics/tests/redeclarations/kt2247.kt deleted file mode 100644 index 6addeabf500..00000000000 --- a/compiler/testData/diagnostics/tests/redeclarations/kt2247.kt +++ /dev/null @@ -1,14 +0,0 @@ -//KT-2247 Report name clashes between inner classes and members of default object - -package kt2247 - -class B { - default object { - class Y { - } - } - - class Y { - } - -} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 6ab32b246b7..4c8eefbb73f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -9195,18 +9195,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { 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") public void testKt2418() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/kt2418.kt"); @@ -9231,6 +9219,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { 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") public void testPropertyAndFunInClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/PropertyAndFunInClass.kt"); @@ -9243,6 +9243,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { 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") public void testRedeclarationInMultiFile() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 27f36d3baf0..a106a301601 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -1007,6 +1007,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { 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") public void testDelegation2() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/delegation2.kt"); diff --git a/idea/testData/checker/duplicateJvmSignature/fields/classObjectCopiedFieldObject.kt b/idea/testData/checker/duplicateJvmSignature/fields/classObjectCopiedFieldObject.kt index 4a3bdb5405e..40219030345 100644 --- a/idea/testData/checker/duplicateJvmSignature/fields/classObjectCopiedFieldObject.kt +++ b/idea/testData/checker/duplicateJvmSignature/fields/classObjectCopiedFieldObject.kt @@ -1,7 +1,21 @@ -class C { - default object { - val Default = this +class B { + default object A { } - val Default = C + val A = this +} + +class C { + default object A { + val A = this + } + +} + +class D { + default object A { + val `OBJECT$` = this + } + + val `OBJECT$` = D } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassObjectTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassObjectTest.java index 7c5f4a50ee1..4b0cde8ffdf 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassObjectTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/ClassObjectTest.java @@ -47,4 +47,8 @@ public final class ClassObjectTest extends SingleFileTranslationTest { public void testNamedClassObject() throws Exception { checkFooBoxIsOk(); } + + public void testDefaultObjectSameNamesAsInOuter() throws Exception { + checkFooBoxIsOk(); + } } diff --git a/js/js.translator/testData/classObject/cases/defaultObjectSameNamesAsInOuter.kt b/js/js.translator/testData/classObject/cases/defaultObjectSameNamesAsInOuter.kt new file mode 100644 index 00000000000..3c827c1d120 --- /dev/null +++ b/js/js.translator/testData/classObject/cases/defaultObjectSameNamesAsInOuter.kt @@ -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" +}