Prohibit constructors declarations for object

This commit is contained in:
Denis Zharkov
2015-02-13 14:55:44 +03:00
parent 3fef4ad742
commit 28fbdb7c53
9 changed files with 103 additions and 3 deletions
@@ -156,6 +156,7 @@ public interface Errors {
// Secondary constructors
DiagnosticFactory0<JetConstructorDelegationCall> CYCLIC_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSecondaryConstructor> SECONDARY_CONSTRUCTOR_IN_OBJECT = DiagnosticFactory0.create(ERROR);
// Trait-specific
@@ -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);
@@ -175,4 +175,9 @@ public class JetSecondaryConstructor extends JetDeclarationStub<KotlinPlaceHolde
public JetConstructorDelegationCall getDelegationCall() {
return getStubOrPsiChild(JetStubElementTypes.CONSTRUCTOR_DELEGATION_CALL);
}
@NotNull
public JetClassOrObject getClassOrObject() {
return (JetClassOrObject) getParent().getParent();
}
}
@@ -37,6 +37,7 @@ import java.util.Collection;
import java.util.List;
import static org.jetbrains.kotlin.diagnostics.Errors.MANY_DEFAULT_OBJECTS;
import static org.jetbrains.kotlin.diagnostics.Errors.SECONDARY_CONSTRUCTOR_IN_OBJECT;
import static org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED;
public class LazyTopDownAnalyzer {
@@ -189,10 +190,10 @@ public class LazyTopDownAnalyzer {
registerDeclarations(classOrObject.getDeclarations());
registerTopLevelFqName(topLevelFqNames, classOrObject, descriptor);
checkManyDefaultObjects(classOrObject);
checkClassOrObjectDeclarations(classOrObject, descriptor);
}
private void checkManyDefaultObjects(JetClassOrObject classOrObject) {
private void checkClassOrObjectDeclarations(JetClassOrObject classOrObject, ClassDescriptor classDescriptor) {
boolean defaultObjectAlreadyFound = false;
for (JetDeclaration jetDeclaration : classOrObject.getDeclarations()) {
if (jetDeclaration instanceof JetObjectDeclaration && ((JetObjectDeclaration) jetDeclaration).isDefault()) {
@@ -201,6 +202,11 @@ public class LazyTopDownAnalyzer {
}
defaultObjectAlreadyFound = true;
}
else if (jetDeclaration instanceof JetSecondaryConstructor) {
if (DescriptorUtils.isSingletonOrAnonymousObject(classDescriptor)) {
trace.report(SECONDARY_CONSTRUCTOR_IN_OBJECT.on((JetSecondaryConstructor) jetDeclaration));
}
}
}
}
@@ -223,6 +229,11 @@ public class LazyTopDownAnalyzer {
@Override
public void visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor) {
ClassDescriptor classDescriptor =
(ClassDescriptor) lazyDeclarationResolver.resolveToDescriptor(constructor.getClassOrObject());
if (!DescriptorUtils.canHaveSecondaryConstructors(classDescriptor)) {
return;
}
c.getSecondaryConstructors().put(
constructor,
(ConstructorDescriptor) lazyDeclarationResolver.resolveToDescriptor(constructor)
@@ -297,8 +297,9 @@ public open class LazyClassMemberScope(
private fun resolveSecondaryConstructors(): Collection<ConstructorDescriptor> {
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(
@@ -0,0 +1,20 @@
object A {
<!SECONDARY_CONSTRUCTOR_IN_OBJECT!>constructor() {}<!>
init {}
}
enum class B {
X : B() {
<!SECONDARY_CONSTRUCTOR_IN_OBJECT!>constructor() {}<!>
}
}
class C {
default object {
<!SECONDARY_CONSTRUCTOR_IN_OBJECT!>constructor() {}<!>
}
}
val anonObject = object {
<!SECONDARY_CONSTRUCTOR_IN_OBJECT!>constructor() {}<!>
}
@@ -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<B> {
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<B>
}
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
}
}
@@ -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");
@@ -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);
}
}