diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index 004e900923e..ce47d93a1eb 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -44,9 +44,6 @@ public interface ClassDescriptor extends ClassifierDescriptor { boolean isObject(); - boolean isAbstract(); - - boolean isOpen(); - - boolean isTrait(); + @NotNull + ClassModifiers getClassModifiers(); } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index 8e9407c092e..08a3aa0c600 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -117,17 +117,8 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl } @Override - public boolean isAbstract() { - return false; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public boolean isTrait() { - return false; + @NotNull + public ClassModifiers getClassModifiers() { + return ClassModifiers.DEFAULT_MODIFIERS; } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ClassModifiers.java b/idea/src/org/jetbrains/jet/lang/descriptors/ClassModifiers.java new file mode 100644 index 00000000000..ddb1897ebfd --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ClassModifiers.java @@ -0,0 +1,40 @@ +package org.jetbrains.jet.lang.descriptors; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetModifierList; +import org.jetbrains.jet.lexer.JetTokens; + +/** + * @author svtk + */ +public class ClassModifiers extends Modifiers { + public static final ClassModifiers DEFAULT_MODIFIERS = new ClassModifiers(false, false, false); + + private boolean open; + private boolean trait; + + public ClassModifiers(boolean anAbstract, boolean open, boolean trait) { + super(anAbstract); + this.open = open; + this.trait = trait; + } + + public boolean isOpen() { + return open; + } + + public boolean isTrait() { + return trait; + } + + public static ClassModifiers resolveModifiers(@Nullable JetModifierList modifierList) { + if (modifierList == null) return DEFAULT_MODIFIERS; + return new ClassModifiers( + modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD), + modifierList.hasModifier(JetTokens.OPEN_KEYWORD) || modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD), + modifierList.hasModifier(JetTokens.TRAIT_KEYWORD) + ); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java index 2196be06a71..300c3836ff5 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java @@ -28,13 +28,13 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @Override @Deprecated - public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType) { + public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, MemberModifiers modifiers) { assert receiverType == null; - return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType); + return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modifiers); } - public ConstructorDescriptorImpl initialize(@NotNull List typeParameters, @NotNull List unsubstitutedValueParameters) { - super.initialize(null, typeParameters, unsubstitutedValueParameters, null); + public ConstructorDescriptorImpl initialize(@NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, MemberModifiers modifiers) { + super.initialize(null, typeParameters, unsubstitutedValueParameters, null, modifiers); return this; } @@ -66,11 +66,6 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements return Collections.emptySet(); } - @Nullable - public MemberModifiers getModifiers() { - return null; - } - @Override public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) { throw new UnsupportedOperationException("Constructors cannot override anything"); diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index 3341cc34633..8a2f4413fdd 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -47,11 +47,13 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements @Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, - @Nullable JetType unsubstitutedReturnType) { + @Nullable JetType unsubstitutedReturnType, + @Nullable MemberModifiers modifiers) { this.receiverType = receiverType; this.typeParameters = typeParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedReturnType = unsubstitutedReturnType; + this.modifiers = modifiers; return this; } @@ -70,11 +72,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements return overriddenFunctions; } - public void setModifiers(MemberModifiers modifiers) { - this.modifiers = modifiers; - } - - @Nullable + @NotNull @Override public MemberModifiers getModifiers() { return modifiers; @@ -141,7 +139,8 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements substitutedReceiverType, substitutedTypeParameters, substitutedValueParameters, - substitutedReturnType + substitutedReturnType, + modifiers ); return substitutedDescriptor; } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 10193133e74..0bd3c58ca7c 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -140,18 +140,9 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { } @Override - public boolean isAbstract() { - return original.isAbstract(); - } - - @Override - public boolean isOpen() { - return original.isOpen(); - } - - @Override - public boolean isTrait() { - return original.isTrait(); + @NotNull + public ClassModifiers getClassModifiers() { + return original.getClassModifiers(); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/MemberModifiers.java b/idea/src/org/jetbrains/jet/lang/descriptors/MemberModifiers.java index 506e08ba4db..c3e9fe29e4c 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/MemberModifiers.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/MemberModifiers.java @@ -1,23 +1,25 @@ package org.jetbrains.jet.lang.descriptors; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetModifierList; +import org.jetbrains.jet.lexer.JetTokens; + /** * @author abreslav */ -public class MemberModifiers { +public class MemberModifiers extends Modifiers { + public static final MemberModifiers DEFAULT_MODIFIERS = new MemberModifiers(false, false, false); - private final boolean isAbstract; private final boolean isVirtual; private final boolean isOverride; public MemberModifiers(boolean isAbstract, boolean isVirtual, boolean isOverride) { - this.isAbstract = isAbstract; + super(isAbstract); this.isVirtual = isVirtual; this.isOverride = isOverride; } - public boolean isAbstract() { - return isAbstract; - } public boolean isVirtual() { return isVirtual; @@ -30,4 +32,19 @@ public class MemberModifiers { public boolean isOverridable() { return isAbstract() || isVirtual() || isOverride(); } + + @NotNull + public static MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList) { + return resolveModifiers(modifierList, DEFAULT_MODIFIERS); + } + + @NotNull + public static MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) { + if (modifierList == null) return defaultModifiers; + return new MemberModifiers( + modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD), + modifierList.hasModifier(JetTokens.VIRTUAL_KEYWORD), + modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD) + ); + } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/Modifiers.java b/idea/src/org/jetbrains/jet/lang/descriptors/Modifiers.java new file mode 100644 index 00000000000..6603316846e --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/descriptors/Modifiers.java @@ -0,0 +1,16 @@ +package org.jetbrains.jet.lang.descriptors; + +/** + * @author svtk + */ +public class Modifiers { + private final boolean isAbstract; + + public Modifiers(boolean anAbstract) { + isAbstract = anAbstract; + } + + public boolean isAbstract() { + return isAbstract; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 4c0eaa3e366..2cd0326c3ac 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -22,9 +22,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private List typeParameters = Lists.newArrayList(); private Collection supertypes = Lists.newArrayList(); - private boolean open; - private boolean isAbstract; - private boolean trait; + private ClassModifiers classModifiers; private TypeConstructor typeConstructor; private final WritableScope scopeForMemberResolution; private final WritableScope scopeForMemberLookup; @@ -143,32 +141,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme scopeForMemberResolution.addLabeledDeclaration(this); } - @Override - public boolean isAbstract() { - return isAbstract || trait; - } - - public void setAbstract(boolean isAbstract) { - this.isAbstract = isAbstract; - } - - @Override - public boolean isTrait() { - return trait; - } - - public void setTrait(boolean trait) { - this.trait = trait; - } - - public boolean isOpen() { - return open; - } - - public void setOpen(boolean open) { - this.open = open; - } - @NotNull @Override public TypeConstructor getTypeConstructor() { @@ -180,7 +152,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme this.typeConstructor = new TypeConstructorImpl( this, Collections.emptyList(), // TODO : pass annotations from the class? - !open, + !classModifiers.isOpen(), getName(), typeParameters, supertypes); @@ -276,6 +248,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme return isObject; } + public void setClassModifiers(ClassModifiers classModifiers) { + this.classModifiers = classModifiers; + } + + @Override + @NotNull + public ClassModifiers getClassModifiers() { + return classModifiers; + } + @Override public String toString() { return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]"; diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java index d465257af93..57ed3275e0b 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java @@ -16,7 +16,7 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl { assert outType != null; assert JetStandardClasses.isFunctionType(outType); VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor); - result.initialize(JetStandardClasses.getReceiverType(outType), Collections.emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType)); + result.initialize(JetStandardClasses.getReceiverType(outType), Collections.emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), MemberModifiers.DEFAULT_MODIFIERS); return result; } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java index 2c5e47472c5..a8f61283fe5 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java @@ -5,6 +5,8 @@ import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetToken; import java.util.ArrayList; @@ -57,4 +59,14 @@ public class JetModifierList extends JetElement { } return null; } + + public boolean checkNotContains(BindingTrace trace, JetToken... tokens) { + for (JetToken token : tokens) { + if (hasModifier(token)) { + trace.getErrorHandler().genericError(getModifierNode(token), "Annotation " + ((JetKeywordToken) token).getValue() + " is not allowed here"); + return false; + } + } + return true; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 79f24d4c1c4..d7294d192f7 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -26,7 +26,7 @@ import java.util.*; */ public class ClassDescriptorResolver { - private static final MemberModifiers DEFAULT_MODIFIERS = new MemberModifiers(false, false, false); +// private static final MemberModifiers DEFAULT_MODIFIERS = new MemberModifiers(false, false, false); private final JetSemanticServices semanticServices; private final TypeResolver typeResolver; @@ -144,10 +144,7 @@ public class ClassDescriptorResolver { index++; } descriptor.setTypeParameterDescriptors(typeParameters); - - descriptor.setOpen(classElement.hasModifier(JetTokens.OPEN_KEYWORD) || classElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)); - descriptor.setAbstract(classElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)); - descriptor.setTrait(classElement.hasModifier(JetTokens.TRAIT_KEYWORD)); + descriptor.setClassModifiers(ClassModifiers.resolveModifiers(classElement.getModifierList())); trace.record(BindingContext.CLASS, classElement, descriptor); } @@ -227,13 +224,13 @@ public class ClassDescriptorResolver { returnType = ErrorUtils.createErrorType("No type, no body"); } } - functionDescriptor.setModifiers(resolveModifiers(function.getModifierList(), DEFAULT_MODIFIERS)); functionDescriptor.initialize( receiverType, typeParameterDescriptors, valueParameterDescriptors, - returnType); + returnType, + MemberModifiers.resolveModifiers(function.getModifierList())); trace.record(BindingContext.FUNCTION, function, functionDescriptor); return functionDescriptor; @@ -466,7 +463,7 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.createAnnotationStubs(modifierList), - resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts + MemberModifiers.resolveModifiers(modifierList), // TODO : default modifiers differ in different contexts false, null, JetPsiUtil.safeName(objectDeclaration.getName()), @@ -516,7 +513,7 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts + MemberModifiers.resolveModifiers(modifierList), // TODO : default modifiers differ in different contexts isVar, receiverType, JetPsiUtil.safeName(property.getName()), @@ -563,16 +560,6 @@ public class ClassDescriptorResolver { } } - @NotNull - private MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) { - if (modifierList == null) return defaultModifiers; - return new MemberModifiers( - modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD), - modifierList.hasModifier(JetTokens.VIRTUAL_KEYWORD), - modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD) - ); - } - @Nullable private PropertySetterDescriptor resolvePropertySetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { JetPropertyAccessor setter = property.getSetter(); @@ -582,7 +569,7 @@ public class ClassDescriptorResolver { JetParameter parameter = setter.getParameter(); setterDescriptor = new PropertySetterDescriptor( - resolveModifiers(setter.getModifierList(), DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts + MemberModifiers.resolveModifiers(setter.getModifierList()), // TODO : default modifiers differ in different contexts propertyDescriptor, annotations, setter.getBodyExpression() != null, false); if (parameter != null) { if (parameter.isRef()) { @@ -646,7 +633,7 @@ public class ClassDescriptorResolver { } getterDescriptor = new PropertyGetterDescriptor( - resolveModifiers(getter.getModifierList(), DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts + MemberModifiers.resolveModifiers(getter.getModifierList()), // TODO : default modifiers differ in different contexts propertyDescriptor, annotations, returnType, getter.getBodyExpression() != null, false); trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); } @@ -677,12 +664,16 @@ public class ClassDescriptorResolver { isPrimary ); trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor); + if (modifierList != null) { + modifierList.checkNotContains(trace, JetTokens.ABSTRACT_KEYWORD, JetTokens.VIRTUAL_KEYWORD, JetTokens.OVERRIDE_KEYWORD); + } return constructorDescriptor.initialize( typeParameters, resolveValueParameters( constructorDescriptor, new WritableScopeImpl(scope, classDescriptor, trace.getErrorHandler()).setDebugName("Scope with value parameters of a constructor"), - valueParameters)); + valueParameters), + MemberModifiers.DEFAULT_MODIFIERS); } @Nullable @@ -717,7 +708,7 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( classDescriptor, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModifiers(modifierList, DEFAULT_MODIFIERS), + MemberModifiers.resolveModifiers(modifierList), isMutable, null, name == null ? "" : name, diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 4f90be5696d..f746751f90c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -172,6 +172,7 @@ public class TopDownAnalyzer { if (klass.hasModifier(JetTokens.ENUM_KEYWORD)) { MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(trace, mutableClassDescriptor, outerScope, true); classObjectDescriptor.setName("class-object-for-" + klass.getName()); + classObjectDescriptor.setClassModifiers(ClassModifiers.DEFAULT_MODIFIERS); classObjectDescriptor.createTypeConstructor(); createPrimaryConstructor(classObjectDescriptor); mutableClassDescriptor.setClassObjectDescriptor(classObjectDescriptor); @@ -226,7 +227,8 @@ public class TopDownAnalyzer { private void createPrimaryConstructor(MutableClassDescriptor mutableClassDescriptor) { ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.emptyList(), true); - constructorDescriptor.initialize(Collections.emptyList(), Collections.emptyList()); + constructorDescriptor.initialize(Collections.emptyList(), Collections.emptyList(), + MemberModifiers.DEFAULT_MODIFIERS); // TODO : make the constructor private? mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor); } @@ -329,6 +331,7 @@ public class TopDownAnalyzer { } for (Map.Entry entry : objects.entrySet()) { MutableClassDescriptor descriptor = entry.getValue(); + descriptor.setClassModifiers(ClassModifiers.DEFAULT_MODIFIERS); descriptor.createTypeConstructor(); } } @@ -484,7 +487,7 @@ public class TopDownAnalyzer { private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { if (!klass.hasPrimaryConstructor()) return; - if (classDescriptor.isTrait()) { + if (classDescriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor"); } @@ -506,7 +509,7 @@ public class TopDownAnalyzer { } private void processSecondaryConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) { - if (classDescriptor.isTrait()) { + if (classDescriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(constructor.getNameNode(), "A trait may not have a constructor"); } ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor( @@ -608,7 +611,7 @@ public class TopDownAnalyzer { @Override public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { - if (descriptor.isTrait()) { + if (descriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(specifier.getNode(), "Traits can not use delegation"); } JetExpression delegateExpression = specifier.getDelegateExpression(); @@ -626,7 +629,7 @@ public class TopDownAnalyzer { @Override public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { - if (descriptor.isTrait()) { + if (descriptor.getClassModifiers().isTrait()) { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); trace.getErrorHandler().genericError(node, "Traits can not initialize supertypes"); @@ -639,7 +642,7 @@ public class TopDownAnalyzer { DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; - if (classDescriptor.isTrait()) { + if (classDescriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(call.getValueArgumentList().getNode(), "A trait may not have a constructor"); } } @@ -661,13 +664,13 @@ public class TopDownAnalyzer { DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; - if (!descriptor.isTrait()) { - if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && !classDescriptor.isTrait()) { + if (!descriptor.getClassModifiers().isTrait()) { + if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && !classDescriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here"); } } else { - if (!classDescriptor.isTrait()) { + if (!classDescriptor.getClassModifiers().isTrait()) { if (superclassAppeared) { trace.getErrorHandler().genericError(specifier.getNode(), "A trait may extend only one class"); } @@ -932,7 +935,7 @@ public class TopDownAnalyzer { "Global property can not be abstract"); return; } - if (!classDescriptor.isAbstract()) { + if (!classDescriptor.getClassModifiers().isAbstract()) { trace.getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), "Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName()); return; @@ -953,7 +956,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.isTrait()) { + } else if (!classDescriptor.getClassModifiers().isTrait()) { trace.getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract"); } } @@ -969,7 +972,7 @@ public class TopDownAnalyzer { PsiElement nameIdentifier = function.getNameIdentifier(); if (containingDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; - if (functionDescriptor.getModifiers().isAbstract() && !classDescriptor.isAbstract()) { + if (functionDescriptor.getModifiers().isAbstract() && !classDescriptor.getClassModifiers().isAbstract()) { trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), "Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName()); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 0f681833fe6..49b7f1c56fa 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -97,6 +97,22 @@ public class CallResolver { if (name == null) return checkArgumentTypesAndFail(trace, scope, call); prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); + ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { + @Override + public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { + if (descriptor instanceof ConstructorDescriptor) { + ClassModifiers modifiers = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getClassModifiers(); + if (modifiers.isAbstract()) { + tracing.reportOverallResolutionError(trace, "Can not create an instance of an abstract class"); + return false; + } + } + return true; + } + }; + for (ResolutionTask task : prioritizedTasks) { + task.setCheckingStrategy(abstractConstructorCheck); + } } else { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); @@ -384,6 +400,7 @@ public class CallResolver { if (dirty.getValue()) { dirtyCandidates.add(candidate); } + task.performAdvancedChecks(candidate, temporaryTrace, tracing); } OverloadResolutionResult result = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates, dirtyCandidates, traces); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java b/idea/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java index 9ba8ed26da1..410f7f00080 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java @@ -7,8 +7,10 @@ import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetTypeProjection; import org.jetbrains.jet.lang.psi.ValueArgument; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.types.JetType; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -21,6 +23,7 @@ import java.util.List; private final List typeArguments; private final List valueArguments; private final List functionLiteralArguments; + private DescriptorCheckStrategy checkingStrategy; public ResolutionTask( @NotNull Collection candidates, @@ -67,5 +70,19 @@ import java.util.List; public List getFunctionLiteralArguments() { return functionLiteralArguments; } + + public void setCheckingStrategy(DescriptorCheckStrategy strategy) { + checkingStrategy = strategy; + } + public boolean performAdvancedChecks(Descriptor descriptor, BindingTrace trace, TracingStrategy tracing) { + if (checkingStrategy != null && !checkingStrategy.performAdvancedChecks(descriptor, trace, tracing)) { + return false; + } + return true; + } + + public interface DescriptorCheckStrategy { + boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java index c13ba2a44fa..1900c6af2c5 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java @@ -20,9 +20,10 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements private JavaClassMembersScope unsubstitutedMemberScope; private JetType classObjectType; private final WritableFunctionGroup constructors = new WritableFunctionGroup(""); - private boolean isAbstract; - private boolean isOpen; - private boolean isTrait; + private ClassModifiers modifiers; +// private boolean isAbstract; +// private boolean isOpen; +// private boolean isTrait; public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) { super(containingDeclaration); @@ -33,9 +34,10 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements } public void setModifiers(boolean isAbstract, boolean isOpen, boolean isTrait) { - this.isAbstract = isAbstract; - this.isOpen = isOpen; - this.isTrait = isTrait; + this.modifiers = new ClassModifiers(isAbstract, isOpen, isTrait); +// this.isAbstract = isAbstract; +// this.isOpen = isOpen; +// this.isTrait = isTrait; } public void setUnsubstitutedMemberScope(JavaClassMembersScope memberScope) { @@ -129,19 +131,25 @@ 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 - public boolean isAbstract() { - return isAbstract; - } - - @Override - public boolean isOpen() { - return isOpen; - } - - @Override - public boolean isTrait() { - return isTrait; + @NotNull + public ClassModifiers getClassModifiers() { + return modifiers; } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 093c93f7a74..fd320d03adc 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -125,7 +125,7 @@ public class JavaDescriptorResolver { classDescriptor, Collections.emptyList(), false); - constructorDescriptor.initialize(typeParameters, Collections.emptyList()); + constructorDescriptor.initialize(typeParameters, Collections.emptyList(), MemberModifiers.DEFAULT_MODIFIERS); constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); classDescriptor.addConstructor(constructorDescriptor); semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor); @@ -137,7 +137,7 @@ public class JavaDescriptorResolver { classDescriptor, Collections.emptyList(), // TODO false); - constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters())); + constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), MemberModifiers.DEFAULT_MODIFIERS); constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); classDescriptor.addConstructor(constructorDescriptor); semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, constructor, constructorDescriptor); @@ -348,7 +348,8 @@ public class JavaDescriptorResolver { null, resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()), semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters), - semanticServices.getTypeTransformer().transformToType(returnType) + semanticServices.getTypeTransformer().transformToType(returnType), + MemberModifiers.DEFAULT_MODIFIERS //TODO ); semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index d4d780c7231..6ec2c4f5440 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -123,7 +123,8 @@ public class ErrorUtils { null, typeParameters, getValueParameters(functionDescriptor, positionedValueArgumentTypes), - createErrorType("") + createErrorType(""), + MemberModifiers.DEFAULT_MODIFIERS ); } @@ -132,7 +133,8 @@ public class ErrorUtils { null, Collections.emptyList(), // TODO Collections.emptyList(), // TODO - createErrorType("") + createErrorType(""), + MemberModifiers.DEFAULT_MODIFIERS ); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 2d474001963..b8755a8cf80 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -932,7 +932,7 @@ public class JetTypeInferrer { else { effectiveReceiverType = receiverType; } - functionDescriptor.initialize(effectiveReceiverType, Collections.emptyList(), valueParameterDescriptors, null); + functionDescriptor.initialize(effectiveReceiverType, Collections.emptyList(), valueParameterDescriptors, null, MemberModifiers.DEFAULT_MODIFIERS); context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor); JetType returnType = NO_EXPECTED_TYPE; diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index d76ae4e600b..33f00dd4a3e 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -251,7 +251,7 @@ public class DescriptorRenderer { @Override public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { - String keyword = descriptor.isTrait() ? "trait class" : "class"; + String keyword = descriptor.getClassModifiers().isTrait() ? "trait class" : "class"; renderClassDescriptor(descriptor, builder, keyword); return super.visitClassDescriptor(descriptor, builder); } diff --git a/idea/testData/checker/Abstract.jet b/idea/testData/checker/Abstract.jet index b1083b6934f..238c0e32c09 100644 --- a/idea/testData/checker/Abstract.jet +++ b/idea/testData/checker/Abstract.jet @@ -47,4 +47,22 @@ abstract class A10 { abstract val i: Int abstract fun foo(): fun(Int): Int val j: Int -fun foo1(): fun(Int): Int \ No newline at end of file +fun foo1(): fun(Int): Int + +//creating an instance +abstract class B1( + val i: Int, + val s: String +) { +} + +class B2() : B1(1, "r") {} + +abstract class B3(i: Int) { + this(): this(1) +} + +fun foo(a: B3) { + val a = B3() + val b = B1(2, "s") +} diff --git a/idea/testData/checker/BinaryCallsOnNullableValues.jet b/idea/testData/checker/BinaryCallsOnNullableValues.jet index 2d35b7ae20c..285605c2a42 100644 --- a/idea/testData/checker/BinaryCallsOnNullableValues.jet +++ b/idea/testData/checker/BinaryCallsOnNullableValues.jet @@ -1,13 +1,13 @@ -abstract class A() { - abstract fun equals(a : Any?) : Boolean +class A() { + fun equals(a : Any?) : Boolean = false } -abstract class B() { - abstract fun equals(a : Any?) : Boolean? +class B() { + fun equals(a : Any?) : Boolean? = false } -abstract class C() { - abstract fun equals(a : Any?) : Int +class C() { + fun equals(a : Any?) : Int = 0 } fun f(): Unit { diff --git a/idea/testData/checker/ExtensionFunctions.jet b/idea/testData/checker/ExtensionFunctions.jet index 20759476be3..0464054f743 100644 --- a/idea/testData/checker/ExtensionFunctions.jet +++ b/idea/testData/checker/ExtensionFunctions.jet @@ -40,9 +40,9 @@ fun Int.foo() = this namespace null_safety { fun parse(cmd: String): Command? { return null } - abstract class Command() { + class Command() { // fun equals(other : Any?) : Boolean - abstract val foo : Int + val foo : Int = 0 } fun Any.equals(other : Any?) : Boolean = true diff --git a/idea/testData/checker/ForRangeConventions.jet b/idea/testData/checker/ForRangeConventions.jet index 6cbd3e3a0b4..da56cf2232e 100644 --- a/idea/testData/checker/ForRangeConventions.jet +++ b/idea/testData/checker/ForRangeConventions.jet @@ -65,16 +65,16 @@ abstract class Range1() { abstract fun iterator() : Iterator } -fun test() { - for (i in NotRange1()); - for (i in NotRange2()); - for (i in NotRange3()); - for (i in NotRange4()); - for (i in NotRange5()); - for (i in NotRange6()); - for (i in NotRange7()); - for (i in Range0()); - for (i in Range1()); +fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, range0: Range0, range1: Range1) { + for (i in notRange1); + for (i in notRange2); + for (i in notRange3); + for (i in notRange4); + for (i in notRange5); + for (i in notRange6); + for (i in notRange7); + for (i in range0); + for (i in range1); for (i in (ArrayList() : List)); }