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 7cff43d00f5..826c5cd9813 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -59,7 +59,7 @@ public interface Errors { return sb.toString(); } }; - ParameterizedDiagnosticFactory1 ILLEGAL_MODIFIER = ParameterizedDiagnosticFactory1.create(ERROR, "Illegal modifier ''{0}''"); + DiagnosticWithParameterFactory ILLEGAL_MODIFIER = DiagnosticWithParameterFactory.create(ERROR, "Illegal modifier ''{0}''", DiagnosticParameters.MODIFIER); PsiElementOnlyDiagnosticFactory2 REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2(Severity.WARNING, "Modifier {0} is redundant because {1} is present") { @NotNull @@ -69,6 +69,7 @@ public interface Errors { } }; DiagnosticWithParameterFactory REDUNDANT_MODIFIER_IN_TRAIT = DiagnosticWithParameterFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", DiagnosticParameters.MODIFIER); + DiagnosticWithParameterFactory REDUNDANT_MODIFIER_IN_GETTER = DiagnosticWithParameterFactory.create(WARNING, "Visibility modifiers are redundant in getter", 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 @@ -94,6 +95,8 @@ public interface Errors { DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithParameterFactory.create(ERROR, "Property with initializer cannot be abstract", DiagnosticParameters.TYPE); DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with getter implementation cannot be abstract", DiagnosticParameters.TYPE); DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with setter implementation cannot be abstract", DiagnosticParameters.TYPE); + + DiagnosticWithParameterFactory GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY = DiagnosticWithParameterFactory.create(ERROR, "Getter visibility must be the same as property visibility", DiagnosticParameters.MODIFIER); SimpleDiagnosticFactory BACKING_FIELD_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property in a trait cannot have a backing field"); SimpleDiagnosticFactory MUST_BE_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "Property must be initialized"); SimplePsiElementOnlyDiagnosticFactory MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract"); @@ -106,22 +109,19 @@ public interface Errors { return super.on(elementToBlame, textRangeToMark, s, classDescriptor, aClass).add(DiagnosticParameters.CLASS, aClass); } }; - PsiElementOnlyDiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract function {0} in non-abstract class {1}") { + PsiElementOnlyDiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract function {0} in non-abstract class {1}") { @NotNull - public DiagnosticWithPsiElement on(@NotNull JetFunctionOrPropertyAccessor elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) { + public DiagnosticWithPsiElement on(@NotNull JetFunction elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) { return super.on(elementToBlame, nodeToMark, s, classDescriptor, modifierListOwner).add(DiagnosticParameters.CLASS, modifierListOwner); } }; - PsiElementOnlyDiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); - PsiElementOnlyDiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract"); + PsiElementOnlyDiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); + PsiElementOnlyDiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract"); PsiElementOnlyDiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract"); - 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"); + 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); - DiagnosticWithParameterFactory ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY = DiagnosticWithParameterFactory.create(ERROR, "Abstract 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"); @@ -130,7 +130,7 @@ public interface Errors { SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors"); SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required"); SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed"); - PsiElementOnlyDiagnosticFactory1 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT); + PsiElementOnlyDiagnosticFactory1 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT); PsiElementOnlyDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field"); ParameterizedDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java index 09fee5a8b43..52c987ea24f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java @@ -14,7 +14,7 @@ import java.util.List; /** * @author abreslav */ -abstract public class JetFunction extends JetTypeParameterListOwner implements JetFunctionOrPropertyAccessor { +abstract public class JetFunction extends JetTypeParameterListOwner implements JetDeclarationWithBody, JetModifierListOwner { public JetFunction(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java deleted file mode 100644 index 9ce62477999..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.jet.lang.psi; - -/** - * @author svtk - */ -public interface JetFunctionOrPropertyAccessor extends JetDeclarationWithBody, JetModifierListOwner { -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java index a1aa5e418c9..6cf67771acb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java @@ -13,7 +13,7 @@ import java.util.List; /** * @author max */ -public class JetPropertyAccessor extends JetDeclaration implements JetFunctionOrPropertyAccessor { +public class JetPropertyAccessor extends JetDeclaration implements JetDeclarationWithBody, JetModifierListOwner { public JetPropertyAccessor(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java index 97efea7d0d9..5fc9b02b565 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.Pair; @@ -10,7 +11,6 @@ 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; @@ -20,7 +20,6 @@ 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.*; @@ -114,7 +113,7 @@ public class DeclarationsChecker { private void checkObject(JetObjectDeclaration objectDeclaration, MutableClassDescriptor classDescriptor) { - checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD); + checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), Sets.newHashSet(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD)); } private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) { @@ -122,7 +121,9 @@ public class DeclarationsChecker { 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); + JetModifierList modifierList = member.getModifierList(); + assert modifierList != null; + ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD); context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass)); } } @@ -225,22 +226,10 @@ public class DeclarationsChecker { } } - protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { + protected void checkFunction(JetNamedFunction 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(); + PsiElement nameIdentifier = function.getNameIdentifier(); + JetModifierList modifierList = function.getModifierList(); ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; boolean hasAbstractModifier = abstractNode != null; if (containingDescriptor instanceof ClassDescriptor) { @@ -251,46 +240,45 @@ public class DeclarationsChecker { 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)); + context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement)); } - if (hasAbstractModifier && inTrait && !isPropertyAccessor) { + if (hasAbstractModifier && inTrait) { context.getTrace().report(REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, abstractNode, JetTokens.ABSTRACT_KEYWORD)); } if (function.getBodyExpression() != null && hasAbstractModifier) { - context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); + context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(function, abstractNode, functionDescriptor)); } - if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) { - context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); + if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null) { + context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, 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)); - } + context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, abstractNode, functionDescriptor)); } - if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) { - context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); + if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) { + context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, 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); - checkModifiers(accessor.getModifierList()); - 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)); + checkIllegalInThisContextModifiers(accessor.getModifierList(), Sets.newHashSet(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD, JetTokens.OVERRIDE_KEYWORD)); + } + JetPropertyAccessor getter = property.getGetter(); + PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); + JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null; + if (getterModifierList != null && getterDescriptor != null) { + Map nodes = getNodesCorrespondingToModifiers(getterModifierList, Sets.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.INTERNAL_KEYWORD)); + if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { + for (Map.Entry entry : nodes.entrySet()) { + context.getTrace().report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(getterModifierList, entry.getValue(), entry.getKey())); + } } - if (propertyDescriptor.getModality() != Modality.ABSTRACT && accessor.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { - ASTNode abstractModifierNode = accessor.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD); - context.getTrace().report(ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY.on(accessor, abstractModifierNode, property)); + else { + for (Map.Entry entry : nodes.entrySet()) { + context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(getterModifierList, entry.getValue(), entry.getKey())); + } } } } @@ -346,12 +334,23 @@ public class DeclarationsChecker { } } - private void checkIllegalInThisContextModifiers(@Nullable JetModifierList modifierList, JetKeywordToken... illegalModifiers) { + private void checkIllegalInThisContextModifiers(@Nullable JetModifierList modifierList, Collection illegalModifiers) { if (modifierList == null) return; for (JetKeywordToken modifier : illegalModifiers) { if (modifierList.hasModifier(modifier)) { - context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList.getModifierNode(modifier), modifier)); + context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList, modifierList.getModifierNode(modifier), modifier)); } } } + + @NotNull + public static Map getNodesCorrespondingToModifiers(@NotNull JetModifierList modifierList, Collection possibleModifiers) { + Map nodes = Maps.newHashMap(); + for (JetKeywordToken modifier : possibleModifiers) { + if (modifierList.hasModifier(modifier)) { + nodes.put(modifier, modifierList.getModifierNode(modifier)); + } + } + return nodes; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 67e12a470e7..6f52c4737ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -253,7 +253,7 @@ public class OverrideResolver { } if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) { // context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declared.getName() + " overrides nothing"); - context.getTrace().report(NOTHING_TO_OVERRIDE.on(member, overrideNode, declared)); + context.getTrace().report(NOTHING_TO_OVERRIDE.on(modifierList, overrideNode, declared)); } PsiElement nameIdentifier = member.getNameIdentifier(); if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java index 7131d3b0e02..4c919f86e94 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java @@ -12,8 +12,8 @@ import org.jetbrains.jet.lang.psi.*; /** * @author svtk */ -public class AddFunctionBodyFix extends JetIntentionAction { - public AddFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) { +public class AddFunctionBodyFix extends JetIntentionAction { + public AddFunctionBodyFix(@NotNull JetFunction element) { super(element); } @@ -37,7 +37,7 @@ public class AddFunctionBodyFix extends JetIntentionAction createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor; - return new AddFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement()); + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetFunction; + return new AddFunctionBodyFix((JetFunction) diagnostic.getPsiElement()); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java index de64087a558..42e28ef25eb 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java @@ -4,11 +4,13 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.psi.JetModifierListOwner; +import org.jetbrains.jet.lang.psi.JetPropertyAccessor; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetToken; @@ -17,19 +19,39 @@ import org.jetbrains.jet.lexer.JetTokens; /** * @author svtk */ -public class AddModifierFix extends ModifierFix { +public class AddModifierFix extends JetIntentionAction { + private final JetKeywordToken modifier; private final JetToken[] modifiersThanCanBeReplaced; private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced) { - super(element, modifier); + super(element); + this.modifier = modifier; this.modifiersThanCanBeReplaced = modifiersThanCanBeReplaced; } + @NotNull + /*package*/ static String getElementName(JetModifierListOwner modifierListOwner) { + String name = null; + if (modifierListOwner instanceof PsiNameIdentifierOwner) { + PsiElement nameIdentifier = ((PsiNameIdentifierOwner) modifierListOwner).getNameIdentifier(); + if (nameIdentifier != null) { + name = nameIdentifier.getText(); + } + } + else if (modifierListOwner instanceof JetPropertyAccessor) { + name = ((JetPropertyAccessor) modifierListOwner).getNamePlaceholder().getText(); + } + if (name == null) { + name = modifierListOwner.getText(); + } + return "'" + name + "'"; + } + @NotNull @Override public String getText() { if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) { - return "Make " + getElementName() + " " + modifier.getValue(); + return "Make " + getElementName(element) + " " + modifier.getValue(); } return "Add '" + modifier.getValue() + "' modifier"; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java deleted file mode 100644 index fa1c38e7a6c..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jetbrains.jet.plugin.quickfix; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiNameIdentifierOwner; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetModifierListOwner; -import org.jetbrains.jet.lang.psi.JetPropertyAccessor; -import org.jetbrains.jet.lexer.JetKeywordToken; - -/** - * @author svtk - */ -public abstract class ModifierFix extends JetIntentionAction { - protected final JetKeywordToken modifier; - - protected ModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier) { - super(element); - this.modifier = modifier; - } - - @NotNull - protected String getElementName() { - String name = null; - if (element instanceof PsiNameIdentifierOwner) { - PsiElement nameIdentifier = ((PsiNameIdentifierOwner) element).getNameIdentifier(); - if (nameIdentifier != null) { - name = nameIdentifier.getText(); - } - } - else if (element instanceof JetPropertyAccessor) { - name = ((JetPropertyAccessor) element).getNamePlaceholder().getText(); - } - if (name == null) { - name = element.getText(); - } - return "'" + name + "'"; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java index 02ffaa2b339..9d7df6ff1b5 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java @@ -1,9 +1,11 @@ package org.jetbrains.jet.plugin.quickfix; +import com.intellij.extapi.psi.ASTDelegatePsiElement; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.diagnostics.DiagnosticParameter; @@ -69,4 +71,12 @@ public class QuickFixUtil { } }; } + + public static boolean removePossiblyWhiteSpace(ASTDelegatePsiElement element, PsiElement possiblyWhiteSpace) { + if (possiblyWhiteSpace instanceof PsiWhiteSpace) { + element.deleteChildInternal(possiblyWhiteSpace.getNode()); + return true; + } + return false; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index a2f4fb48753..290b95890fb 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -29,7 +29,7 @@ public class QuickFixes { } static { - JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD); + JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_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); @@ -53,22 +53,21 @@ public class QuickFixes { add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); - JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); + JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory); add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory); - JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); + JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory); add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory); add(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory); - add(Errors.NON_MEMBER_ABSTRACT_ACCESSOR, removeAbstractModifierFactory); add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory); - add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD)); + add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListFactory(JetTokens.OVERRIDE_KEYWORD)); add(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD, new JetToken[] {JetTokens.OPEN_KEYWORD})); add(Errors.VAL_WITH_SETTER, ChangeVariableMutabilityFix.createFactory()); @@ -84,10 +83,10 @@ public class QuickFixes { add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory()); - JetIntentionActionFactory removeRedundantModifierFactory = RemoveRedundantModifierFix.createFactory(); + JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(true); 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.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD)); add(Errors.PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR, RemovePartsFromPropertyFix.createRemoveInitializerFactory()); @@ -96,14 +95,13 @@ public class QuickFixes { 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); + JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(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); - add(Errors.ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, DiagnosticParameters.PROPERTY)); - add(Errors.ABSTRACT_ACCESSOR_OF_NON_ABSTRACT_PROPERTY, removeAbstractModifierFactory); + JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(); + add(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory); + add(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory); + add(Errors.ILLEGAL_MODIFIER, removeModifierFactory); } -} - +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java index 4b7bb7fd187..35e58499ddc 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java @@ -4,18 +4,22 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lexer.JetTokens; /** * @author svtk */ -public class RemoveFunctionBodyFix extends JetIntentionAction { +public class RemoveFunctionBodyFix extends JetIntentionAction { - public RemoveFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) { + public RemoveFunctionBodyFix(@NotNull JetFunction element) { super(element); } @@ -39,25 +43,41 @@ public class RemoveFunctionBodyFix extends JetIntentionAction createFactory() { - return new JetIntentionActionFactory() { + private static boolean removePossiblyEquationSign(@NotNull JetElement element, @Nullable PsiElement possiblyEq) { + if (possiblyEq instanceof LeafPsiElement && ((LeafPsiElement)possiblyEq).getElementType() == JetTokens.EQ) { + QuickFixUtil.removePossiblyWhiteSpace(element, possiblyEq.getNextSibling()); + element.deleteChildInternal(possiblyEq.getNode()); + return true; + } + return false; + } + + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor; - return new RemoveFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement()); + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetFunction; + return new RemoveFunctionBodyFix((JetFunction) diagnostic.getPsiElement()); } }; } -} +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index ac68ec8c38c..79cb415fee0 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -1,14 +1,15 @@ package org.jetbrains.jet.plugin.quickfix; -import com.intellij.extapi.psi.ASTDelegatePsiElement; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiWhiteSpace; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetModifierList; @@ -20,35 +21,31 @@ import org.jetbrains.jet.lexer.JetTokens; /** * @author svtk */ -public class RemoveModifierFix extends ModifierFix { +public class RemoveModifierFix { + private final JetKeywordToken modifier; + private final boolean isRedundant; - public RemoveModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier) { - super(element, modifier); + public RemoveModifierFix(JetKeywordToken modifier, boolean isRedundant) { + this.modifier = modifier; + this.isRedundant = isRedundant; } - @NotNull - @Override - public String getText() { - if (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) { - return "Make " + getElementName() + " not " + modifier.getValue(); + private static String makeText(@Nullable JetModifierListOwner element, JetKeywordToken modifier, boolean isRedundant) { + if (isRedundant) { + return "Remove redundant '" + modifier.getValue() + "' modifier"; + } + if (element != null && modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) { + return "Make " + AddModifierFix.getElementName(element) + " not " + modifier.getValue(); } return "Remove '" + modifier.getValue() + "' modifier"; } - - @NotNull - @Override - public String getFamilyName() { - return "Remove modifier"; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - JetModifierListOwner newElement = (JetModifierListOwner) element.copy(); - element.replace(removeModifier(newElement, modifier)); + + private static String getFamilyName() { + return "Remove modifier fix"; } @NotNull - /*package*/ static T removeModifier(T element, JetToken modifier) { + private static T removeModifier(T element, JetToken modifier) { JetModifierList modifierList = element.getModifierList(); assert modifierList != null; removeModifierFromList(modifierList, modifier); @@ -56,38 +53,128 @@ public class RemoveModifierFix extends ModifierFix { PsiElement whiteSpace = modifierList.getNextSibling(); assert element instanceof JetElement; ((JetElement) element).deleteChildInternal(modifierList.getNode()); - removeWhiteSpace((JetElement) element, whiteSpace); + QuickFixUtil.removePossiblyWhiteSpace((JetElement) element, whiteSpace); } return element; } - /*package*/ static JetModifierList removeModifierFromList(@NotNull JetModifierList modifierList, JetToken modifier) { + @NotNull + private static JetModifierList removeModifierFromList(@NotNull JetModifierList modifierList, JetToken modifier) { assert modifierList.hasModifier(modifier); ASTNode modifierNode = modifierList.getModifierNode(modifier); PsiElement whiteSpace = modifierNode.getPsi().getNextSibling(); - boolean wsRemoved = removeWhiteSpace(modifierList, whiteSpace); + boolean wsRemoved = QuickFixUtil.removePossiblyWhiteSpace(modifierList, whiteSpace); modifierList.deleteChildInternal(modifierNode); if (!wsRemoved) { - removeWhiteSpace(modifierList, modifierList.getLastChild()); + QuickFixUtil.removePossiblyWhiteSpace(modifierList, modifierList.getLastChild()); } return modifierList; } - - private static boolean removeWhiteSpace(ASTDelegatePsiElement element, PsiElement subElement) { - if (subElement instanceof PsiWhiteSpace) { - element.deleteChildInternal(subElement.getNode()); - return true; + + private class RemoveModifierFromListOwner extends JetIntentionAction { + public RemoveModifierFromListOwner(@NotNull JetModifierListOwner element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return makeText(element, modifier, isRedundant); + } + + @NotNull + @Override + public String getFamilyName() { + return RemoveModifierFix.getFamilyName(); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetModifierListOwner newElement = (JetModifierListOwner) element.copy(); + element.replace(removeModifier(newElement, modifier)); } - return false; } - public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier) { + private class RemoveModifierFromList extends JetIntentionAction { + public RemoveModifierFromList(@NotNull JetModifierList element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return makeText(null, modifier, isRedundant); + } + + @NotNull + @Override + public String getFamilyName() { + return RemoveModifierFix.getFamilyName(); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetModifierList newElement = (JetModifierList) element.copy(); + element.replace(RemoveModifierFix.removeModifierFromList(newElement, modifier)); + } + } + + + public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) { return new JetIntentionActionFactory() { @Override public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return new RemoveModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier); + return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement()); } }; } -} + + private static RemoveModifierFix createRemoveModifierFixFromDiagnostic(DiagnosticWithPsiElement diagnostic, boolean isRedundant) { + DiagnosticWithParameters diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER); + JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER); + return new RemoveModifierFix(modifier, isRedundant); + } + + public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final boolean isRedundant) { + return new JetIntentionActionFactory() { + @Override + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetModifierListOwner; + return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement()); + } + }; + } + + public static JetIntentionActionFactory createRemoveModifierFromListFactory(final boolean isRedundant) { + return new JetIntentionActionFactory() { + @Override + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetModifierList; + return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement()); + } + }; + } + + public static JetIntentionActionFactory createRemoveModifierFromListFactory(final JetKeywordToken modifier, final boolean isRedundant) { + return new JetIntentionActionFactory() { + @Override + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetModifierList; + return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement()); + } + }; + } + + public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) { + return createRemoveModifierFromListOwnerFactory(modifier, false); + } + + public static JetIntentionActionFactory createRemoveModifierFromListFactory() { + return createRemoveModifierFromListFactory(false); + } + + public static JetIntentionActionFactory createRemoveModifierFromListFactory(final JetKeywordToken modifier) { + return createRemoveModifierFromListFactory(modifier, false); + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java deleted file mode 100644 index 4c895b3ebcf..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRedundantModifierFix.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.jetbrains.jet.plugin.quickfix; - -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.JetModifierList; -import org.jetbrains.jet.lexer.JetKeywordToken; - -/** - * @author svtk - */ -public class RemoveRedundantModifierFix extends JetIntentionAction { - private JetKeywordToken redundantModifier; - public RemoveRedundantModifierFix(@NotNull JetModifierList element, @NotNull JetKeywordToken redundantModifier) { - super(element); - this.redundantModifier = redundantModifier; - } - - @NotNull - @Override - public String getText() { - return "Remove redundant '" + redundantModifier + "' modifier"; - } - - @NotNull - @Override - public String getFamilyName() { - return "Remove redundant modifier"; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - JetModifierList newElement = (JetModifierList) element.copy(); - element.replace(RemoveModifierFix.removeModifierFromList(newElement, redundantModifier)); - } - - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierList; - DiagnosticWithParameters diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER); - JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER); - return new RemoveRedundantModifierFix((JetModifierList) diagnostic.getPsiElement(), modifier); - } - }; - } -} diff --git a/idea/testData/checker/infos/PropertiesWithBackingFields.jet b/idea/testData/checker/infos/PropertiesWithBackingFields.jet index 294ea276524..5e9b644e94c 100644 --- a/idea/testData/checker/infos/PropertiesWithBackingFields.jet +++ b/idea/testData/checker/infos/PropertiesWithBackingFields.jet @@ -35,8 +35,6 @@ var v5 : Int get() = 1; set(x){$v5 = x} var v6 : Int get() = $v6 + 1; set(x){} - abstract val v7 : Int abstract get - abstract var v8 : Int abstract get abstract set var v9 : Int set var v10 : Int get diff --git a/idea/testData/checker/regression/Jet67.jet b/idea/testData/checker/regression/Jet67.jet index 7c2248a5f6a..94549ab8df9 100644 --- a/idea/testData/checker/regression/Jet67.jet +++ b/idea/testData/checker/regression/Jet67.jet @@ -1,4 +1,4 @@ abstract class XXX { - abstract val a : Int abstract get + abstract val a : Int get } diff --git a/idea/testData/checkerWithErrorTypes/full/Abstract.jet b/idea/testData/checkerWithErrorTypes/full/Abstract.jet index a1c73c553d7..e1633f74b05 100644 --- a/idea/testData/checkerWithErrorTypes/full/Abstract.jet +++ b/idea/testData/checkerWithErrorTypes/full/Abstract.jet @@ -29,19 +29,19 @@ class MyClass() { abstract fun j() {} //property accessors - var i: Int abstract get abstract set - var i1: Int = 0; abstract get abstract set + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set - var j: Int get() = i; abstract set - var j1: Int = 0; get() = i; abstract set + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set - var k: Int abstract set - var k1: Int = 0; abstract set + var k: Int abstract set + var k1: Int = 0; abstract set - var l: Int abstract get abstract set - var l1: Int = 0; abstract get abstract set + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set - var n: Int abstract get abstract set(v: Int) {} + var n: Int abstract get abstract set(v: Int) {} } abstract class MyAbstractClass() { @@ -73,19 +73,19 @@ abstract class MyAbstractClass() { abstract fun j() {} //property accessors - var i: Int abstract get abstract set - var i1: Int = 0; abstract get abstract set + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set - var j: Int get() = i; abstract set - var j1: Int get() = i; abstract set + var j: Int get() = i; abstract set + var j1: Int get() = i; abstract set - var k: Int abstract set - var k1: Int = 0; abstract set + var k: Int abstract set + var k1: Int = 0; abstract set - var l: Int abstract get abstract set - var l1: Int = 0; abstract get abstract set + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set - var n: Int abstract get abstract set(v: Int) {} + var n: Int abstract get abstract set(v: Int) {} } trait MyTrait { @@ -117,19 +117,19 @@ trait MyTrait { abstract fun j() {} //property accessors - var i: Int abstract get abstract set - var i1: Int = 0; abstract get abstract set + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set - var j: Int get() = i; abstract set - var j1: Int = 0; get() = i; abstract set + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set - var k: Int abstract set - var k1: Int = 0; abstract set + var k: Int abstract set + var k1: Int = 0; abstract set - var l: Int abstract get abstract set - var l1: Int = 0; abstract get abstract set + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set - var n: Int abstract get abstract set(v: Int) {} + var n: Int abstract get abstract set(v: Int) {} } enum class MyEnum() { @@ -161,19 +161,19 @@ enum class MyEnum() { abstract fun j() {} //property accessors - var i: Int abstract get abstract set - var i1: Int = 0; abstract get abstract set + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set - var j: Int get() = i; abstract set - var j1: Int = 0; get() = i; abstract set + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set - var k: Int abstract set - var k1: Int = 0; abstract set + var k: Int abstract set + var k1: Int = 0; abstract set - var l: Int abstract get abstract set - var l1: Int = 0; abstract get abstract set + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set - var n: Int abstract get abstract set(v: Int) {} + var n: Int abstract get abstract set(v: Int) {} } abstract enum class MyAbstractEnum() {} @@ -207,19 +207,19 @@ namespace MyNamespace { abstract fun j() {} //property accessors - var i: Int abstract get abstract set - var i1: Int = 0; abstract get abstract set + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set - var j: Int get() = i; abstract set - var j1: Int = 0; get() = i; abstract set + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set - var k: Int abstract set - var k1: Int = 0; abstract set + var k: Int abstract set + var k1: Int = 0; abstract set - var l: Int abstract get abstract set - var l1: Int = 0; abstract get abstract set + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set - var n: Int abstract get abstract set(v: Int) {} + var n: Int abstract get abstract set(v: Int) {} } //creating an instance diff --git a/idea/testData/checkerWithErrorTypes/full/IllegalModifiers.jet b/idea/testData/checkerWithErrorTypes/full/IllegalModifiers.jet index 9feae3696e1..a3585e341de 100644 --- a/idea/testData/checkerWithErrorTypes/full/IllegalModifiers.jet +++ b/idea/testData/checkerWithErrorTypes/full/IllegalModifiers.jet @@ -7,7 +7,7 @@ abstract class A() { open var r: String get - abstract protected set + abstract protected set } final trait T {} @@ -15,7 +15,7 @@ abstract class A() { class FinalClass() { open fun foo() {} val i: Int = 1 - open get(): Int = $i + open get(): Int = $i var j: Int = 1 - open set(v: Int) {} + open set(v: Int) {} } \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet index 3f417b56418..9371df4b877 100644 --- a/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet +++ b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet @@ -35,10 +35,12 @@ abstract class Test() { var v5 : Int get() = 1; set(x){$v5 = x} var v6 : Int get() = $v6 + 1; set(x){} - abstract val v7 : Int abstract get - abstract var v8 : Int abstract get abstract set - var v9 : Int abstract set - var v10 : Int abstract get + abstract val v7 : Int get + abstract var v8 : Int get set + var v9 : Int set + var v10 : Int get + abstract val v11 : Int abstract get + abstract var v12 : Int abstract get abstract set } diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet index 7c2248a5f6a..94549ab8df9 100644 --- a/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet @@ -1,4 +1,4 @@ abstract class XXX { - abstract val a : Int abstract get + abstract val a : Int get } diff --git a/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody2.kt b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody2.kt new file mode 100644 index 00000000000..1712a56945f --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody2.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() : Any +} diff --git a/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody3.kt b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody3.kt new file mode 100644 index 00000000000..1712a56945f --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody3.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() : Any +} diff --git a/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt b/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt deleted file mode 100644 index 9d9d46b6606..00000000000 --- a/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt +++ /dev/null @@ -1,2 +0,0 @@ -// "Make 'get' not abstract" "true" -val i : Int = 0; get \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody2.kt b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody2.kt new file mode 100644 index 00000000000..70a03c43058 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody2.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() : Any { return "a" } +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody3.kt b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody3.kt new file mode 100644 index 00000000000..f15fe523b9c --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody3.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() : Any = 1 +} diff --git a/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt b/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt deleted file mode 100644 index 4eab8790a9e..00000000000 --- a/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt +++ /dev/null @@ -1,2 +0,0 @@ -// "Make 'get' not abstract" "true" -val i : Int = 0; abstract get \ No newline at end of file diff --git a/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty1.kt b/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty1.kt deleted file mode 100644 index 7ae88e4147a..00000000000 --- a/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty1.kt +++ /dev/null @@ -1,5 +0,0 @@ -// "Make 'i' open" "true" -open class A() { - open val i: Int = 1 - open get(): Int = $i -} \ No newline at end of file diff --git a/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty2.kt b/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty2.kt deleted file mode 100644 index 62cf211cb44..00000000000 --- a/idea/testData/quickfix/modifiers/afterNonFinalAccessorOfFinalProperty2.kt +++ /dev/null @@ -1,5 +0,0 @@ -// "Make 'get' not open" "true" -open class A() { - val i: Int = 1 - get(): Int = $i -} \ No newline at end of file diff --git a/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty1.kt b/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty1.kt deleted file mode 100644 index da2f748ec26..00000000000 --- a/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty1.kt +++ /dev/null @@ -1,5 +0,0 @@ -// "Make 'i' open" "true" -open class A() { - val i: Int = 1 - open get(): Int = $i -} \ No newline at end of file diff --git a/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty2.kt b/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty2.kt deleted file mode 100644 index 868366c07ba..00000000000 --- a/idea/testData/quickfix/modifiers/beforeNonFinalAccessorOfFinalProperty2.kt +++ /dev/null @@ -1,5 +0,0 @@ -// "Make 'get' not open" "true" -open class A() { - val i: Int = 1 - open get(): Int = $i -} \ No newline at end of file