Added 'incompatible modifiers' error; 'remove redundant modifier' fix
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -7,6 +8,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@@ -25,6 +27,27 @@ public interface Errors {
|
||||
UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.INSTANCE;
|
||||
RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE;
|
||||
PsiElementOnlyDiagnosticFactory2<PsiElement, JetType, JetType> TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected");
|
||||
ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>>(ERROR, "Incompatible modifiers: {0}") {
|
||||
@Override
|
||||
protected String makeMessageFor(Collection<JetKeywordToken> argument) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<JetKeywordToken> iterator = argument.iterator(); iterator.hasNext(); ) {
|
||||
JetKeywordToken modifier = iterator.next();
|
||||
sb.append(modifier.getValue());
|
||||
if (iterator.hasNext()) {
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
PsiElementOnlyDiagnosticFactory2<JetModifierList, JetKeywordToken, JetKeywordToken> REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2<JetModifierList, JetKeywordToken, JetKeywordToken>(Severity.WARNING, "Modifier {0} is redundant because {1} is present") {
|
||||
@NotNull
|
||||
@Override
|
||||
public Diagnostic on(@NotNull JetModifierList element, @NotNull ASTNode node, @NotNull JetKeywordToken redundantModifier, @NotNull JetKeywordToken presentModifier) {
|
||||
return new DiagnosticWithAdditionalInfo<JetModifierList, JetKeywordToken>(this, severity, makeMessage(redundantModifier, presentModifier), element, node.getTextRange(), redundantModifier);
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -90,7 +90,7 @@ public class JetPsiChecker implements Annotator {
|
||||
DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic;
|
||||
if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) {
|
||||
PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory();
|
||||
Set<IntentionActionFactory> intentionActionFactories = QuickFixes.get(factory);
|
||||
Collection<IntentionActionFactory> intentionActionFactories = QuickFixes.get(factory);
|
||||
for (IntentionActionFactory intentionActionFactory : intentionActionFactories) {
|
||||
IntentionAction action = null;
|
||||
if (intentionActionFactory != null) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory;
|
||||
@@ -11,15 +12,16 @@ import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class QuickFixes {
|
||||
private static HashMultimap<PsiElementOnlyDiagnosticFactory, IntentionActionFactory> actionMap = HashMultimap.create();
|
||||
private static final Multimap<PsiElementOnlyDiagnosticFactory, IntentionActionFactory> actionMap = HashMultimap.create();
|
||||
|
||||
public static Set<IntentionActionFactory> get(PsiElementOnlyDiagnosticFactory diagnosticFactory) {
|
||||
public static Collection<IntentionActionFactory> get(PsiElementOnlyDiagnosticFactory diagnosticFactory) {
|
||||
return actionMap.get(diagnosticFactory);
|
||||
}
|
||||
|
||||
@@ -83,6 +85,8 @@ public class QuickFixes {
|
||||
add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory());
|
||||
|
||||
add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory());
|
||||
|
||||
add(Errors.REDUNDANT_MODIFIER, RemoveRedundantModifierFix.createFactory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
@@ -47,32 +48,42 @@ public class RemoveModifierFix extends ModifierFix {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
element.replace(removeModifier(element, modifier));
|
||||
JetModifierListOwner newElement = (JetModifierListOwner) element.copy();
|
||||
element.replace(removeModifier(newElement, modifier));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/*package*/ static <T extends JetModifierListOwner> T removeModifier(T element, JetToken modifier) {
|
||||
T newElement = (T) (element.copy());
|
||||
assert newElement.hasModifier(modifier);
|
||||
JetModifierList modifierList = newElement.getModifierList();
|
||||
ASTNode modifierNode = modifierList.getModifierNode(modifier);
|
||||
PsiElement whiteSpace = modifierNode.getPsi().getNextSibling();
|
||||
((JetElement)newElement).deleteChildInternal(modifierNode);
|
||||
if (modifierList.getChildren().length == 0) {
|
||||
whiteSpace = modifierList.getNextSibling();
|
||||
((JetElement) newElement).deleteChildInternal(modifierList.getNode());
|
||||
removeWhiteSpace(newElement, whiteSpace);
|
||||
JetModifierList modifierList = element.getModifierList();
|
||||
assert modifierList != null;
|
||||
removeModifierFromList(modifierList, modifier);
|
||||
if (modifierList.getFirstChild() == null) {
|
||||
PsiElement whiteSpace = modifierList.getNextSibling();
|
||||
assert element instanceof JetElement;
|
||||
((JetElement) element).deleteChildInternal(modifierList.getNode());
|
||||
removeWhiteSpace((JetElement) element, whiteSpace);
|
||||
}
|
||||
else {
|
||||
removeWhiteSpace(newElement, whiteSpace);
|
||||
}
|
||||
return newElement;
|
||||
return element;
|
||||
}
|
||||
|
||||
private static void removeWhiteSpace(PsiElement element, PsiElement subElement) {
|
||||
if (subElement instanceof PsiWhiteSpace) {
|
||||
((JetElement) element).deleteChildInternal(subElement.getNode());
|
||||
/*package*/ 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);
|
||||
modifierList.deleteChildInternal(modifierNode);
|
||||
if (!wsRemoved) {
|
||||
removeWhiteSpace(modifierList, modifierList.getLastChild());
|
||||
}
|
||||
return modifierList;
|
||||
}
|
||||
|
||||
private static boolean removeWhiteSpace(ASTDelegatePsiElement element, PsiElement subElement) {
|
||||
if (subElement instanceof PsiWhiteSpace) {
|
||||
element.deleteChildInternal(subElement.getNode());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IntentionActionFactory<JetModifierListOwner> createFactory(final JetKeywordToken modifier) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithAdditionalInfo;
|
||||
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 IntentionActionForPsiElement<JetModifierList> {
|
||||
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 IntentionActionFactory<JetModifierList> createFactory() {
|
||||
return new IntentionActionFactory<JetModifierList>() {
|
||||
@Override
|
||||
public IntentionActionForPsiElement<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
|
||||
assert diagnostic.getPsiElement() instanceof JetModifierList;
|
||||
assert diagnostic instanceof DiagnosticWithAdditionalInfo;
|
||||
Object info = ((DiagnosticWithAdditionalInfo) diagnostic).getInfo();
|
||||
assert info instanceof JetKeywordToken;
|
||||
return new RemoveRedundantModifierFix((JetModifierList) diagnostic.getPsiElement(), (JetKeywordToken) info);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>abstract override fun foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>abstract override fun foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>abstract override fun foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>open abstract override fun foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>abstract open override fun foo()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Remove redundant 'open' modifier" "true"
|
||||
abstract class B() {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
abstract class A() : B() {
|
||||
<caret>abstract override open fun foo()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
|
||||
import org.jetbrains.jet.JetTestCaseBase;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class ModifiersTest extends LightQuickFixTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/quickfix/modifiers";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JetTestCaseBase.getTestDataPathBase();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user