Default 'abstract' in traits

This commit is contained in:
svtk
2011-09-08 18:31:56 +04:00
parent cd2db7f1ee
commit 2c3076d1c2
12 changed files with 79 additions and 53 deletions
@@ -45,5 +45,5 @@ public interface ClassDescriptor extends ClassifierDescriptor {
boolean isObject();
@NotNull
ClassModifiers getClassModifiers();
ClassModifiers getModifiers();
}
@@ -118,7 +118,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
@Override
@NotNull
public ClassModifiers getClassModifiers() {
public ClassModifiers getModifiers() {
return ClassModifiers.DEFAULT_MODIFIERS;
}
}
@@ -4,15 +4,17 @@ package org.jetbrains.jet.lang.descriptors;
* @author svtk
*/
public class ClassModifiers extends Modifiers {
public static final ClassModifiers DEFAULT_MODIFIERS = new ClassModifiers(false, false, false);
public static final ClassModifiers DEFAULT_MODIFIERS = new ClassModifiers(false, false, false, false);
private boolean open;
private boolean trait;
private boolean isEnum;
public ClassModifiers(boolean anAbstract, boolean open, boolean trait) {
public ClassModifiers(boolean anAbstract, boolean open, boolean trait, boolean isEnum) {
super(anAbstract);
this.open = open;
this.trait = trait;
this.isEnum = isEnum;
}
public boolean isOpen() {
@@ -22,6 +24,8 @@ public class ClassModifiers extends Modifiers {
public boolean isTrait() {
return trait;
}
public boolean isEnum() {
return isEnum;
}
}
@@ -141,8 +141,8 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
@Override
@NotNull
public ClassModifiers getClassModifiers() {
return original.getClassModifiers();
public ClassModifiers getModifiers() {
return original.getModifiers();
}
@Override
@@ -254,7 +254,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override
@NotNull
public ClassModifiers getClassModifiers() {
public ClassModifiers getModifiers() {
return classModifiers;
}
@@ -561,10 +561,12 @@ public class ClassDescriptorResolver {
if (modifierList == null) return ClassModifiers.DEFAULT_MODIFIERS;
boolean abstractModifier = modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD);
boolean traitModifier = modifierList.hasModifier(JetTokens.TRAIT_KEYWORD);
boolean enumModifier = modifierList.hasModifier(JetTokens.ENUM_KEYWORD);
return new ClassModifiers(
abstractModifier || traitModifier,
modifierList.hasModifier(JetTokens.OPEN_KEYWORD) || abstractModifier || traitModifier,
traitModifier
traitModifier,
enumModifier
);
}
@@ -487,7 +487,7 @@ public class TopDownAnalyzer {
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (!klass.hasPrimaryConstructor()) return;
if (classDescriptor.getClassModifiers().isTrait()) {
if (classDescriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor");
}
@@ -509,7 +509,7 @@ public class TopDownAnalyzer {
}
private void processSecondaryConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) {
if (classDescriptor.getClassModifiers().isTrait()) {
if (classDescriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(constructor.getNameNode(), "A trait may not have a constructor");
}
ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor(
@@ -632,7 +632,7 @@ public class TopDownAnalyzer {
@Override
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
if (descriptor.getClassModifiers().isTrait()) {
if (descriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(specifier.getNode(), "Traits can not use delegation");
}
JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
@@ -653,7 +653,7 @@ public class TopDownAnalyzer {
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
if (descriptor.getClassModifiers().isTrait()) {
if (descriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(node, "Traits can not initialize supertypes");
}
JetTypeReference typeReference = call.getTypeReference();
@@ -664,7 +664,7 @@ public class TopDownAnalyzer {
recordSupertype(typeReference, supertype);
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
if (classDescriptor != null) {
if (classDescriptor.getClassModifiers().isTrait()) {
if (classDescriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(node, "A trait may not have a constructor");
}
}
@@ -673,7 +673,7 @@ public class TopDownAnalyzer {
recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
}
}
else if (!descriptor.getClassModifiers().isTrait()) {
else if (!descriptor.getModifiers().isTrait()) {
JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
recordSupertype(typeReference, supertype);
@@ -692,8 +692,8 @@ public class TopDownAnalyzer {
if (supertype != null) {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
if (classDescriptor != null) {
if (!descriptor.getClassModifiers().isTrait()) {
if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && !classDescriptor.getClassModifiers().isTrait()) {
if (!descriptor.getModifiers().isTrait()) {
if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && !classDescriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here");
}
}
@@ -735,7 +735,7 @@ public class TopDownAnalyzer {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
if (classDescriptor != null) {
if (!classDescriptor.getClassModifiers().isTrait()) {
if (!classDescriptor.getModifiers().isTrait()) {
if (classAppeared) {
trace.getErrorHandler().genericError(typeReference.getNode(), "Only one class may appear in a supertype list");
}
@@ -987,7 +987,7 @@ public class TopDownAnalyzer {
"Global property can not be abstract");
return;
}
if (!classDescriptor.getClassModifiers().isAbstract()) {
if (!classDescriptor.getModifiers().isAbstract()) {
trace.getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName());
return;
@@ -1008,7 +1008,7 @@ public class TopDownAnalyzer {
if (initializer == null && !trace.getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) {
if (classDescriptor == null || (getter != null && getter.getBodyExpression() != null) || (setter != null && setter.getBodyExpression() != null)) {
trace.getErrorHandler().genericError(nameNode, "Property must be initialized");
} else if (!classDescriptor.getClassModifiers().isTrait()) {
} else if (!classDescriptor.getModifiers().isTrait()) {
trace.getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract");
}
}
@@ -1022,22 +1022,34 @@ public class TopDownAnalyzer {
protected void checkFunction(JetNamedFunction function, FunctionDescriptor functionDescriptor, DeclarationDescriptor containingDescriptor) {
PsiElement nameIdentifier = function.getNameIdentifier();
boolean isAbstract = functionDescriptor.getModifiers().isAbstract();
if (containingDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
if (functionDescriptor.getModifiers().isAbstract() && !classDescriptor.getClassModifiers().isAbstract()) {
boolean inTrait = classDescriptor.getModifiers().isTrait();
boolean inEnum = classDescriptor.getModifiers().isEnum();
boolean inAbstractClass = classDescriptor.getModifiers().isAbstract();
if (isAbstract && !inAbstractClass && !inTrait && !inEnum) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName());
}
if (function.getBodyExpression() == null && !functionDescriptor.getModifiers().isAbstract() && nameIdentifier != null) {
if (isAbstract && inTrait) {
trace.getErrorHandler().genericWarning(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Abstract modifier is not necessary in traits");
}
if (function.getBodyExpression() != null && isAbstract) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Method " + function.getName() + " with body can not be abstract");
}
if (function.getBodyExpression() == null && !isAbstract && !inTrait && nameIdentifier != null) {
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Method " + function.getName() + " without body must be abstract");
}
return;
}
if (functionDescriptor.getModifiers().isAbstract()) {
if (isAbstract) {
trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
"Global function " + function.getName() + " can not be abstract");
}
if (function.getBodyExpression() == null && !functionDescriptor.getModifiers().isAbstract() && nameIdentifier != null) {
if (function.getBodyExpression() == null && !isAbstract && nameIdentifier != null) {
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Global function " + function.getName() + " must have body");
}
}
@@ -101,7 +101,7 @@ public class CallResolver {
@Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
if (descriptor instanceof ConstructorDescriptor) {
ClassModifiers modifiers = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getClassModifiers();
ClassModifiers modifiers = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModifiers();
if (modifiers.isAbstract()) {
tracing.reportOverallResolutionError(trace, "Can not create an instance of an abstract class");
return false;
@@ -21,9 +21,6 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
private JetType classObjectType;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private ClassModifiers modifiers;
// private boolean isAbstract;
// private boolean isOpen;
// private boolean isTrait;
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) {
super(containingDeclaration);
@@ -33,11 +30,8 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
this.typeConstructor = typeConstructor;
}
public void setModifiers(boolean isAbstract, boolean isOpen, boolean isTrait) {
this.modifiers = new ClassModifiers(isAbstract, isOpen, isTrait);
// this.isAbstract = isAbstract;
// this.isOpen = isOpen;
// this.isTrait = isTrait;
public void setModifiers(boolean isAbstract, boolean isOpen, boolean isTrait, boolean isEnum) {
this.modifiers = new ClassModifiers(isAbstract, isOpen, isTrait, isEnum);
}
public void setUnsubstitutedMemberScope(JavaClassMembersScope memberScope) {
@@ -131,24 +125,9 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
return false;
}
// @Override
// public boolean isAbstract() {
// return isAbstract;
// }
//
// @Override
// public boolean isOpen() {
// return isOpen;
// }
//
// @Override
// public boolean isTrait() {
// return isTrait;
// }
@Override
@NotNull
public ClassModifiers getClassModifiers() {
public ClassModifiers getModifiers() {
return modifiers;
}
@@ -109,7 +109,8 @@ public class JavaDescriptorResolver {
classDescriptor.setModifiers(
psiClass.hasModifierProperty(PsiModifier.ABSTRACT),
!psiClass.hasModifierProperty(PsiModifier.FINAL),
psiClass.isInterface()
psiClass.isInterface(),
psiClass.isEnum()
);
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
@@ -251,7 +251,7 @@ public class DescriptorRenderer {
@Override
public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) {
String keyword = descriptor.getClassModifiers().isTrait() ? "trait class" : "class";
String keyword = descriptor.getModifiers().isTrait() ? "trait class" : "class";
renderClassDescriptor(descriptor, builder, keyword);
return super.visitClassDescriptor(descriptor, builder);
}
+29 -1
View File
@@ -1,5 +1,33 @@
namespace abstract
class MyClass() {
fun <error>f</error>()
fun g() {}
<error>abstract</error> fun h()
<error>abstract</error> fun j() {}
}
abstract class MyAbstractClass() {
fun <error>f</error>()
fun g() {}
abstract fun h()
<error>abstract</error> fun j() {}
}
trait class MyTrait {
fun f()
fun g() {}
<warning>abstract</warning> fun h()
<error>abstract</error> fun j() {}
}
enum class MyEnum {
fun <error>f</error>()
fun g() {}
abstract fun h()
<error>abstract</error> fun j() {}
}
class A1() {
fun <error>foo</error>(): Int
<error>abstract</error> fun f(): Int
@@ -65,4 +93,4 @@ abstract class B3(i: Int) {
fun foo(a: B3) {
val a = <error>B3()</error>
val b = <error>B1(2, "s")</error>
}
}