Added quick fixes binding to error codes
This commit is contained in:
+7
-1
@@ -1,6 +1,8 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -10,7 +12,11 @@ public class DiagnosticWithPsiElement<T extends PsiElement> extends GenericDiagn
|
||||
private final T psiElement;
|
||||
|
||||
public DiagnosticWithPsiElement(DiagnosticFactory factory, Severity severity, String message, T psiElement) {
|
||||
super(factory, severity, message, psiElement.getContainingFile(), psiElement.getTextRange());
|
||||
this(factory, severity, message, psiElement, psiElement.getTextRange());
|
||||
}
|
||||
|
||||
public DiagnosticWithPsiElement(DiagnosticFactory factory, Severity severity, String message, T psiElement, @NotNull TextRange textRange) {
|
||||
super(factory, severity, message, psiElement.getContainingFile(), textRange);
|
||||
this.psiElement = psiElement;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public interface Errors {
|
||||
SimpleDiagnosticFactory PROPERTY_INITIALIZER_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property initializers are not allowed in traits");
|
||||
SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field");
|
||||
SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Property initializers are not allowed when no primary constructor is present");
|
||||
SimpleDiagnosticFactory REDUNDANT_ABSTRACT = SimpleDiagnosticFactory.create(WARNING, "Abstract modifier is redundant in traits");
|
||||
SimplePsiElementOnlyDiagnosticFactory<JetDeclaration> REDUNDANT_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "Abstract modifier is redundant in traits");
|
||||
ParameterizedDiagnosticFactory2<String, ClassDescriptor> ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = ParameterizedDiagnosticFactory2.create(ERROR, "Abstract property {0} in non-abstract class {1}");
|
||||
ParameterizedDiagnosticFactory2<String, ClassDescriptor> ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = ParameterizedDiagnosticFactory2.create(ERROR, "Abstract function {0} in non-abstract class {1}");
|
||||
ParameterizedDiagnosticFactory1<FunctionDescriptor> ABSTRACT_FUNCTION_WITH_BODY = ParameterizedDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract");
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public interface PsiElementOnlyDiagnosticFactory<T extends PsiElement> extends DiagnosticFactory {
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class SimplePsiElementOnlyDiagnosticFactory<T extends PsiElement> extends DiagnosticFactoryWithSeverity implements PsiElementOnlyDiagnosticFactory<T> {
|
||||
|
||||
public static <T extends PsiElement> SimplePsiElementOnlyDiagnosticFactory<T> create(Severity severity, String message) {
|
||||
return new SimplePsiElementOnlyDiagnosticFactory<T>(severity, message);
|
||||
}
|
||||
|
||||
protected final String message;
|
||||
|
||||
public SimplePsiElementOnlyDiagnosticFactory(Severity severity, String message) {
|
||||
super(severity);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Diagnostic on(@NotNull T element, @NotNull ASTNode node) {
|
||||
return new DiagnosticWithPsiElement<T>(this, severity, message, element, node.getTextRange());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Diagnostic on(@NotNull T element) {
|
||||
return on(element, element.getNode());
|
||||
}
|
||||
}
|
||||
@@ -621,7 +621,7 @@ public class BodyResolver {
|
||||
}
|
||||
if (classDescriptor.getKind() == ClassKind.TRAIT) {
|
||||
// context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in traits");
|
||||
context.getTrace().report(REDUNDANT_ABSTRACT.on(abstractNode));
|
||||
context.getTrace().report(REDUNDANT_ABSTRACT.on(property, abstractNode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,7 +799,7 @@ public class BodyResolver {
|
||||
}
|
||||
if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
|
||||
// context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in trait");
|
||||
context.getTrace().report(REDUNDANT_ABSTRACT.on(abstractNode));
|
||||
context.getTrace().report(REDUNDANT_ABSTRACT.on((JetDeclaration)function, abstractNode)); //TODO
|
||||
}
|
||||
if (function.getBodyExpression() != null && hasAbstractModifier) {
|
||||
// context.getTrace().getErrorHandler().genericError(abstractNode, "Method " + methodName + "with body cannot be abstract");
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.jetbrains.jet.plugin.annotations;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
@@ -18,6 +20,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.AnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.JetHighlighter;
|
||||
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -49,6 +52,7 @@ public class JetPsiChecker implements Annotator {
|
||||
Collection<Diagnostic> diagnostics = bindingContext.getDiagnostics();
|
||||
Set<DeclarationDescriptor> redeclarations = new HashSet<DeclarationDescriptor>();
|
||||
for (Diagnostic diagnostic : diagnostics) {
|
||||
Annotation annotation = null;
|
||||
if (diagnostic.getSeverity() == Severity.ERROR) {
|
||||
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
|
||||
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic;
|
||||
@@ -70,11 +74,25 @@ public class JetPsiChecker implements Annotator {
|
||||
markRedeclaration(redeclarations, redeclarationDiagnostic.getB(), bindingContext, holder);
|
||||
}
|
||||
else {
|
||||
holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), diagnostic.getMessage());
|
||||
annotation = holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), diagnostic.getMessage());
|
||||
}
|
||||
}
|
||||
else if (diagnostic.getSeverity() == Severity.WARNING) {
|
||||
holder.createWarningAnnotation(diagnostic.getFactory().getTextRange(diagnostic), diagnostic.getMessage());
|
||||
annotation = holder.createWarningAnnotation(diagnostic.getFactory().getTextRange(diagnostic), diagnostic.getMessage());
|
||||
}
|
||||
if (annotation != null && diagnostic instanceof DiagnosticWithPsiElement) {
|
||||
DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic;
|
||||
if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) {
|
||||
PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory();
|
||||
QuickFixes.IntentionActionFactory intentionActionFactory = QuickFixes.get(factory);
|
||||
IntentionAction action = null;
|
||||
if (intentionActionFactory != null) {
|
||||
action = intentionActionFactory.createAction(diagnosticWithPsiElement);
|
||||
}
|
||||
if (action != null) {
|
||||
annotation.registerFix(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class QuickFixes {
|
||||
private static Map<PsiElementOnlyDiagnosticFactory, IntentionActionFactory> actionMap = Maps.newHashMap();
|
||||
|
||||
public static IntentionActionFactory get(PsiElementOnlyDiagnosticFactory f) {
|
||||
return actionMap.get(f);
|
||||
}
|
||||
|
||||
private QuickFixes() {}
|
||||
|
||||
public static abstract class IntentionActionForPsiElement<T extends PsiElement> implements IntentionAction {
|
||||
protected T psiElement;
|
||||
|
||||
public IntentionActionForPsiElement(T element) {
|
||||
this.psiElement = element;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IntentionActionFactory<T extends PsiElement> {
|
||||
IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic);
|
||||
}
|
||||
|
||||
private static <T extends PsiElement> void add(PsiElementOnlyDiagnosticFactory<T> diagnosticFactory, IntentionActionFactory<T> actionFactory) {
|
||||
actionMap.put(diagnosticFactory, actionFactory);
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
add(Errors.REDUNDANT_ABSTRACT, RemoveAbstractModifierFix.factory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.jetbrains.jet.plugin.quickfix;
|
||||
|
||||
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.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class RemoveAbstractModifierFix extends QuickFixes.IntentionActionForPsiElement<JetDeclaration> {
|
||||
public RemoveAbstractModifierFix(JetDeclaration declaration) {
|
||||
super(declaration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return "remove.abstract.modifier.fix";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "remove.abstract.modifier.family";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return psiElement.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
JetDeclaration declaration = removeAbstractModifier(psiElement);
|
||||
psiElement.replace(declaration);
|
||||
}
|
||||
|
||||
public static JetDeclaration removeAbstractModifier(PsiElement element) {
|
||||
assert element instanceof JetDeclaration;
|
||||
JetDeclaration declaration = (JetDeclaration) (element.copy());
|
||||
assert declaration.hasModifier(JetTokens.ABSTRACT_KEYWORD);
|
||||
ASTNode abstractNode = declaration.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD);
|
||||
declaration.deleteChildInternal(abstractNode);
|
||||
return declaration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static QuickFixes.IntentionActionFactory<JetDeclaration> factory =
|
||||
new QuickFixes.IntentionActionFactory<JetDeclaration>() {
|
||||
@Override
|
||||
public QuickFixes.IntentionActionForPsiElement<JetDeclaration> createAction(DiagnosticWithPsiElement diagnostic) {
|
||||
assert diagnostic.getPsiElement() instanceof JetDeclaration;
|
||||
return new RemoveAbstractModifierFix((JetDeclaration) diagnostic.getPsiElement());
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user