diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java index a0d3413d0ec..85e90747a9a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java @@ -27,8 +27,8 @@ public abstract class DiagnosticFactoryWithPsiElement1 } @NotNull - public DiagnosticWithPsiElement on(@NotNull T element, @NotNull A argument) { - return on(element, element.getTextRange(), argument); + public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A argument) { + return on(elementToMark, elementToMark.getTextRange(), argument); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java index ce1a0bb29c2..ccc2b4b10d0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java @@ -31,8 +31,8 @@ public abstract class DiagnosticFactoryWithPsiElement2 on(@NotNull T element, @NotNull A a, @NotNull B b) { - return on(element, element.getNode(), a, b); + public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A a, @NotNull B b) { + return on(elementToMark, elementToMark.getNode(), a, b); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java index 7f5499d2a00..a4801044fbf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java @@ -34,8 +34,8 @@ public abstract class DiagnosticFactoryWithPsiElement3 on(@NotNull T element, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(element, element, a, b, c); + public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A a, @NotNull B b, @NotNull C c) { + return on(elementToMark, elementToMark, a, b, c); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticParameters.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticParameters.java index edbb89e2dc7..4712b76625b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticParameters.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticParameters.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.diagnostics; import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetKeywordToken; @@ -11,4 +12,5 @@ public interface DiagnosticParameters { DiagnosticParameter MODIFIER = new DiagnosticParameterImpl("MODIFIER"); DiagnosticParameter CLASS = new DiagnosticParameterImpl("CLASS"); DiagnosticParameter TYPE = new DiagnosticParameterImpl("TYPE"); + DiagnosticParameter PROPERTY = new DiagnosticParameterImpl("TYPE"); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 3ac77dc4ebb..d5abd98d3af 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -59,6 +59,7 @@ public interface Errors { return sb.toString(); } }; + ParameterizedDiagnosticFactory1 ILLEGAL_MODIFIER = ParameterizedDiagnosticFactory1.create(ERROR, "Illegal modifier ''{0}''"); PsiElementOnlyDiagnosticFactory2 REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2(Severity.WARNING, "Modifier {0} is redundant because {1} is present") { @NotNull @@ -67,6 +68,8 @@ public interface Errors { return super.on(elementToBlame, nodeToMark, redundantModifier, presentModifier).add(DiagnosticParameters.MODIFIER, redundantModifier); } }; + DiagnosticWithParameterFactory REDUNDANT_MODIFIER_IN_TRAIT = DiagnosticWithParameterFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", DiagnosticParameters.MODIFIER); + SimplePsiElementOnlyDiagnosticFactory TRAIT_CAN_NOT_BE_FINAL = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Trait can not be final"); SimpleDiagnosticFactory SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES = SimpleDiagnosticFactory.create(ERROR, "Safe calls are not allowed on namespaces"); SimpleDiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = SimpleDiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem"); // TODO: message SimpleDiagnosticFactory RETURN_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "'return' is not allowed here"); @@ -116,6 +119,9 @@ public interface Errors { SimplePsiElementOnlyDiagnosticFactory NON_MEMBER_ABSTRACT_ACCESSOR = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property is not a class or trait member and thus cannot have abstract accessors"); // TODO : Better message PsiElementOnlyDiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body"); + + DiagnosticWithParameterFactory NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticWithParameterFactory.create(ERROR, "Non final member in a final class", DiagnosticParameters.CLASS); + DiagnosticWithParameterFactory NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY = DiagnosticWithParameterFactory.create(ERROR, "Non final accessor of a final property", DiagnosticParameters.PROPERTY); SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java index 90729dfdb17..e22b08002c0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java @@ -27,12 +27,12 @@ public class ParameterizedDiagnosticFactory1 extends DiagnosticFactoryWithPsi } @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange range, @NotNull A argument) { - return new GenericDiagnostic(this, severity, makeMessage(argument), psiFile, range); + public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A argument) { + return new GenericDiagnostic(this, severity, makeMessage(argument), psiFile, rangeToMark); } @NotNull - public Diagnostic on(@NotNull ASTNode node, @NotNull A argument) { - return on(DiagnosticUtils.getContainingFile(node), node.getTextRange(), argument); + public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A argument) { + return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), argument); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java index d76bc5b47e1..c25fcc78f86 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java @@ -27,13 +27,13 @@ public class ParameterizedDiagnosticFactory2 extends DiagnosticFactoryWith } @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange range, @NotNull A a, @NotNull B b) { - return new GenericDiagnostic(this, severity, makeMessage(a, b), psiFile, range); + public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A a, @NotNull B b) { + return new GenericDiagnostic(this, severity, makeMessage(a, b), psiFile, rangeToMark); } @NotNull - public Diagnostic on(@NotNull ASTNode node, @NotNull A a, @NotNull B b) { - return on(DiagnosticUtils.getContainingFile(node), node.getTextRange(), a, b); + public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b) { + return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), a, b); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java index ad574334bea..aefdcb8c876 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java @@ -27,12 +27,12 @@ public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryW } @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange range, @NotNull A a, @NotNull B b, @NotNull C c) { - return new GenericDiagnostic(this, severity, makeMessage(a, b, c), psiFile, range); + public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { + return new GenericDiagnostic(this, severity, makeMessage(a, b, c), psiFile, rangeToMark); } @NotNull - public Diagnostic on(@NotNull ASTNode node, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(DiagnosticUtils.getContainingFile(node), node.getTextRange(), a, b, c); + public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { + return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), a, b, c); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 37dad7b2ce4..cd98216b91b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -3,10 +3,8 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; @@ -18,14 +16,17 @@ import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; /** -* @author abreslav -*/ + * @author abreslav + */ public class BodyResolver { private final TopDownAnalysisContext context; @@ -43,7 +44,6 @@ public class BodyResolver { JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression; if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { if (!BodyResolver.this.context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) descriptor)) { -// BodyResolver.this.context.getTrace().getErrorHandler().genericError(expression.getNode(), "This property does not have a backing field"); BodyResolver.this.context.getTrace().report(NO_BACKING_FIELD.on(expression)); } } @@ -68,7 +68,6 @@ public class BodyResolver { public void resolveBehaviorDeclarationBodies() { -// bindOverrides(); resolveDelegationSpecifierLists(); resolveClassAnnotations(); @@ -79,30 +78,9 @@ public class BodyResolver { resolveSecondaryConstructorBodies(); resolveFunctionBodies(); - checkIfPrimaryConstructorIsNecessary(); -// checkOverrides(); } - private void checkIfPrimaryConstructorIsNecessary() { - for (Map.Entry entry : context.getClasses().entrySet()) { - MutableClassDescriptor classDescriptor = entry.getValue(); - JetClass jetClass = entry.getKey(); - if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null && !(classDescriptor.getKind() == ClassKind.TRAIT)) { - for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { - if (context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { - PsiElement nameIdentifier = jetClass.getNameIdentifier(); - if (nameIdentifier != null) { -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), -// "This class must have a primary constructor, because property " + propertyDescriptor.getName() + " has a backing field"); - context.getTrace().report(PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY.on(jetClass, nameIdentifier, propertyDescriptor)); - } - break; - } - } - } - } - } private void resolveDelegationSpecifierLists() { // TODO : Make sure the same thing is not initialized twice @@ -117,8 +95,8 @@ public class BodyResolver { private void resolveDelegationSpecifierList(final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) { final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor(); final JetScope scopeForConstructor = primaryConstructor == null - ? null - : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true); + ? null + : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true); final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow final Map supertypes = Maps.newLinkedHashMap(); @@ -131,7 +109,6 @@ public class BodyResolver { @Override public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { if (descriptor.getKind() == ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericError(specifier.getNode(), "Traits cannot use delegation"); context.getTrace().report(DELEGATION_IN_TRAIT.on(specifier)); } JetType supertype = context.getTrace().getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference()); @@ -162,7 +139,6 @@ public class BodyResolver { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); if (descriptor.getKind() == ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericError(node, "Traits cannot initialize supertypes"); context.getTrace().report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(node)); } JetTypeReference typeReference = call.getTypeReference(); @@ -174,7 +150,6 @@ public class BodyResolver { ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (classDescriptor.getKind() == ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericError(node, "A trait may not have a constructor"); context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(node)); } } @@ -188,8 +163,6 @@ public class BodyResolver { recordSupertype(typeReference, supertype); assert valueArgumentList != null; -// context.getTrace().getErrorHandler().genericError(valueArgumentList.getNode(), -// "Class " + JetPsiUtil.safeName(jetClass.getName()) + " must have a constructor in order to be able to initialize supertypes"); context.getTrace().report(PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL.on(valueArgumentList, jetClass)); } } @@ -205,7 +178,6 @@ public class BodyResolver { if (classDescriptor != null) { if (descriptor.getKind() != ClassKind.TRAIT) { if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && classDescriptor.getKind() != ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericError(specifier.getNode(), "This type has a constructor, and thus must be initialized here"); context.getTrace().report(SUPERTYPE_NOT_INITIALIZED.on(specifier)); } } @@ -249,7 +221,6 @@ public class BodyResolver { if (classDescriptor != null) { if (classDescriptor.getKind() != ClassKind.TRAIT) { if (classAppeared) { -// context.getTrace().getErrorHandler().genericError(typeReference.getNode(), "Only one class may appear in a supertype list"); context.getTrace().report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference)); } else { @@ -258,18 +229,15 @@ public class BodyResolver { } } else { -// context.getTrace().getErrorHandler().genericError(typeReference.getNode(), "Only classes and traits may serve as supertypes"); context.getTrace().report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference)); } TypeConstructor constructor = supertype.getConstructor(); if (!typeConstructors.add(constructor)) { -// context.getTrace().getErrorHandler().genericError(typeReference.getNode(), "A supertype appears twice"); context.getTrace().report(SUPERTYPE_APPEARS_TWICE.on(typeReference)); } if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) { -// context.getTrace().getErrorHandler().genericError(typeReference.getNode(), "This type is final, so it cannot be inherited from"); context.getTrace().report(FINAL_SUPERTYPE.on(typeReference)); } } @@ -301,7 +269,6 @@ public class BodyResolver { } else { for (JetClassInitializer anonymousInitializer : anonymousInitializers) { -// context.getTrace().getErrorHandler().genericError(anonymousInitializer.getNode(), "Anonymous initializers are only allowed in the presence of a primary constructor"); context.getTrace().report(ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR.on(anonymousInitializer)); } } @@ -326,13 +293,11 @@ public class BodyResolver { JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class); assert containingClass != null : "This must be guaranteed by the parser"; if (!containingClass.hasPrimaryConstructor()) { -// context.getTrace().getErrorHandler().genericError(declaration.getNameNode(), "A secondary constructor may appear only in a class that has a primary constructor"); context.getTrace().report(SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY.on(declaration.getNameNode())); } else { List initializers = declaration.getInitializers(); if (initializers.isEmpty()) { -// context.getTrace().getErrorHandler().genericError(declaration.getNameNode(), "Secondary constructors must have an initializer list"); context.getTrace().report(SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST.on(declaration.getNameNode())); } else { @@ -352,8 +317,8 @@ public class BodyResolver { ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), - functionInnerScope, - ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); + functionInnerScope, + ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), @@ -363,13 +328,11 @@ public class BodyResolver { @Override public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { -// context.getTrace().getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors"); context.getTrace().report(BY_IN_SECONDARY_CONSTRUCTOR.on(specifier)); } @Override public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { -// context.getTrace().getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required"); context.getTrace().report(INITIALIZER_WITH_NO_ARGUMENTS.on(specifier)); } @@ -380,7 +343,6 @@ public class BodyResolver { }); for (int i = 1, initializersSize = initializers.size(); i < initializersSize; i++) { JetDelegationSpecifier initializer = initializers.get(i); -// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Only one call to 'this(...)' is allowed"); context.getTrace().report(MANY_CALLS_TO_THIS.on(initializer)); } } @@ -440,7 +402,6 @@ public class BodyResolver { } resolvePropertyAccessors(property, propertyDescriptor, declaringScope); - checkProperty(property, propertyDescriptor, classDescriptor); processed.add(property); } } @@ -459,7 +420,6 @@ public class BodyResolver { } resolvePropertyAccessors(property, propertyDescriptor, declaringScope); - checkProperty(property, propertyDescriptor, null); } } @@ -494,109 +454,6 @@ public class BodyResolver { } } - protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) { - checkPropertyAbstractness(property, propertyDescriptor, classDescriptor); - checkPropertyInitializer(property, propertyDescriptor, classDescriptor); - } - - private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) { - JetPropertyAccessor getter = property.getGetter(); - JetPropertyAccessor setter = property.getSetter(); - JetModifierList modifierList = property.getModifierList(); - ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; - - if (abstractNode != null) { //has abstract modifier - if (classDescriptor == null) { -// context.getTrace().getErrorHandler().genericError(abstractNode, "A property may be abstract only when defined in a class or trait"); - context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(property, abstractNode)); - return; - } - if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) { -// context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName()); - PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); - assert classElement instanceof JetClass; - context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, property.getName(), classDescriptor, (JetClass) classElement)); - return; - } - if (classDescriptor.getKind() == ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in traits"); - context.getTrace().report(REDUNDANT_ABSTRACT.on(property, abstractNode)); - } - } - - if (propertyDescriptor.getModality() == Modality.ABSTRACT) { - JetType returnType = propertyDescriptor.getReturnType(); - if (returnType instanceof DeferredType) { - returnType = ((DeferredType) returnType).getActualType(); - } - - JetExpression initializer = property.getInitializer(); - if (initializer != null) { -// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property with initializer cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(property, initializer, returnType)); - } - if (getter != null && getter.getBodyExpression() != null) { -// context.getTrace().getErrorHandler().genericError(getter.getNode(), "Property with getter implementation cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(property, getter, returnType)); - } - if (setter != null && setter.getBodyExpression() != null) { -// context.getTrace().getErrorHandler().genericError(setter.getNode(), "Property with setter implementation cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(property, setter, returnType)); - } - } - } - - private void checkPropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) { - JetPropertyAccessor getter = property.getGetter(); - JetPropertyAccessor setter = property.getSetter(); - boolean hasAccessorImplementation = (getter != null && getter.getBodyExpression() != null) || - (setter != null && setter.getBodyExpression() != null); - if (propertyDescriptor.getModality() == Modality.ABSTRACT) return; - - boolean inTrait = classDescriptor != null && classDescriptor.getKind() == ClassKind.TRAIT; - JetExpression initializer = property.getInitializer(); - boolean backingFieldRequired = context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); - - PsiElement nameIdentifier = property.getNameIdentifier(); - ASTNode nameNode = nameIdentifier == null ? property.getNode() : nameIdentifier.getNode(); - - if (inTrait && backingFieldRequired && hasAccessorImplementation) { -// context.getTrace().getErrorHandler().genericError(nameNode, "Property in a trait cannot have a backing field"); - context.getTrace().report(BACKING_FIELD_IN_TRAIT.on(nameNode)); - } - if (initializer == null) { - if (backingFieldRequired && !inTrait && !context.getTrace().getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) { - if (classDescriptor == null || hasAccessorImplementation) { -// context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized"); - context.getTrace().report(MUST_BE_INITIALIZED.on(nameNode)); - } else { -// context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract"); - context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property, nameNode)); - } - } - return; - } - if (inTrait) { -// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed in traits"); - JetType returnType = propertyDescriptor.getReturnType(); - if (returnType instanceof DeferredType) { - returnType = ((DeferredType) returnType).getActualType(); - } - context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(property, initializer, returnType)); - } - else if (!backingFieldRequired) { -// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no backing field"); - context.getTrace().report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); - } - else if (classDescriptor != null && classDescriptor.getUnsubstitutedPrimaryConstructor() == null) { -// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed when no primary constructor is present"); - PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); - assert classElement instanceof JetClass; - - context.getTrace().report(PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR.on(property, initializer, (JetClass) classElement)); - } - } - private BindingTraceAdapter createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) { return new BindingTraceAdapter(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler() { @Override @@ -647,13 +504,13 @@ public class BodyResolver { private void resolveFunctionBodies() { for (Map.Entry entry : this.context.getFunctions().entrySet()) { - JetDeclaration declaration = entry.getKey(); + JetNamedFunction declaration = entry.getKey(); FunctionDescriptor descriptor = entry.getValue(); JetScope declaringScope = this.context.getDeclaringScopes().get(declaration); assert declaringScope != null; - resolveFunctionBody(traceForMembers, (JetNamedFunction) declaration, descriptor, declaringScope); + resolveFunctionBody(traceForMembers, declaration, descriptor, declaringScope); assert descriptor.getReturnType() != null; } @@ -673,60 +530,6 @@ public class BodyResolver { typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor); } - checkFunction(function, functionDescriptor); assert functionDescriptor.getReturnType() != null; } - - protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { - DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); - PsiElement nameIdentifier; - boolean isPropertyAccessor = false; - if (function instanceof JetNamedFunction) { - nameIdentifier = ((JetNamedFunction) function).getNameIdentifier(); - } - else if (function instanceof JetPropertyAccessor) { - isPropertyAccessor = true; - nameIdentifier = ((JetPropertyAccessor) function).getNamePlaceholder(); - } - else { - throw new UnsupportedOperationException(); - } - JetFunctionOrPropertyAccessor functionOrPropertyAccessor = (JetFunctionOrPropertyAccessor) function; - JetModifierList modifierList = functionOrPropertyAccessor.getModifierList(); - ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; - boolean hasAbstractModifier = abstractNode != null; - if (containingDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; - boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT; - boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS; - boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT; - if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) { - PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); - assert classElement instanceof JetClass; - context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement)); - } - if (hasAbstractModifier && inTrait && !isPropertyAccessor) { - context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode)); - } - if (function.getBodyExpression() != null && hasAbstractModifier) { - context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); - } - if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) { - context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); - } - return; - } - if (hasAbstractModifier) { - if (!isPropertyAccessor) { - context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); - } - else { - context.getTrace().report(NON_MEMBER_ABSTRACT_ACCESSOR.on(functionOrPropertyAccessor, abstractNode)); - } - } - if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) { - context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); - } - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 4690faad394..0cd5ea93978 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -21,8 +21,6 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lexer.JetKeywordToken; -import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; @@ -67,8 +65,8 @@ public class ClassDescriptorResolver { } descriptor.setTypeParameterDescriptors(typeParameters); Modality defaultModality = descriptor.getKind() == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL; - descriptor.setModality(resolveModalityFromModifiers(trace, classElement.getModifierList(), defaultModality)); - descriptor.setVisibility(resolveVisibilityFromModifiers(trace, classElement.getModifierList())); + descriptor.setModality(resolveModalityFromModifiers(classElement.getModifierList(), defaultModality)); + descriptor.setVisibility(resolveVisibilityFromModifiers(classElement.getModifierList())); trace.record(BindingContext.CLASS, classElement, descriptor); } @@ -193,8 +191,8 @@ public class ClassDescriptorResolver { } boolean hasBody = function.getBodyExpression() != null; Modality defaultModality = getDefaultModality(containingDescriptor, hasBody); - Modality modality = resolveModalityFromModifiers(trace, function.getModifierList(), defaultModality); - Visibility visibility = resolveVisibilityFromModifiers(trace, function.getModifierList()); + Modality modality = resolveModalityFromModifiers(function.getModifierList(), defaultModality); + Visibility visibility = resolveVisibilityFromModifiers(function.getModifierList()); functionDescriptor.initialize( receiverType, typeParameterDescriptors, @@ -438,7 +436,7 @@ public class ClassDescriptorResolver { containingDeclaration, annotationResolver.createAnnotationStubs(modifierList), Modality.FINAL, - resolveVisibilityFromModifiers(trace, objectDeclaration.getModifierList()), + resolveVisibilityFromModifiers(objectDeclaration.getModifierList()), false, null, JetPsiUtil.safeName(objectDeclaration.getName()), @@ -499,8 +497,8 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModalityFromModifiers(trace, property.getModifierList(), defaultModality), - resolveVisibilityFromModifiers(trace, property.getModifierList()), + resolveModalityFromModifiers(property.getModifierList(), defaultModality), + resolveVisibilityFromModifiers(property.getModifierList()), isVar, receiverType, JetPsiUtil.safeName(property.getName()), @@ -552,17 +550,12 @@ public class ClassDescriptorResolver { } @NotNull - /*package*/ static Modality resolveModalityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, @NotNull Modality defaultModality) { + /*package*/ static Modality resolveModalityFromModifiers(@Nullable JetModifierList modifierList, @NotNull Modality defaultModality) { if (modifierList == null) return defaultModality; - checkCompatibility(trace, modifierList, Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD), - Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD)); boolean hasAbstractModifier = modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD); boolean hasOverrideModifier = modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD); if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) { - if (hasAbstractModifier || hasOverrideModifier) { - trace.report(Errors.REDUNDANT_MODIFIER.on(modifierList, JetTokens.OPEN_KEYWORD, hasAbstractModifier ? JetTokens.ABSTRACT_KEYWORD : JetTokens.OVERRIDE_KEYWORD)); - } if (hasAbstractModifier || defaultModality == Modality.ABSTRACT) { return Modality.ABSTRACT; } @@ -582,15 +575,13 @@ public class ClassDescriptorResolver { } @NotNull - /*package*/ static Visibility resolveVisibilityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList) { - return resolveVisibilityFromModifiers(trace, modifierList, Visibility.INTERNAL); + /*package*/ static Visibility resolveVisibilityFromModifiers(@Nullable JetModifierList modifierList) { + return resolveVisibilityFromModifiers(modifierList, Visibility.INTERNAL); } @NotNull - /*package*/ static Visibility resolveVisibilityFromModifiers(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, @NotNull Visibility defaultVisibility) { + /*package*/ static Visibility resolveVisibilityFromModifiers(@Nullable JetModifierList modifierList, @NotNull Visibility defaultVisibility) { if (modifierList == null) return defaultVisibility; - checkCompatibility(trace, modifierList, Lists.newArrayList(JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PUBLIC_KEYWORD, JetTokens.INTERNAL_KEYWORD), - Lists.newArrayList(JetTokens.PROTECTED_KEYWORD, JetTokens.INTERNAL_KEYWORD)); if (modifierList.hasModifier(JetTokens.PRIVATE_KEYWORD)) return Visibility.PRIVATE; if (modifierList.hasModifier(JetTokens.PUBLIC_KEYWORD)) return Visibility.PUBLIC; if (modifierList.hasModifier(JetTokens.PROTECTED_KEYWORD)) { @@ -601,29 +592,7 @@ public class ClassDescriptorResolver { } return defaultVisibility; } - - /*package*/ static boolean checkCompatibility(@NotNull BindingTrace trace, @Nullable JetModifierList modifierList, Collection availableModifiers, Collection... availableCombinations) { - if (modifierList == null) return true; - Collection presentModifiers = Sets.newLinkedHashSet(); - for (JetKeywordToken modifier : availableModifiers) { - if (modifierList.hasModifier(modifier)) { - presentModifiers.add(modifier); - } - } - if (presentModifiers.size() == 1) { - return true; - } - for (Collection combination : availableCombinations) { - if (presentModifiers.containsAll(combination) && combination.containsAll(presentModifiers)) { - return true; - } - } - for (JetKeywordToken token : presentModifiers) { - trace.report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token), presentModifiers)); - } - return false; - } - + @Nullable private PropertySetterDescriptor resolvePropertySetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { JetPropertyAccessor setter = property.getSetter(); @@ -633,8 +602,8 @@ public class ClassDescriptorResolver { JetParameter parameter = setter.getParameter(); setterDescriptor = new PropertySetterDescriptor( - resolveModalityFromModifiers(trace, setter.getModifierList(), propertyDescriptor.getModality()), - resolveVisibilityFromModifiers(trace, setter.getModifierList(), propertyDescriptor.getVisibility()), + resolveModalityFromModifiers(setter.getModifierList(), propertyDescriptor.getModality()), + resolveVisibilityFromModifiers(setter.getModifierList(), propertyDescriptor.getVisibility()), propertyDescriptor, annotations, setter.getBodyExpression() != null, false); if (parameter != null) { if (parameter.isRef()) { @@ -708,8 +677,8 @@ public class ClassDescriptorResolver { } getterDescriptor = new PropertyGetterDescriptor( - propertyDescriptor, annotations, resolveModalityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getModality()), - resolveVisibilityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getVisibility()), + propertyDescriptor, annotations, resolveModalityFromModifiers(getter.getModifierList(), propertyDescriptor.getModality()), + resolveVisibilityFromModifiers(getter.getModifierList(), propertyDescriptor.getVisibility()), returnType, getter.getBodyExpression() != null, false); trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); } @@ -748,7 +717,7 @@ public class ClassDescriptorResolver { new WritableScopeImpl(scope, classDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Scope with value parameters of a constructor"), valueParameters), Modality.FINAL, - resolveVisibilityFromModifiers(trace, modifierList)); + resolveVisibilityFromModifiers(modifierList)); } @Nullable @@ -784,8 +753,8 @@ public class ClassDescriptorResolver { PropertyDescriptor propertyDescriptor = new PropertyDescriptor( classDescriptor, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModalityFromModifiers(trace, parameter.getModifierList(), Modality.FINAL), - resolveVisibilityFromModifiers(trace, parameter.getModifierList()), + resolveModalityFromModifiers(parameter.getModifierList(), Modality.FINAL), + resolveVisibilityFromModifiers(parameter.getModifierList()), isMutable, null, name == null ? "" : name, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java new file mode 100644 index 00000000000..844c7d62671 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -0,0 +1,352 @@ +package org.jetbrains.jet.lang.resolve; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.diagnostics.Errors; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.DeferredType; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lexer.JetKeywordToken; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import static org.jetbrains.jet.lang.diagnostics.Errors.*; + +/** + * @author svtk + */ +public class DeclarationsChecker { + private TopDownAnalysisContext context; + + public DeclarationsChecker(TopDownAnalysisContext context) { + this.context = context; + } + + public void process() { + checkIfPrimaryConstructorIsNecessary(); + + Map classes = context.getClasses(); + for (Map.Entry entry : classes.entrySet()) { + JetClass aClass = entry.getKey(); + MutableClassDescriptor classDescriptor = entry.getValue(); + + checkClass(aClass, classDescriptor); + checkModifiers(aClass.getModifierList()); + } + + Map objects = context.getObjects(); + for (Map.Entry entry : objects.entrySet()) { + JetObjectDeclaration objectDeclaration = entry.getKey(); + MutableClassDescriptor objectDescriptor = entry.getValue(); + + checkObject(objectDeclaration, objectDescriptor); + } + + Map functions = context.getFunctions(); + for (Map.Entry entry : functions.entrySet()) { + JetNamedFunction function = entry.getKey(); + FunctionDescriptorImpl functionDescriptor = entry.getValue(); + + checkFunction(function, functionDescriptor); + checkModifiers(function.getModifierList()); + } + + Map properties = context.getProperties(); + for (Map.Entry entry : properties.entrySet()) { + JetProperty property = entry.getKey(); + PropertyDescriptor propertyDescriptor = entry.getValue(); + + checkProperty(property, propertyDescriptor); + checkModifiers(property.getModifierList()); + } + + } + + private void checkIfPrimaryConstructorIsNecessary() { + for (Map.Entry entry : context.getClasses().entrySet()) { + MutableClassDescriptor classDescriptor = entry.getValue(); + JetClass jetClass = entry.getKey(); + if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null && !(classDescriptor.getKind() == ClassKind.TRAIT)) { + for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { + if (context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { + PsiElement nameIdentifier = jetClass.getNameIdentifier(); + if (nameIdentifier != null) { + context.getTrace().report(PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY.on(jetClass, nameIdentifier, propertyDescriptor)); + } + break; + } + } + } + } + } + + private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) { + checkOpenMembers(aClass, classDescriptor); + checkTraitModifiers(aClass); + } + + private void checkTraitModifiers(JetClass aClass) { + if (!aClass.isTrait()) return; + JetModifierList modifierList = aClass.getModifierList(); + if (modifierList == null) return; + if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { + context.getTrace().report(Errors.TRAIT_CAN_NOT_BE_FINAL.on(aClass, modifierList.getModifierNode(JetTokens.FINAL_KEYWORD))); + } + ArrayList redundantModifiers = Lists.newArrayList(JetTokens.OPEN_KEYWORD, JetTokens.ABSTRACT_KEYWORD); + for (JetKeywordToken modifier : redundantModifiers) { + if (modifierList.hasModifier(modifier)) { + context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, modifierList.getModifierNode(modifier), modifier)); + } + } + } + + + private void checkObject(JetObjectDeclaration objectDeclaration, MutableClassDescriptor classDescriptor) { + checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD); + } + + private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) { + for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) { + + JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor); + if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) { + ASTNode openModifierNode = member.getModifierList().getModifierNode(JetTokens.OPEN_KEYWORD); + context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass)); + } + } + } + + protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { + DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); + ClassDescriptor classDescriptor = (containingDeclaration instanceof ClassDescriptor) + ? (ClassDescriptor) containingDeclaration + : null; + checkPropertyAbstractness(property, propertyDescriptor, classDescriptor); + checkPropertyInitializer(property, propertyDescriptor, classDescriptor); + checkAccessors(property, propertyDescriptor); + } + + private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) { + JetPropertyAccessor getter = property.getGetter(); + JetPropertyAccessor setter = property.getSetter(); + JetModifierList modifierList = property.getModifierList(); + ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; + + if (abstractNode != null) { //has abstract modifier + if (classDescriptor == null) { + context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(property, abstractNode)); + return; + } + if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) { + PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); + assert classElement instanceof JetClass; + context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, property.getName(), classDescriptor, (JetClass) classElement)); + return; + } + if (classDescriptor.getKind() == ClassKind.TRAIT) { + context.getTrace().report(REDUNDANT_ABSTRACT.on(property, abstractNode)); + } + } + + if (propertyDescriptor.getModality() == Modality.ABSTRACT) { + JetType returnType = propertyDescriptor.getReturnType(); + if (returnType instanceof DeferredType) { + returnType = ((DeferredType) returnType).getActualType(); + } + + JetExpression initializer = property.getInitializer(); + if (initializer != null) { + context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(property, initializer, returnType)); + } + if (getter != null && getter.getBodyExpression() != null) { + context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(property, getter, returnType)); + } + if (setter != null && setter.getBodyExpression() != null) { + context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(property, setter, returnType)); + } + } + } + + private void checkPropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) { + JetPropertyAccessor getter = property.getGetter(); + JetPropertyAccessor setter = property.getSetter(); + boolean hasAccessorImplementation = (getter != null && getter.getBodyExpression() != null) || + (setter != null && setter.getBodyExpression() != null); + if (propertyDescriptor.getModality() == Modality.ABSTRACT) return; + + boolean inTrait = classDescriptor != null && classDescriptor.getKind() == ClassKind.TRAIT; + JetExpression initializer = property.getInitializer(); + boolean backingFieldRequired = context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); + + PsiElement nameIdentifier = property.getNameIdentifier(); + ASTNode nameNode = nameIdentifier == null ? property.getNode() : nameIdentifier.getNode(); + + if (inTrait && backingFieldRequired && hasAccessorImplementation) { + context.getTrace().report(BACKING_FIELD_IN_TRAIT.on(nameNode)); + } + if (initializer == null) { + if (backingFieldRequired && !inTrait && !context.getTrace().getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) { + if (classDescriptor == null || hasAccessorImplementation) { + context.getTrace().report(MUST_BE_INITIALIZED.on(nameNode)); + } + else { + context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property, nameNode)); + } + } + return; + } + if (inTrait) { + JetType returnType = propertyDescriptor.getReturnType(); + if (returnType instanceof DeferredType) { + returnType = ((DeferredType) returnType).getActualType(); + } + context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(property, initializer, returnType)); + } + else if (!backingFieldRequired) { + context.getTrace().report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); + } + else if (classDescriptor != null && classDescriptor.getUnsubstitutedPrimaryConstructor() == null) { + PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); + assert classElement instanceof JetClass; + + context.getTrace().report(PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR.on(property, initializer, (JetClass) classElement)); + } + } + + protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { + DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); + PsiElement nameIdentifier; + boolean isPropertyAccessor = false; + if (function instanceof JetNamedFunction) { + nameIdentifier = ((JetNamedFunction) function).getNameIdentifier(); + } + else if (function instanceof JetPropertyAccessor) { + isPropertyAccessor = true; + nameIdentifier = ((JetPropertyAccessor) function).getNamePlaceholder(); + } + else { + throw new UnsupportedOperationException(); + } + JetFunctionOrPropertyAccessor functionOrPropertyAccessor = (JetFunctionOrPropertyAccessor) function; + JetModifierList modifierList = functionOrPropertyAccessor.getModifierList(); + ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; + boolean hasAbstractModifier = abstractNode != null; + if (containingDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; + boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT; + boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS; + boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT; + if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) { + PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); + assert classElement instanceof JetClass; + context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement)); + } + if (hasAbstractModifier && inTrait && !isPropertyAccessor) { + context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode)); + } + if (function.getBodyExpression() != null && hasAbstractModifier) { + context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); + } + if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) { + context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); + } + return; + } + if (hasAbstractModifier) { + if (!isPropertyAccessor) { + context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); + } + else { + context.getTrace().report(NON_MEMBER_ABSTRACT_ACCESSOR.on(functionOrPropertyAccessor, abstractNode)); + } + } + if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) { + context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); + } + } + + private void checkAccessors(JetProperty property, PropertyDescriptor propertyDescriptor) { + for (JetPropertyAccessor accessor : property.getAccessors()) { + PropertyAccessorDescriptor accessorDescriptor = accessor.isGetter() + ? propertyDescriptor.getGetter() + : propertyDescriptor.getSetter(); + checkFunction(accessor, accessorDescriptor); + if (propertyDescriptor.getModality() == Modality.FINAL && accessor.hasModifier(JetTokens.OPEN_KEYWORD)) { + ASTNode openModifierNode = accessor.getModifierList().getModifierNode(JetTokens.OPEN_KEYWORD); + context.getTrace().report(NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY.on(accessor, openModifierNode, property)); + } + } + } + + private void checkModifiers(@Nullable JetModifierList modifierList) { + checkModalityModifiers(modifierList); + checkVisibilityModifiers(modifierList); + } + + private void checkModalityModifiers(@Nullable JetModifierList modifierList) { + if (modifierList == null) return; + checkRedundantModifier(modifierList, Pair.create(JetTokens.OPEN_KEYWORD, JetTokens.ABSTRACT_KEYWORD), Pair.create(JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD)); + + checkCompatibility(modifierList, Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD), + Lists.newArrayList(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD)); + } + + private void checkVisibilityModifiers(@Nullable JetModifierList modifierList) { + if (modifierList == null) return; + + checkCompatibility(modifierList, Lists.newArrayList(JetTokens.PRIVATE_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PUBLIC_KEYWORD, JetTokens.INTERNAL_KEYWORD), + Lists.newArrayList(JetTokens.PROTECTED_KEYWORD, JetTokens.INTERNAL_KEYWORD)); + } + + private void checkCompatibility(@Nullable JetModifierList modifierList, Collection availableModifiers, Collection... availableCombinations) { + if (modifierList == null) return; + Collection presentModifiers = Sets.newLinkedHashSet(); + for (JetKeywordToken modifier : availableModifiers) { + if (modifierList.hasModifier(modifier)) { + presentModifiers.add(modifier); + } + } + if (presentModifiers.size() == 1) { + return; + } + for (Collection combination : availableCombinations) { + if (presentModifiers.containsAll(combination) && combination.containsAll(presentModifiers)) { + return; + } + } + for (JetKeywordToken token : presentModifiers) { + context.getTrace().report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token), presentModifiers)); + } + } + + private void checkRedundantModifier(@NotNull JetModifierList modifierList, Pair... redundantBundles) { + for (Pair tokenPair : redundantBundles) { + JetKeywordToken redundantModifier = tokenPair.getFirst(); + JetKeywordToken sufficientModifier = tokenPair.getSecond(); + if (modifierList.hasModifier(redundantModifier) && modifierList.hasModifier(sufficientModifier)) { + context.getTrace().report(Errors.REDUNDANT_MODIFIER.on(modifierList, modifierList.getModifierNode(redundantModifier), redundantModifier, sufficientModifier)); + } + } + } + + private void checkIllegalInThisContextModifiers(@Nullable JetModifierList modifierList, JetKeywordToken... illegalModifiers) { + if (modifierList == null) return; + for (JetKeywordToken modifier : illegalModifiers) { + if (modifierList.hasModifier(modifier)) { + context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList.getModifierNode(modifier), modifier)); + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 43d992ed5ce..b486dd556c2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -68,6 +68,7 @@ public class TopDownAnalyzer { new DelegationResolver(context).process(); new OverrideResolver(context).process(); new BodyResolver(context).resolveBehaviorDeclarationBodies(); + new DeclarationsChecker(context).process(); } public static void processStandardLibraryNamespace( @@ -86,16 +87,7 @@ public class TopDownAnalyzer { } }; overrideResolver.process(); - BodyResolver bodyResolver = new BodyResolver(context) { - @Override - protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) { - } - - @Override - protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { - } - }; - bodyResolver.resolveBehaviorDeclarationBodies(); + new BodyResolver(context).resolveBehaviorDeclarationBodies(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index fbf91dd2808..9d860516b34 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -98,7 +98,7 @@ public class TypeHierarchyResolver { MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(context.getTrace(), mutableClassDescriptor, outerScope, ClassKind.OBJECT); classObjectDescriptor.setName("class-object-for-" + klass.getName()); classObjectDescriptor.setModality(Modality.FINAL); - classObjectDescriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(context.getTrace(), klass.getModifierList())); + classObjectDescriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(klass.getModifierList())); classObjectDescriptor.createTypeConstructor(); createPrimaryConstructorForObject(null, classObjectDescriptor); mutableClassDescriptor.setClassObjectDescriptor(classObjectDescriptor); @@ -274,7 +274,7 @@ public class TypeHierarchyResolver { JetObjectDeclaration objectDeclaration = entry.getKey(); MutableClassDescriptor descriptor = entry.getValue(); descriptor.setModality(Modality.FINAL); - descriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(context.getTrace(), objectDeclaration.getModifierList())); + descriptor.setVisibility(ClassDescriptorResolver.resolveVisibilityFromModifiers(objectDeclaration.getModifierList())); descriptor.createTypeConstructor(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java index c22862070c7..3a647100c87 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java @@ -19,27 +19,16 @@ import org.jetbrains.jet.lexer.JetTokens; */ public class AddModifierFix extends ModifierFix { private final JetToken[] modifiersThanCanBeReplaced; - private final JetToken[] conflictedModifiers; - private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced, JetToken[] conflictedModifiers) { + private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced) { super(element, modifier); this.modifiersThanCanBeReplaced = modifiersThanCanBeReplaced; - this.conflictedModifiers = conflictedModifiers; - } - - private static boolean checkConflictModifiers(JetModifierListOwner element, JetToken[] conflictedModifiers) { - for (JetToken conflictedModifier : conflictedModifiers) { - if (element.hasModifier(conflictedModifier)) { - return true; - } - } - return false; } @NotNull @Override public String getText() { - if (modifier == JetTokens.ABSTRACT_KEYWORD) { + if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) { return "Make " + getElementName() + " " + modifier.getValue(); } return "Add '" + modifier.getValue() + "' modifier"; @@ -53,7 +42,7 @@ public class AddModifierFix extends ModifierFix { @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return element.isValid() && !checkConflictModifiers(element, conflictedModifiers); + return element.isValid(); } @Override @@ -97,17 +86,17 @@ public class AddModifierFix extends ModifierFix { return true; } - public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced, final JetToken[] conflictedModifiers) { + public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) { return new JetIntentionActionFactory() { @Override public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced, conflictedModifiers); + return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced); } }; } public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier) { - return createFactory(modifier, new JetToken[0], new JetToken[0]); + return createFactory(modifier, new JetToken[0]); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 07c3da654ab..dc1bd99e2cc 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -30,7 +30,7 @@ public class QuickFixes { static { JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD); - JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD}, new JetToken[] {JetTokens.FINAL_KEYWORD}); + JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD}); add(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory); add(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory); @@ -84,14 +84,24 @@ public class QuickFixes { add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory()); - - add(Errors.REDUNDANT_MODIFIER, RemoveRedundantModifierFix.createFactory()); + + JetIntentionActionFactory removeRedundantModifierFactory = RemoveRedundantModifierFix.createFactory(); + add(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory); + add(Errors.REDUNDANT_MODIFIER_IN_TRAIT, removeRedundantModifierFactory); + add(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createFactory(JetTokens.FINAL_KEYWORD)); add(Errors.PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR, RemovePartsFromPropertyFix.createRemoveInitializerFactory()); JetIntentionActionFactory addPrimaryConstructorFactory = AddPrimaryConstructorFix.createFactory(); add(Errors.PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addPrimaryConstructorFactory, DiagnosticParameters.CLASS)); add(Errors.PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY, addPrimaryConstructorFactory); + + JetIntentionActionFactory addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD}); + JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createFactory(JetTokens.OPEN_KEYWORD); + add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, DiagnosticParameters.CLASS)); + add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory); + add(Errors.NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, DiagnosticParameters.PROPERTY)); + add(Errors.NON_FINAL_ACCESSOR_OF_FINAL_PROPERTY, removeOpenModifierFactory); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index 5c6379f384d..b4e7afe9ce8 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -29,7 +29,7 @@ public class RemoveModifierFix extends ModifierFix { @NotNull @Override public String getText() { - if (modifier == JetTokens.ABSTRACT_KEYWORD) { + if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) { return "Make " + getElementName() + " not " + modifier.getValue(); } return "Remove '" + modifier.getValue() + "' modifier"; diff --git a/idea/testData/checker/CyclicHierarchy.jet b/idea/testData/checker/CyclicHierarchy.jet index 431db452077..f63abefd2be 100644 --- a/idea/testData/checker/CyclicHierarchy.jet +++ b/idea/testData/checker/CyclicHierarchy.jet @@ -1,13 +1,13 @@ -open trait A { +trait A { fun foo() {} } -open trait B : A, E {} -open trait C : B {} -open trait D : B {} -open trait E : F {} -open trait F : D, C {} -open trait G : F {} -open trait H : F {} +trait B : A, E {} +trait C : B {} +trait D : B {} +trait E : F {} +trait F : D, C {} +trait G : F {} +trait H : F {} val a : A? = null val b : B? = null diff --git a/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet b/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet index ff99017a12b..e0857d24e0f 100644 --- a/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet +++ b/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet @@ -1,13 +1,13 @@ -open trait A { +trait A { fun foo() {} } -open trait B : A, E {} -open trait C : B {} -open trait D : B {} -open trait E : F {} -open trait F : D, C {} -open trait G : F {} -open trait H : F {} +trait B : A, E {} +trait C : B {} +trait D : B {} +trait E : F {} +trait F : D, C {} +trait G : F {} +trait H : F {} val a : A? = null val b : B? = null diff --git a/idea/testData/checkerWithErrorTypes/full/IncompatibleModifiers.jet b/idea/testData/checkerWithErrorTypes/full/IncompatibleModifiers.jet new file mode 100644 index 00000000000..a7b3f5a6e88 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/IncompatibleModifiers.jet @@ -0,0 +1,7 @@ +namespace a + +abstract class A() { + abstract final fun f() + abstract open fun g() + final open fun h() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeHasFinal.kt b/idea/testData/quickfix/abstract/beforeHasFinal.kt deleted file mode 100644 index 6140b0d1c56..00000000000 --- a/idea/testData/quickfix/abstract/beforeHasFinal.kt +++ /dev/null @@ -1,4 +0,0 @@ -// "Make 'foo' abstract" "false" -class B() { - final fun foo() -} diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt index 38c63050707..181b7b6aadc 100644 --- a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier2.kt @@ -4,5 +4,5 @@ abstract class B() { } abstract class A() : B() { - abstract override fun foo() + abstract override fun foo() } diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt index 38c63050707..2f6b03af29c 100644 --- a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt @@ -4,5 +4,5 @@ abstract class B() { } abstract class A() : B() { - abstract override fun foo() + abstract override fun foo() } diff --git a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt index 4d4d6440fb0..0e158cee4dc 100644 --- a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt +++ b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier2.kt @@ -4,5 +4,5 @@ abstract class B() { } abstract class A() : B() { - abstract open override fun foo() + abstract open override fun foo() } diff --git a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt index 53a92e31819..7db5121da51 100644 --- a/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt +++ b/idea/testData/quickfix/modifiers/beforeRemoveRedundantModifier3.kt @@ -4,5 +4,5 @@ abstract class B() { } abstract class A() : B() { - abstract override open fun foo() + abstract override open fun foo() }