Allow default object to be denoted with 'default' modifier

Report 'default' modifier in illegal positions
This commit is contained in:
Pavel V. Talanov
2015-03-05 16:43:26 +03:00
parent b73d7e19b7
commit 913724f0e9
9 changed files with 337 additions and 3 deletions
@@ -91,7 +91,7 @@ public class JetObjectDeclaration extends JetNamedDeclarationStub<KotlinObjectSt
if (stub != null) {
return stub.isDefault();
}
return getClassKeyword() != null;
return getClassKeyword() != null || hasModifier(JetTokens.DEFAULT_KEYWORD);
}
@Override
@@ -39,6 +39,7 @@ import java.util.*;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.lexer.JetTokens.*;
import static org.jetbrains.kotlin.psi.JetStubbedPsiUtil.getContainingDeclaration;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isDefaultObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
@@ -141,6 +142,7 @@ public class ModifiersChecker {
}
else {
checkInnerModifier(modifierListOwner, descriptor);
checkDefaultModifier(modifierListOwner);
checkModalityModifiers(modifierListOwner);
checkVisibilityModifiers(modifierListOwner, descriptor);
checkVarianceModifiersOfTypeParameters(modifierListOwner);
@@ -232,6 +234,24 @@ public class ModifiersChecker {
IN_OBJECT,
}
private void checkDefaultModifier(@NotNull JetDeclaration declaration) {
if (declaration.hasModifier(DEFAULT_KEYWORD) && !isDefaultModifierAllowed(declaration)) {
reportIllegalModifiers(declaration, Collections.singletonList(DEFAULT_KEYWORD));
}
}
// NOTE: just checks if this is legal context for default modifier (Default object descriptor can be created)
// DEFAULT_OBJECT_NOT_ALLOWED can be reported later
public static boolean isDefaultModifierAllowed(@NotNull JetDeclaration declaration) {
if (declaration instanceof JetObjectDeclaration) {
JetDeclaration containingDeclaration = getContainingDeclaration(declaration);
if (containingDeclaration instanceof JetClassOrObject) {
return true;
}
}
return false;
}
@NotNull
private static InnerModifierCheckResult checkIllegalInner(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION;
@@ -20,9 +20,9 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.name.FqName;
import java.util.Collections;
import java.util.List;
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind;
import org.jetbrains.kotlin.psi.JetObjectDeclaration;
import org.jetbrains.kotlin.psi.JetParameter;
import org.jetbrains.kotlin.psi.JetTypeParameterList;
import org.jetbrains.kotlin.resolve.ModifiersChecker;
import java.util.Collections;
import java.util.List;
@@ -54,6 +55,6 @@ public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
}
public boolean isDefaultObject() {
return element.isDefault();
return element.isDefault() && ModifiersChecker.isDefaultModifierAllowed(element);
}
}
@@ -0,0 +1,17 @@
class A {
inner class I {
default <!DEFAULT_OBJECT_NOT_ALLOWED!>object A<!>
default <!MANY_DEFAULT_OBJECTS, MANY_DEFAULT_OBJECTS, DEFAULT_OBJECT_NOT_ALLOWED!>object B<!>
default <!MANY_DEFAULT_OBJECTS, MANY_DEFAULT_OBJECTS, DEFAULT_OBJECT_NOT_ALLOWED!>object C<!>
}
}
object O {
default <!DEFAULT_OBJECT_NOT_ALLOWED!>object A<!>
default <!MANY_DEFAULT_OBJECTS, DEFAULT_OBJECT_NOT_ALLOWED!>object B<!>
default <!MANY_DEFAULT_OBJECTS, DEFAULT_OBJECT_NOT_ALLOWED!>object C<!>
}
@@ -0,0 +1,64 @@
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 final inner class I {
public constructor I()
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 class 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 class object B {
private constructor 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 class object C {
private 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 object O {
private constructor O()
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 class 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 class object B {
private constructor 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 class object C {
private 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
}
}
@@ -0,0 +1,55 @@
<!ILLEGAL_MODIFIER!>default<!> class A {
default object {
}
}
class B {
default object
val c: Int = 1
}
class C {
default object A {
}
}
class D {
default object A {
default <!DEFAULT_OBJECT_NOT_ALLOWED!>object<!> {
}
}
}
<!ILLEGAL_MODIFIER!>default<!> object G {
default <!DEFAULT_OBJECT_NOT_ALLOWED!>object<!>
}
<!ILLEGAL_MODIFIER!>default<!> trait H {
default object
}
class J {
default object C {
default <!DEFAULT_OBJECT_NOT_ALLOWED!>object<!>
}
}
<!ILLEGAL_MODIFIER!>default<!> enum class Enum {
E1
E2
default object
}
<!ILLEGAL_MODIFIER!>default<!> fun main() {
}
<!ILLEGAL_MODIFIER!>default<!> var prop: Int = 1
<!ILLEGAL_MODIFIER!>default<!> get
<!ILLEGAL_MODIFIER!>default<!> set
class Z(<!ILLEGAL_MODIFIER!>default<!> val c: Int)
@@ -0,0 +1,165 @@
package
internal var prop: kotlin.Int
internal fun main(): kotlin.Unit
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 class 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
}
}
internal final class B {
public constructor B()
internal final val c: 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 class 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
}
}
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 class 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 D {
public constructor D()
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 class 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 class 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
}
}
}
internal final enum class Enum : kotlin.Enum<Enum> {
public enum entry E1 : Enum {
private constructor E1()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Enum): 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
}
public enum entry E2 : Enum {
private constructor E2()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Enum): 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 Enum()
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Enum): 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
internal class 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
}
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Enum
public final /*synthesized*/ fun values(): kotlin.Array<Enum>
}
internal object G {
private 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
internal class 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
}
}
internal trait H {
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 class 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
}
}
internal final class J {
public constructor J()
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 class object C {
private 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 class 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
}
}
}
internal final class Z {
public constructor Z(/*0*/ c: kotlin.Int)
internal final val c: kotlin.Int
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
}
@@ -1576,6 +1576,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("multipleDissallowedDefaultObjects.kt")
public void testMultipleDissallowedDefaultObjects() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classObjects/multipleDissallowedDefaultObjects.kt");
doTest(fileName);
}
@TestMetadata("nestedClassInPrivateClassObject.kt")
public void testNestedClassInPrivateClassObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classObjects/nestedClassInPrivateClassObject.kt");
@@ -7380,6 +7386,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/modifiers"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultModifier.kt")
public void testDefaultModifier() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/defaultModifier.kt");
doTest(fileName);
}
@TestMetadata("IllegalModifiers.kt")
public void testIllegalModifiers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.kt");