Added AddAbstractModifierFix, renamed JetChangeUtil -> JetPsiFactory

This commit is contained in:
svtk
2011-09-15 20:17:09 +04:00
parent ae66babdc2
commit 4b720733c0
22 changed files with 287 additions and 100 deletions
@@ -22,6 +22,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.IntentionActionFactory;
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
import java.util.Collection;
@@ -85,7 +86,7 @@ public class JetPsiChecker implements Annotator {
DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic;
if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) {
PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory();
QuickFixes.IntentionActionFactory intentionActionFactory = QuickFixes.get(factory);
IntentionActionFactory intentionActionFactory = QuickFixes.get(factory);
IntentionAction action = null;
if (intentionActionFactory != null) {
action = intentionActionFactory.createAction(diagnosticWithPsiElement);
@@ -0,0 +1,83 @@
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.*;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author svtk
*/
public class AddAbstractModifierFix extends IntentionActionForPsiElement<JetModifierListOwner> {
public AddAbstractModifierFix(@NotNull JetModifierListOwner element) {
super(element);
}
@NotNull
@Override
public String getText() {
return "add.abstract.modifier.fix";
}
@NotNull
@Override
public String getFamilyName() {
return "add.abstract.modifier.family";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return element.isValid() && !element.hasModifier(JetTokens.FINAL_KEYWORD);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
element.replace(addAbstractModifier(element, project));
}
@NotNull
public static JetModifierListOwner addAbstractModifier(@NotNull PsiElement element, @NotNull Project project) {
JetModifierListOwner newElement = (JetModifierListOwner) (element.copy());
JetModifierList modifierList = newElement.getModifierList();
JetModifierList listWithModifier = JetPsiFactory.createModifier(project, JetTokens.ABSTRACT_KEYWORD);
PsiElement whiteSpace = JetPsiFactory.createWhiteSpace(project);
if (modifierList == null) {
PsiElement firstChild = newElement.getFirstChild();
newElement.addBefore(listWithModifier, firstChild);
newElement.addBefore(whiteSpace, firstChild);
}
else if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) {
PsiElement openModifierPsi = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD).getPsi();
assert openModifierPsi != null;
openModifierPsi.replace(listWithModifier.getFirstChild());
}
else {
PsiElement lastChild = modifierList.getLastChild();
modifierList.addAfter(listWithModifier.getFirstChild(), lastChild);
modifierList.addAfter(whiteSpace, lastChild);
}
return newElement;
}
@Override
public boolean startInWriteAction() {
return true;
}
public static IntentionActionFactory<JetModifierListOwner> factory =
new IntentionActionFactory<JetModifierListOwner>() {
@Override
public IntentionActionForPsiElement<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return new AddAbstractModifierFix((JetModifierListOwner) diagnostic.getPsiElement());
}
};
}
@@ -0,0 +1,13 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
/**
* @author svtk
*/
public interface IntentionActionFactory<T extends PsiElement> {
IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic);
}
@@ -0,0 +1,16 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
* @author svtk
*/
public abstract class IntentionActionForPsiElement<T extends PsiElement> implements IntentionAction {
protected @NotNull T element;
public IntentionActionForPsiElement(@NotNull T element) {
this.element = element;
}
}
@@ -3,7 +3,6 @@ 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.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory;
@@ -15,24 +14,12 @@ import java.util.Map;
public class QuickFixes {
private static Map<PsiElementOnlyDiagnosticFactory, IntentionActionFactory> actionMap = Maps.newHashMap();
public static IntentionActionFactory get(PsiElementOnlyDiagnosticFactory f) {
return actionMap.get(f);
public static IntentionActionFactory get(PsiElementOnlyDiagnosticFactory diagnosticFactory) {
return actionMap.get(diagnosticFactory);
}
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);
}
@@ -40,6 +27,8 @@ public class QuickFixes {
static {
add(Errors.REDUNDANT_ABSTRACT, RemoveAbstractModifierFix.factory);
add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, RemoveAbstractModifierFix.factory);
add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, AddAbstractModifierFix.factory);
}
}
@@ -9,14 +9,15 @@ 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.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author svtk
*/
public class RemoveAbstractModifierFix extends QuickFixes.IntentionActionForPsiElement<JetModifierListOwner> {
public RemoveAbstractModifierFix(JetModifierListOwner element) {
public class RemoveAbstractModifierFix extends IntentionActionForPsiElement<JetModifierListOwner> {
public RemoveAbstractModifierFix(@NotNull JetModifierListOwner element) {
super(element);
}
@@ -34,22 +35,21 @@ public class RemoveAbstractModifierFix extends QuickFixes.IntentionActionForPsiE
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return psiElement.isValid();
return element.isValid();
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetDeclaration declaration = removeAbstractModifier(psiElement);
psiElement.replace(declaration);
element.replace(removeAbstractModifier(element));
}
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;
@NotNull
public static JetModifierListOwner removeAbstractModifier(PsiElement element) {
JetModifierListOwner newElement = (JetModifierListOwner) (element.copy());
assert newElement.hasModifier(JetTokens.ABSTRACT_KEYWORD);
ASTNode abstractNode = newElement.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD);
((JetElement)newElement).deleteChildInternal(abstractNode);
return newElement;
}
@Override
@@ -57,10 +57,10 @@ public class RemoveAbstractModifierFix extends QuickFixes.IntentionActionForPsiE
return true;
}
public static QuickFixes.IntentionActionFactory<JetModifierListOwner> factory =
new QuickFixes.IntentionActionFactory<JetModifierListOwner>() {
public static IntentionActionFactory<JetModifierListOwner> factory =
new IntentionActionFactory<JetModifierListOwner>() {
@Override
public QuickFixes.IntentionActionForPsiElement<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
public IntentionActionForPsiElement<JetModifierListOwner> createAction(DiagnosticWithPsiElement diagnostic) {
assert diagnostic.getPsiElement() instanceof JetModifierListOwner;
return new RemoveAbstractModifierFix((JetModifierListOwner) diagnostic.getPsiElement());
}
@@ -69,7 +69,7 @@ class JetSimpleNameReference extends JetPsiReference {
@Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
PsiElement element = JetChangeUtil.createNameIdentifier(myExpression.getProject(), newElementName);
PsiElement element = JetPsiFactory.createNameIdentifier(myExpression.getProject(), newElementName);
return myExpression.getReferencedNameElement().replace(element);
}
@@ -7,7 +7,7 @@ import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorUtil;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetChangeUtil;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
import org.jetbrains.jet.lang.types.*;
@@ -144,7 +144,7 @@ public class JetOverridingTest extends LightDaemonAnalyzerTestCase {
}
private FunctionDescriptor makeFunction(String funDecl) {
JetNamedFunction function = JetChangeUtil.createFunction(getProject(), funDecl);
JetNamedFunction function = JetPsiFactory.createFunction(getProject(), funDecl);
return classDescriptorResolver.resolveFunctionDescriptor(root, library.getLibraryScope(), function);
}
}
@@ -490,14 +490,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private void assertType(String expression, JetType expectedType) {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).getType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
assertTrue(type + " != " + expectedType, type.equals(expectedType));
}
private void assertErrorType(String expression) {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).safeGetType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type));
}
@@ -520,7 +520,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private void assertType(JetScope scope, String expression, String expectedTypeStr) {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).getType(addImports(scope), jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
JetType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
assertEquals(expectedType, type);
@@ -540,7 +540,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
}
private JetType makeType(JetScope scope, String typeStr) {
return new TypeResolver(semanticServices, JetTestUtils.DUMMY_TRACE, true).resolveType(scope, JetChangeUtil.createType(getProject(), typeStr));
return new TypeResolver(semanticServices, JetTestUtils.DUMMY_TRACE, true).resolveType(scope, JetPsiFactory.createType(getProject(), typeStr));
}
@Override
@@ -594,7 +594,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
public ClassifierDescriptor getClassifier(@NotNull String name) {
if (CLASSES.isEmpty()) {
for (String classDeclaration : CLASS_DECLARATIONS) {
JetClass classElement = JetChangeUtil.createClass(getProject(), classDeclaration);
JetClass classElement = JetPsiFactory.createClass(getProject(), classDeclaration);
ClassDescriptor classDescriptor = resolveClassDescriptor(this, classElement);
CLASSES.put(classDescriptor.getName(), classDescriptor);
}
@@ -617,7 +617,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
// }
ModuleDescriptor module = new ModuleDescriptor("TypeCheckerTest");
for (String funDecl : FUNCTION_DECLARATIONS) {
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(module, this, JetChangeUtil.createFunction(getProject(), funDecl));
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(module, this, JetPsiFactory.createFunction(getProject(), funDecl));
if (name.equals(functionDescriptor.getName())) {
writableFunctionGroup.addFunction(functionDescriptor);
}