Prohibit constructors declarations for object
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+1
@@ -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)
|
||||
|
||||
+2
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user