Diagnostics & diagnostic factories refactoring

This commit is contained in:
Svetlana Isakova
2012-02-27 21:35:00 +04:00
parent 4c70d341b1
commit 631961e761
81 changed files with 1486 additions and 1999 deletions
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.jet.checkers.CheckerTestUtil;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -48,7 +49,7 @@ public class CopyAsDiagnosticTestAction extends AnAction {
assert editor != null && psiFile != null;
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile);
List<TextRange> syntaxError = AnalyzingUtils.getSyntaxErrorRanges(psiFile);
List<PsiErrorElement> syntaxError = AnalyzingUtils.getSyntaxErrorRanges(psiFile);
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext, syntaxError).toString();
@@ -79,7 +79,7 @@ public class JetPsiChecker implements Annotator {
for (Diagnostic diagnostic : diagnostics) {
// This is needed because we have the same context for all files
if (diagnostic.getFactory().getPsiFile(diagnostic) != file) continue;
if (diagnostic.getPsiFile() != file) continue;
registerDiagnosticAnnotations(diagnostic, redeclarations, holder);
}
@@ -158,7 +158,7 @@ public class JetPsiChecker implements Annotator {
@NotNull Set<PsiElement> redeclarations,
@NotNull final AnnotationHolder holder
) {
List<TextRange> textRanges = diagnostic.getFactory().getTextRanges(diagnostic);
List<TextRange> textRanges = diagnostic.getTextRanges();
if (diagnostic.getSeverity() == Severity.ERROR) {
if (diagnostic.getFactory() == Errors.UNRESOLVED_IDE_TEMPLATE) {
return;
@@ -226,21 +226,18 @@ public class JetPsiChecker implements Annotator {
return null;
}
if (diagnostic instanceof DiagnosticWithPsiElementImpl && diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) {
PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory();
Collection<JetIntentionActionFactory> intentionActionFactories = QuickFixes.get(factory);
for (JetIntentionActionFactory intentionActionFactory : intentionActionFactories) {
IntentionAction action = null;
if (intentionActionFactory != null) {
action = intentionActionFactory.createAction((DiagnosticWithPsiElement) diagnostic);
}
if (action != null) {
annotation.registerFix(action);
}
Collection<JetIntentionActionFactory> intentionActionFactories = QuickFixes.getActionFactories(diagnostic.getFactory());
for (JetIntentionActionFactory intentionActionFactory : intentionActionFactories) {
IntentionAction action = null;
if (intentionActionFactory != null) {
action = intentionActionFactory.createAction(diagnostic);
}
if (action != null) {
annotation.registerFix(action);
}
}
Collection<IntentionAction> actions = QuickFixes.get(diagnostic.getFactory());
Collection<IntentionAction> actions = QuickFixes.getActions(diagnostic.getFactory());
for (IntentionAction action : actions) {
annotation.registerFix(action);
}
@@ -259,7 +256,7 @@ public class JetPsiChecker implements Annotator {
@Nullable
private Annotation markRedeclaration(@NotNull Set<PsiElement> redeclarations, @NotNull RedeclarationDiagnostic diagnostic, @NotNull AnnotationHolder holder) {
if (!redeclarations.add(diagnostic.getPsiElement())) return null;
return holder.createErrorAnnotation(diagnostic.getFactory().getTextRanges(diagnostic).get(0), getMessage(diagnostic));
return holder.createErrorAnnotation(diagnostic.getTextRanges().get(0), getMessage(diagnostic));
}
@@ -18,11 +18,14 @@ 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.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
@@ -67,12 +70,15 @@ public class AddFunctionBodyFix extends JetIntentionAction<JetFunction> {
element.replace(newElement);
}
public static JetIntentionActionFactory<JetFunction> createFactory() {
return new JetIntentionActionFactory<JetFunction>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Nullable
@Override
public JetIntentionAction<JetFunction> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunction;
return new AddFunctionBodyFix((JetFunction) diagnostic.getPsiElement());
public JetIntentionAction createAction(Diagnostic diagnostic) {
PsiElement element = diagnostic.getPsiElement();
JetFunction function = PsiTreeUtil.getParentOfType(element, JetFunction.class, false);
if (function == null) return null;
return new AddFunctionBodyFix(function);
}
};
}
@@ -23,7 +23,7 @@ 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.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
@@ -120,17 +120,14 @@ public class AddModifierFix extends JetIntentionAction<JetModifierListOwner> {
return true;
}
public static JetIntentionActionFactory<JetModifierListOwner> createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) {
return new JetIntentionActionFactory<JetModifierListOwner>() {
public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced);
public JetIntentionAction<JetModifierListOwner> createAction(Diagnostic diagnostic) {
JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class);
if (modifierListOwner == null) return null;
return new AddModifierFix(modifierListOwner, modifier, modifiersThatCanBeReplaced);
}
};
}
public static JetIntentionActionFactory<JetModifierListOwner> createFactory(final JetKeywordToken modifier) {
return createFactory(modifier, new JetToken[0]);
}
}
@@ -23,23 +23,18 @@ 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.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetBundle;
/**
* @author svtk
*/
* @author svtk
*/
public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
private JetType type;
public AddReturnTypeFix(@NotNull JetNamedDeclaration element, JetType type) {
public AddReturnTypeFix(@NotNull JetNamedDeclaration element) {
super(element);
this.type = type;
}
@NotNull
@@ -56,13 +51,16 @@ public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return super.isAvailable(project, editor, file) && !ErrorUtils.isErrorType(type);
JetType type = QuickFixUtil.getDeclarationReturnType(element);
return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!(file instanceof JetFile)) return;
PsiElement newElement;
JetType type = QuickFixUtil.getDeclarationReturnType(element);
if (type == null) return;
if (element instanceof JetProperty) {
newElement = addPropertyType(project, (JetProperty) element, type);
}
@@ -70,7 +68,7 @@ public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
assert element instanceof JetFunction;
newElement = addFunctionType(project, (JetFunction) element, type);
}
ImportClassHelper.addImportDirectiveIfNeeded(type, (JetFile)file);
ImportClassHelper.addImportDirectiveIfNeeded(type, (JetFile) file);
element.replace(newElement);
}
@@ -79,7 +77,7 @@ public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
return true;
}
public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) {
public static JetProperty addPropertyType(@NotNull Project project, @NotNull JetProperty property, @NotNull JetType type) {
JetProperty newProperty = (JetProperty) property.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
@@ -88,7 +86,7 @@ public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
return newProperty;
}
public static JetFunction addFunctionType(Project project, JetFunction function, JetType type) {
public static JetFunction addFunctionType(@NotNull Project project, @NotNull JetFunction function, @NotNull JetType type) {
JetFunction newFunction = (JetFunction) function.copy();
JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString());
Pair<PsiElement, PsiElement> colon = JetPsiFactory.createColon(project);
@@ -103,14 +101,13 @@ public class AddReturnTypeFix extends JetIntentionAction<JetNamedDeclaration> {
element.addRangeAfter(colon.getFirst(), colon.getSecond(), anchor);
}
public static JetIntentionActionFactory<JetNamedDeclaration> createFactory() {
return new JetIntentionActionFactory<JetNamedDeclaration>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetNamedDeclaration> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetNamedDeclaration;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE);
JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE);
return new AddReturnTypeFix((JetNamedDeclaration) diagnostic.getPsiElement(), type);
public JetIntentionAction<JetNamedDeclaration> createAction(Diagnostic diagnostic) {
JetNamedDeclaration declaration = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedDeclaration.class);
if (declaration == null) return null;
return new AddReturnTypeFix(declaration);
}
};
}
@@ -18,18 +18,19 @@ 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.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.util.PsiTreeUtil;
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.JetParameter;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetTypeReference;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetBundle;
@@ -37,17 +38,30 @@ import org.jetbrains.jet.plugin.JetBundle;
* @author svtk
*/
public class ChangeAccessorTypeFix extends JetIntentionAction<JetPropertyAccessor> {
private final JetType type;
public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element, JetType type) {
public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element) {
super(element);
this.type = type;
}
@Nullable
private JetType getPropertyType() {
JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class);
if (property == null) return null;
return QuickFixUtil.getDeclarationReturnType(property);
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
JetType type = getPropertyType();
return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type);
}
@NotNull
@Override
public String getText() {
return element.isGetter() ? JetBundle.message("change.getter.type", type) : JetBundle.message("change.setter.type", type);
JetType type = getPropertyType();
return element.isGetter()
? JetBundle.message("change.getter.type", type)
: JetBundle.message("change.setter.type", type);
}
@NotNull
@@ -58,6 +72,8 @@ public class ChangeAccessorTypeFix extends JetIntentionAction<JetPropertyAccesso
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetType type = getPropertyType();
if (type == null) return;
JetPropertyAccessor newElement = (JetPropertyAccessor) element.copy();
JetTypeReference newTypeReference = JetPsiFactory.createType(project, type.toString());
@@ -75,15 +91,14 @@ public class ChangeAccessorTypeFix extends JetIntentionAction<JetPropertyAccesso
}
element.replace(newElement);
}
public static JetIntentionActionFactory<JetPropertyAccessor> createFactory() {
return new JetIntentionActionFactory<JetPropertyAccessor>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetPropertyAccessor> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetPropertyAccessor;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE);
JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE);
return new ChangeAccessorTypeFix((JetPropertyAccessor) diagnostic.getPsiElement(), type);
public JetIntentionAction<JetPropertyAccessor> createAction(Diagnostic diagnostic) {
JetPropertyAccessor accessor = QuickFixUtil.getParentElementOfType(diagnostic, JetPropertyAccessor.class);
if (accessor == null) return null;
return new ChangeAccessorTypeFix(accessor);
}
};
}
@@ -18,12 +18,12 @@ 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.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.plugin.JetBundle;
/**
@@ -52,12 +52,22 @@ public class ChangeToBackingFieldFix extends JetIntentionAction<JetSimpleNameExp
element.replace(backingField);
}
public static JetIntentionActionFactory<JetSimpleNameExpression> createFactory() {
return new JetIntentionActionFactory<JetSimpleNameExpression>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetSimpleNameExpression> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetSimpleNameExpression;
return new ChangeToBackingFieldFix((JetSimpleNameExpression) diagnostic.getPsiElement());
public JetIntentionAction<JetSimpleNameExpression> createAction(Diagnostic diagnostic) {
JetSimpleNameExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetSimpleNameExpression.class);
if (expression == null) {
PsiElement element = diagnostic.getPsiElement();
if (element instanceof JetQualifiedExpression && ((JetQualifiedExpression) element).getReceiverExpression() instanceof JetThisExpression) {
JetExpression selector = ((JetQualifiedExpression) element).getSelectorExpression();
if (selector instanceof JetSimpleNameExpression) {
expression = (JetSimpleNameExpression) selector;
}
}
}
if (expression == null) return null;
return new ChangeToBackingFieldFix(expression);
}
};
}
@@ -21,7 +21,7 @@ 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.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass;
@@ -61,12 +61,14 @@ public class ChangeToInvocationFix extends JetIntentionAction<JetDelegatorToSupe
element.replace(specifier);
}
public static JetIntentionActionFactory<JetDelegatorToSuperClass> createFactory() {
return new JetIntentionActionFactory<JetDelegatorToSuperClass>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetDelegatorToSuperClass> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass;
return new ChangeToInvocationFix((JetDelegatorToSuperClass) diagnostic.getPsiElement());
public JetIntentionAction<JetDelegatorToSuperClass> createAction(Diagnostic diagnostic) {
if (diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass) {
return new ChangeToInvocationFix((JetDelegatorToSuperClass) diagnostic.getPsiElement());
}
return null;
}
};
}
@@ -0,0 +1,74 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.Severity;
import java.util.List;
/**
* @author svtk
*/
public class FakeDiagnosticForQuickFixes implements Diagnostic {
private final PsiElement element;
public FakeDiagnosticForQuickFixes(PsiElement element) {
this.element = element;
}
@NotNull
@Override
public AbstractDiagnosticFactory getFactory() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public String getMessage() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Severity getSeverity() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiElement getPsiElement() {
return element;
}
@NotNull
@Override
public List<TextRange> getTextRanges() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public PsiFile getPsiFile() {
return element.getContainingFile();
}
}
@@ -38,7 +38,7 @@ import com.intellij.psi.search.PsiShortNamesCache;
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.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
@@ -205,11 +205,11 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
}
@Nullable
public static JetIntentionActionFactory<JetSimpleNameExpression> createFactory() {
return new JetIntentionActionFactory<JetSimpleNameExpression>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Nullable
@Override
public JetIntentionAction<JetSimpleNameExpression> createAction(@NotNull DiagnosticWithPsiElement diagnostic) {
public JetIntentionAction<JetSimpleNameExpression> createAction(@NotNull Diagnostic diagnostic) {
// There could be different psi elements (i.e. JetArrayAccessExpression), but we can fix only JetSimpleNameExpression case
if (diagnostic.getPsiElement() instanceof JetSimpleNameExpression) {
JetSimpleNameExpression psiElement = (JetSimpleNameExpression) diagnostic.getPsiElement();
@@ -219,4 +219,5 @@ public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression>
return null;
}
};
}}
}
}
@@ -21,12 +21,10 @@ 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.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameter;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import java.util.Arrays;
/**
* @author svtk
@@ -47,16 +45,4 @@ public abstract class JetIntentionAction<T extends PsiElement> implements Intent
public boolean startInWriteAction() {
return true;
}
public static DiagnosticWithParameters<PsiElement> assertAndCastToDiagnosticWithParameters(Diagnostic diagnostic, DiagnosticParameter... parameters) {
assert diagnostic instanceof DiagnosticWithParameters :
"For this type of quick fix diagnostic with additional " +
(parameters.length == 1 ? "parameter '" + parameters[0] + "'" : "parameters " + Arrays.asList(parameters)) + " is expected";
for (DiagnosticParameter parameter : parameters) {
assert ((DiagnosticWithParameters) diagnostic).hasParameter(parameter) :
"For this type of quick fix diagnostic with additional parameter '" + parameter + "' is expected";
}
return (DiagnosticWithParameters<PsiElement>) diagnostic;
}
}
@@ -16,14 +16,16 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import com.intellij.codeInsight.intention.IntentionAction;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
/**
* @author svtk
*/
public interface JetIntentionActionFactory<T extends PsiElement> {
public interface JetIntentionActionFactory {
JetIntentionAction<T> createAction(DiagnosticWithPsiElement diagnostic);
@Nullable
IntentionAction createAction(Diagnostic diagnostic);
}
@@ -16,18 +16,22 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.codeInsight.intention.IntentionAction;
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;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElementImpl;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author svtk
@@ -36,54 +40,12 @@ public class QuickFixUtil {
private QuickFixUtil() {
}
public static <T extends PsiElement, P extends T> JetIntentionActionFactory<PsiElement> createFactoryRedirectingAdditionalInfoToAnotherFactory(final JetIntentionActionFactory<T> factory, final DiagnosticParameter<P> parameter) {
return new JetIntentionActionFactory<PsiElement>() {
public static <T extends PsiElement> JetIntentionActionFactory createFactoryRedirectingAdditionalInfoToAnotherFactory(final JetIntentionActionFactory factory, final Class<T> aClass) {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<PsiElement> createAction(DiagnosticWithPsiElement diagnostic) {
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, parameter);
P element = diagnosticWithParameters.getParameter(parameter);
return (JetIntentionAction<PsiElement>) factory.createAction(new DiagnosticWithPsiElementImpl<T>(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), element));
}
};
}
public static <T extends PsiElement, P extends T> JetIntentionActionFactory<PsiElement> createFactoryRedirectingAdditionalInfoIfAnyToAnotherFactory(final JetIntentionActionFactory<T> factory, final DiagnosticParameter<P> parameter) {
return new JetIntentionActionFactory<PsiElement>() {
@Override
public JetIntentionAction<PsiElement> createAction(DiagnosticWithPsiElement diagnostic) {
if (diagnostic instanceof DiagnosticWithParameters && ((DiagnosticWithParameters<PsiElement>) diagnostic).hasParameter(parameter)) {
P element = ((DiagnosticWithParameters<PsiElement>) diagnostic).getParameter(parameter);
return (JetIntentionAction<PsiElement>) factory.createAction(new DiagnosticWithPsiElementImpl<T>(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), element));
}
return createDoNothingAction(diagnostic);
}
};
}
public static JetIntentionAction<PsiElement> createDoNothingAction(DiagnosticWithPsiElement diagnostic) {
return new JetIntentionAction<PsiElement>(diagnostic.getPsiElement()) {
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return false;
}
@NotNull
@Override
public String getText() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public String getFamilyName() {
throw new UnsupportedOperationException();
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
throw new UnsupportedOperationException();
public IntentionAction createAction(Diagnostic diagnostic) {
T element = getParentElementOfType(diagnostic, aClass);
return factory.createAction(new FakeDiagnosticForQuickFixes(element));
}
};
}
@@ -95,4 +57,23 @@ public class QuickFixUtil {
}
return false;
}
@Nullable
public static <T extends PsiElement> T getParentElementOfType(Diagnostic diagnostic, Class<T> aClass) {
return PsiTreeUtil.getParentOfType(diagnostic.getPsiElement(), aClass, false);
}
@Nullable
public static JetType getDeclarationReturnType(JetNamedDeclaration declaration) {
PsiFile file = declaration.getContainingFile();
if (!(file instanceof JetFile)) return null;
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) file, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
if (!(descriptor instanceof CallableDescriptor)) return null;
JetType type = ((CallableDescriptor) descriptor).getReturnType();
if (type instanceof DeferredType) {
type = ((DeferredType) type).getActualType();
}
return type;
}
}
@@ -19,12 +19,9 @@ package org.jetbrains.jet.plugin.quickfix;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler;
@@ -35,109 +32,107 @@ import java.util.Collection;
* @author svtk
*/
public class QuickFixes {
private static final Multimap<PsiElementOnlyDiagnosticFactory, JetIntentionActionFactory> jetActionMap = HashMultimap.create();
private static final Multimap<DiagnosticFactory, IntentionAction> actionMap = HashMultimap.create();
public static Collection<JetIntentionActionFactory> get(PsiElementOnlyDiagnosticFactory diagnosticFactory) {
return jetActionMap.get(diagnosticFactory);
private static final Multimap<AbstractDiagnosticFactory, JetIntentionActionFactory> factories = HashMultimap.create();
private static final Multimap<AbstractDiagnosticFactory, IntentionAction> actions = HashMultimap.create();
public static Collection<JetIntentionActionFactory> getActionFactories(AbstractDiagnosticFactory diagnosticFactory) {
return factories.get(diagnosticFactory);
}
public static Collection<IntentionAction> get(DiagnosticFactory diagnosticFactory) {
return actionMap.get(diagnosticFactory);
public static Collection<IntentionAction> getActions(AbstractDiagnosticFactory diagnosticFactory) {
return actions.get(diagnosticFactory);
}
private QuickFixes() {}
private static <T extends PsiElement> void add(PsiElementOnlyDiagnosticFactory<? extends T> diagnosticFactory, JetIntentionActionFactory<T> actionFactory) {
jetActionMap.put(diagnosticFactory, actionFactory);
}
static {
JetIntentionActionFactory<JetModifierListOwner> removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD);
JetIntentionActionFactory<JetModifierListOwner> addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD, JetTokens.FINAL_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);
add(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory);
JetIntentionActionFactory<JetProperty> removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory();
add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory);
factories.put(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory);
JetIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory();
factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory);
add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory);
add(Errors.PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory);
add(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory);
factories.put(Errors.PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory);
JetIntentionActionFactory<PsiElement> addAbstractToClassFactory = QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, DiagnosticParameters.CLASS);
add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
factories.put(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory);
JetIntentionActionFactory<JetFunction> removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory();
add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
JetIntentionActionFactory addAbstractToClassFactory = QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, JetClass.class);
factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory);
add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory);
JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory();
factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory);
JetIntentionActionFactory<JetFunction> addFunctionBodyFactory = AddFunctionBodyFix.createFactory();
add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory);
add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory);
factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory);
factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory);
add(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory);
add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory();
factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory);
factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory);
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}));
factories.put(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory);
factories.put(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
add(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory());
add(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory());
factories.put(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OVERRIDE_KEYWORD));
factories.put(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD, new JetToken[] {JetTokens.OPEN_KEYWORD}));
JetIntentionActionFactory<JetPropertyAccessor> changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory();
add(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory);
add(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory);
factories.put(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory());
factories.put(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory());
add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory());
JetIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory();
factories.put(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory);
factories.put(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory);
JetIntentionActionFactory<JetModifierList> removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(true);
add(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory);
add(Errors.REDUNDANT_MODIFIER_IN_TRAIT, removeRedundantModifierFactory);
add(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD));
factories.put(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory());
JetIntentionActionFactory<JetModifierListOwner> addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD});
JetIntentionActionFactory<JetModifierListOwner> 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);
JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true);
factories.put(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory);
factories.put(Errors.ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD, true));
factories.put(Errors.OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD, true));
factories.put(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD));
JetIntentionActionFactory<JetModifierList> removeModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory();
add(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
add(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
add(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
JetIntentionActionFactory addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD});
JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD);
factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, JetClass.class));
factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory);
add(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory();
factories.put(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory);
factories.put(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory);
factories.put(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
JetIntentionActionFactory<JetSimpleNameExpression> changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory();
add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
factories.put(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
JetIntentionActionFactory<JetSimpleNameExpression> unresolvedReferenceFactory = ImportClassAndFunFix.createFactory();
add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory);
JetIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory();
factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
JetIntentionActionFactory unresolvedReferenceFactory = ImportClassAndFunFix.createFactory();
factories.put(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory);
factories.put(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory());
add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory());
ImplementMethodsHandler implementMethodsHandler = new ImplementMethodsHandler();
actionMap.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actionMap.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actions.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
actions.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
ChangeVariableMutabilityFix changeVariableMutabilityFix = new ChangeVariableMutabilityFix();
actionMap.put(Errors.VAL_WITH_SETTER, changeVariableMutabilityFix);
actionMap.put(Errors.VAL_REASSIGNMENT, changeVariableMutabilityFix);
actions.put(Errors.VAL_WITH_SETTER, changeVariableMutabilityFix);
actions.put(Errors.VAL_REASSIGNMENT, changeVariableMutabilityFix);
actionMap.put(Errors.UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false));
actionMap.put(Errors.UNSAFE_CALL, new ReplaceCallFix(true));
actions.put(Errors.UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false));
actions.put(Errors.UNSAFE_CALL, new ReplaceCallFix(true));
}
}
}
@@ -24,7 +24,7 @@ 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.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunction;
@@ -88,12 +88,13 @@ public class RemoveFunctionBodyFix extends JetIntentionAction<JetFunction> {
return false;
}
public static JetIntentionActionFactory<JetFunction> createFactory() {
return new JetIntentionActionFactory<JetFunction>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetFunction> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetFunction;
return new RemoveFunctionBodyFix((JetFunction) diagnostic.getPsiElement());
public JetIntentionAction<JetFunction> createAction(Diagnostic diagnostic) {
JetFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetFunction.class);
if (function == null) return null;
return new RemoveFunctionBodyFix(function);
}
};
}
@@ -21,12 +21,11 @@ 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.tree.IElementType;
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.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
@@ -36,13 +35,14 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetBundle;
/**
* @author svtk
*/
public class RemoveModifierFix {
* @author svtk
*/
public class RemoveModifierFix extends JetIntentionAction<JetModifierListOwner> {
private final JetKeywordToken modifier;
private final boolean isRedundant;
public RemoveModifierFix(JetKeywordToken modifier, boolean isRedundant) {
public RemoveModifierFix(@NotNull JetModifierListOwner element, @NotNull JetKeywordToken modifier, boolean isRedundant) {
super(element);
this.modifier = modifier;
this.isRedundant = isRedundant;
}
@@ -56,8 +56,10 @@ public class RemoveModifierFix {
}
return JetBundle.message("remove.modifier", modifier.getValue());
}
private static String getFamilyName() {
@NotNull
@Override
public String getFamilyName() {
return JetBundle.message("remove.modifier.family");
}
@@ -87,111 +89,53 @@ public class RemoveModifierFix {
}
return modifierList;
}
private class RemoveModifierFromListOwner extends JetIntentionAction<JetModifierListOwner> {
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));
}
@NotNull
@Override
public String getText() {
return makeText(element, modifier, isRedundant);
}
private class RemoveModifierFromList extends JetIntentionAction<JetModifierList> {
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));
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetModifierListOwner newElement = (JetModifierListOwner) element.copy();
element.replace(removeModifier(newElement, modifier));
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierListOwner>() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement());
}
};
}
private static RemoveModifierFix createRemoveModifierFixFromDiagnostic(DiagnosticWithPsiElement diagnostic, boolean isRedundant) {
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER);
JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER);
return new RemoveModifierFix(modifier, isRedundant);
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierListOwner>() {
@Override
public JetIntentionAction<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierList>() {
@Override
public JetIntentionAction<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierList;
return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final JetKeywordToken modifier, final boolean isRedundant) {
return new JetIntentionActionFactory<JetModifierList>() {
@Override
public JetIntentionAction<JetModifierList> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierList;
return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement());
}
};
}
public static JetIntentionActionFactory<JetModifierListOwner> createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) {
public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) {
return createRemoveModifierFromListOwnerFactory(modifier, false);
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory() {
return createRemoveModifierFromListFactory(false);
public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) {
return new JetIntentionActionFactory() {
@Nullable
@Override
public JetIntentionAction<JetModifierListOwner> createAction(Diagnostic diagnostic) {
JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class);
if (modifierListOwner == null) return null;
return new RemoveModifierFix(modifierListOwner, modifier, isRedundant);
}
};
}
public static JetIntentionActionFactory<JetModifierList> createRemoveModifierFromListFactory(final JetKeywordToken modifier) {
return createRemoveModifierFromListFactory(modifier, false);
public static JetIntentionActionFactory createRemoveModifierFactory() {
return createRemoveModifierFactory(false);
}
public static JetIntentionActionFactory createRemoveModifierFactory(final boolean isRedundant) {
return new JetIntentionActionFactory() {
@Nullable
@Override
public JetIntentionAction<JetModifierListOwner> createAction(Diagnostic diagnostic) {
JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class);
if (modifierListOwner == null) return null;
PsiElement psiElement = diagnostic.getPsiElement();
IElementType elementType = psiElement.getNode().getElementType();
if (!(elementType instanceof JetKeywordToken)) return null;
JetKeywordToken modifier = (JetKeywordToken) elementType;
return new RemoveModifierFix(modifierListOwner, modifier, isRedundant);
}
};
}
}
@@ -20,16 +20,12 @@ 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.util.PsiTreeUtil;
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.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.psi.JetPropertyAccessor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetBundle;
@@ -37,29 +33,23 @@ import org.jetbrains.jet.plugin.JetBundle;
* @author svtk
*/
public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty> {
private final JetType type;
private final boolean removeInitializer;
private final boolean removeGetter;
private final boolean removeSetter;
private RemovePartsFromPropertyFix(@NotNull JetProperty element, @Nullable JetType type, boolean removeInitializer, boolean removeGetter, boolean removeSetter) {
private RemovePartsFromPropertyFix(@NotNull JetProperty element, boolean removeInitializer, boolean removeGetter, boolean removeSetter) {
super(element);
this.type = type;
this.removeInitializer = removeInitializer;
this.removeGetter = removeGetter;
this.removeSetter = removeSetter;
}
private RemovePartsFromPropertyFix(@NotNull JetProperty element, @Nullable JetType type) {
this(element, type, element.getInitializer() != null,
private RemovePartsFromPropertyFix(@NotNull JetProperty element) {
this(element, element.getInitializer() != null,
element.getGetter() != null && element.getGetter().getBodyExpression() != null,
element.getSetter() != null && element.getSetter().getBodyExpression() != null);
}
private RemovePartsFromPropertyFix(@NotNull JetProperty element, boolean removeInitializer, boolean removeGetter, boolean removeSetter) {
this(element, null, removeInitializer, removeGetter, removeSetter);
}
private static String partsToRemove(boolean getter, boolean setter, boolean initializer) {
StringBuilder sb = new StringBuilder();
if (getter) {
@@ -95,9 +85,16 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
return JetBundle.message("remove.parts.from.property.family");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
JetType type = QuickFixUtil.getDeclarationReturnType(element);
return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!(file instanceof JetFile)) return;
JetType type = QuickFixUtil.getDeclarationReturnType(element);
JetProperty newElement = (JetProperty) element.copy();
JetPropertyAccessor getter = newElement.getGetter();
if (removeGetter && getter != null) {
@@ -127,24 +124,15 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction<JetProperty>
element.replace(newElement);
}
public static JetIntentionActionFactory<JetProperty> createFactory() {
return new JetIntentionActionFactory<JetProperty>() {
public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetProperty> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetProperty;
DiagnosticWithParameters<PsiElement> diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE);
JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE);
return new RemovePartsFromPropertyFix((JetProperty) diagnostic.getPsiElement(), type);
}
};
}
public static JetIntentionActionFactory<JetProperty> createRemoveInitializerFactory() {
return new JetIntentionActionFactory<JetProperty>() {
@Override
public JetIntentionAction<JetProperty> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetProperty;
return new RemovePartsFromPropertyFix((JetProperty) diagnostic.getPsiElement(), true, false, false);
public JetIntentionAction<JetProperty> createAction(Diagnostic diagnostic) {
PsiElement element = diagnostic.getPsiElement();
assert element instanceof JetElement;
JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class);
if (property == null) return null;
return new RemovePartsFromPropertyFix(property);
}
};
}
@@ -21,7 +21,7 @@ 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.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS;
import org.jetbrains.jet.lang.psi.JetExpression;
@@ -30,9 +30,16 @@ import org.jetbrains.jet.plugin.JetBundle;
/**
* @author svtk
*/
public abstract class RemoveRightPartOfBinaryExpressionFix<T extends JetExpression> extends JetIntentionAction<T> {
public RemoveRightPartOfBinaryExpressionFix(@NotNull T element) {
public class RemoveRightPartOfBinaryExpressionFix<T extends JetExpression> extends JetIntentionAction<T> {
private final String message;
public RemoveRightPartOfBinaryExpressionFix(@NotNull T element, String message) {
super(element);
this.message = message;
}
public String getText() {
return message;
}
@NotNull
@@ -53,34 +60,24 @@ public abstract class RemoveRightPartOfBinaryExpressionFix<T extends JetExpressi
}
}
public static JetIntentionActionFactory<JetBinaryExpressionWithTypeRHS> createRemoveCastFactory() {
return new JetIntentionActionFactory<JetBinaryExpressionWithTypeRHS>() {
public static JetIntentionActionFactory createRemoveCastFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetBinaryExpressionWithTypeRHS> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS;
return new RemoveRightPartOfBinaryExpressionFix<JetBinaryExpressionWithTypeRHS>((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement()) {
@NotNull
@Override
public String getText() {
return JetBundle.message("remove.cast");
}
};
public JetIntentionAction<JetBinaryExpressionWithTypeRHS> createAction(Diagnostic diagnostic) {
JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class);
if (expression == null) return null;
return new RemoveRightPartOfBinaryExpressionFix<JetBinaryExpressionWithTypeRHS>(expression, JetBundle.message("remove.cast"));
}
};
}
public static JetIntentionActionFactory<JetBinaryExpression> createRemoveElvisOperatorFactory() {
return new JetIntentionActionFactory<JetBinaryExpression>() {
public static JetIntentionActionFactory createRemoveElvisOperatorFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetBinaryExpression> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetBinaryExpression;
return new RemoveRightPartOfBinaryExpressionFix<JetBinaryExpression>((JetBinaryExpression) diagnostic.getPsiElement()) {
@NotNull
@Override
public String getText() {
return JetBundle.message("remove.elvis.operator");
}
};
public JetIntentionAction<JetBinaryExpression> createAction(Diagnostic diagnostic) {
JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class);
if (expression == null) return null;
return new RemoveRightPartOfBinaryExpressionFix<JetBinaryExpression>(expression, JetBundle.message("remove.elvis.operator"));
}
};
}
@@ -18,10 +18,11 @@ 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.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
@@ -33,6 +34,7 @@ import org.jetbrains.jet.plugin.JetBundle;
*/
public abstract class ReplaceOperationInBinaryExpressionFix<T extends JetExpression> extends JetIntentionAction<T> {
private final String operation;
public ReplaceOperationInBinaryExpressionFix(@NotNull T element, String operation) {
super(element);
this.operation = operation;
@@ -56,12 +58,13 @@ public abstract class ReplaceOperationInBinaryExpressionFix<T extends JetExpress
}
}
public static JetIntentionActionFactory<JetBinaryExpressionWithTypeRHS> createChangeCastToStaticAssertFactory() {
return new JetIntentionActionFactory<JetBinaryExpressionWithTypeRHS>() {
public static JetIntentionActionFactory createChangeCastToStaticAssertFactory() {
return new JetIntentionActionFactory() {
@Override
public JetIntentionAction<JetBinaryExpressionWithTypeRHS> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS;
return new ReplaceOperationInBinaryExpressionFix<JetBinaryExpressionWithTypeRHS>((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement(), " : ") {
public JetIntentionAction<JetBinaryExpressionWithTypeRHS> createAction(Diagnostic diagnostic) {
JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class);
if (expression == null) return null;
return new ReplaceOperationInBinaryExpressionFix<JetBinaryExpressionWithTypeRHS>(expression, " : ") {
@NotNull
@Override
public String getText() {
@@ -4,5 +4,5 @@ abstract class B() {
}
abstract class A() : B() {
abstract override<caret> fun foo()
abstract override <caret>fun foo()
}