From 28fbdb7c5335ab75e83b566a3f517806e51e6eab Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Fri, 13 Feb 2015 14:55:44 +0300 Subject: [PATCH] Prohibit constructors declarations for object --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../kotlin/psi/JetSecondaryConstructor.java | 5 ++ .../kotlin/resolve/LazyTopDownAnalyzer.java | 15 +++++- .../lazy/descriptors/LazyClassMemberScope.kt | 3 +- .../constructorInObject.kt | 20 ++++++++ .../constructorInObject.txt | 48 +++++++++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 +++ .../kotlin/resolve/DescriptorUtils.java | 7 +++ 9 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.kt create mode 100644 compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index ace75d397d5..b4b2e72f64c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -156,6 +156,7 @@ public interface Errors { // Secondary constructors DiagnosticFactory0 CYCLIC_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 SECONDARY_CONSTRUCTOR_IN_OBJECT = DiagnosticFactory0.create(ERROR); // Trait-specific diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 9555d449272..9e30474f233 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -414,6 +414,7 @@ public class DefaultErrorMessages { MAP.put(SINGLETON_IN_SUPERTYPE, "Cannot inherit from a singleton"); MAP.put(CYCLIC_CONSTRUCTOR_DELEGATION_CALL, "There's a cycle in the delegation calls chain"); + MAP.put(SECONDARY_CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects"); MAP.put(ILLEGAL_SELECTOR, "Expression ''{0}'' cannot be a selector (occur after a dot)", STRING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java index 3dc4d1e5549..ef4b04f660e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java @@ -175,4 +175,9 @@ public class JetSecondaryConstructor extends JetDeclarationStub { val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject() + if (!DescriptorUtils.canHaveSecondaryConstructors(thisDescriptor)) return emptyList() + // Script classes have usual class descriptors but do not have conventional class body if (classOrObject !is JetClass) return emptyList() - if (thisDescriptor.getKind().isSingleton()) return emptyList() return classOrObject.getSecondaryConstructors().map { constructor -> val descriptor = c.descriptorResolver.resolveSecondaryConstructorDescriptor( diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.kt b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.kt new file mode 100644 index 00000000000..aed9f3cd0ba --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.kt @@ -0,0 +1,20 @@ +object A { + constructor() {} + init {} +} + +enum class B { + X : B() { + constructor() {} + } +} + +class C { + default object { + constructor() {} + } +} + +val anonObject = object { + constructor() {} +} diff --git a/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.txt b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.txt new file mode 100644 index 00000000000..16da2d008ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.txt @@ -0,0 +1,48 @@ +package + +internal val anonObject: kotlin.Any + +internal 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 enum class B : kotlin.Enum { + public enum entry X : B { + private constructor X() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: B): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + private constructor B() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: B): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): B + public final /*synthesized*/ fun values(): kotlin.Array +} + +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 Default { + private constructor 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index ede8a982d8c..b9259500056 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -10415,6 +10415,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("constructorInObject.kt") + public void testConstructorInObject() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/constructorInObject.kt"); + doTest(fileName); + } + @TestMetadata("cyclicDelegationCalls.kt") public void testCyclicDelegationCalls() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/secondaryConstructors/cyclicDelegationCalls.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index b99d2879e1c..782dffddee4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -480,4 +480,11 @@ public class DescriptorUtils { return false; } + public static boolean isSingletonOrAnonymousObject(@NotNull ClassDescriptor classDescriptor) { + return classDescriptor.getKind().isSingleton() || isAnonymousObject(classDescriptor); + } + + public static boolean canHaveSecondaryConstructors(@NotNull ClassDescriptor classDescriptor) { + return !isSingletonOrAnonymousObject(classDescriptor) && !isTrait(classDescriptor); + } }