Default 'abstract' in traits
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user