Quick Fix: Create Abstract Method from Usage

This commit is contained in:
Anton Makeev
2009-09-21 18:29:28 +04:00
parent 0f7795752b
commit 6ad85ec855
6 changed files with 90 additions and 10 deletions
@@ -350,6 +350,7 @@ public class HighlightMethodUtil {
else {
TextRange range = getFixRange(methodCall);
QuickFixAction.registerQuickFixAction(highlightInfo, range, new CreateMethodFromUsageFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, range, new CreateAbstractMethodFromUsageFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, range, new CreatePropertyFromUsageFix(methodCall), null);
}
}
@@ -461,6 +462,7 @@ public class HighlightMethodUtil {
PsiExpressionList list, PsiResolveHelper resolveHelper) {
TextRange fixRange = getFixRange(methodCall);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new CreateMethodFromUsageFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new CreateAbstractMethodFromUsageFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new CreateConstructorFromSuperFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new CreateConstructorFromThisFix(methodCall), null);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new CreatePropertyFromUsageFix(methodCall), null);
@@ -0,0 +1,42 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class CreateAbstractMethodFromUsageFix extends CreateMethodFromUsageFix {
public CreateAbstractMethodFromUsageFix(PsiMethodCallExpression methodCall) {
super(methodCall);
}
@Override
protected String getDisplayString(String name) {
return QuickFixBundle.message("create.abstract.method.from.usage.text", name);
}
@NotNull
@Override
protected List<PsiClass> getTargetClasses(PsiElement element) {
List<PsiClass> result = new ArrayList<PsiClass>();
PsiReferenceExpression expr = getMethodCall().getMethodExpression();
for (PsiClass each : super.getTargetClasses(element)) {
if (PsiUtil.isAbstractClass(each) && !each.isInterface() && !shouldCreateStaticMember(expr, each)) result.add(each);
}
return result;
}
@Override
protected String getVisibility(PsiClass parentClass, PsiClass targetClass) {
String result = super.getVisibility(parentClass, targetClass);
return PsiModifier.PUBLIC.equals(result) ? result : PsiModifier.PROTECTED;
}
@Override
protected boolean shouldBeAbstract(PsiClass targetClass) {
return true;
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -134,16 +135,19 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
return FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
}
protected static void setupVisibility(PsiClass parentClass, PsiClass targetClass, PsiModifierList list) throws IncorrectOperationException {
protected void setupVisibility(PsiClass parentClass, PsiClass targetClass, PsiModifierList list) throws IncorrectOperationException {
if (targetClass.isInterface()) {
list.deleteChildRange(list.getFirstChild(), list.getLastChild());
return;
}
RefactoringUtil.setVisibility(list, getVisibility(parentClass, targetClass));
}
protected String getVisibility(PsiClass parentClass, PsiClass targetClass) {
if (parentClass != null && (parentClass.equals(targetClass) || PsiTreeUtil.isAncestor(targetClass, parentClass, true))) {
list.setModifierProperty(PsiModifier.PRIVATE, true);
return PsiModifier.PRIVATE;
} else {
list.setModifierProperty(PsiModifier.PUBLIC, true);
return PsiModifier.PUBLIC;
}
}
@@ -50,10 +50,14 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
if (name == null || !JavaPsiFacade.getInstance(ref.getProject()).getNameHelper().isIdentifier(name)) return false;
if (hasErrorsInArgumentList(call)) return false;
setText(QuickFixBundle.message("create.method.from.usage.text", name));
setText(getDisplayString(name));
return true;
}
protected String getDisplayString(String name) {
return QuickFixBundle.message("create.method.from.usage.text", name);
}
private static boolean isMethodSignatureExists(PsiMethodCallExpression call, PsiClass target) {
String name = call.getMethodExpression().getReferenceName();
PsiExpressionList list = call.getArgumentList();
@@ -142,20 +146,24 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
PsiCodeBlock body = method.getBody();
assert body != null;
if (targetClass.isInterface()) {
if (shouldBeAbstract(targetClass)) {
body.delete();
if (!targetClass.isInterface()) {
method.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, true);
}
}
setupVisibility(parentClass, targetClass, method.getModifierList());
if (shouldCreateStaticMember(expression.getMethodExpression(), targetClass) && !targetClass.isInterface()) {
if (shouldCreateStaticMember(expression.getMethodExpression(), targetClass) && !shouldBeAbstract(targetClass)) {
PsiUtil.setModifierProperty(method, PsiModifier.STATIC, true);
}
final PsiElement context = PsiTreeUtil.getParentOfType(expression, PsiClass.class, PsiMethod.class);
PsiExpression[] arguments = expression.getArgumentList().getExpressions();
doCreate(targetClass, method, ContainerUtil.map2List(arguments, new Function<PsiExpression, Pair<PsiExpression, PsiType>>() {
doCreate(targetClass, method, shouldBeAbstract(targetClass),
ContainerUtil.map2List(arguments, new Function<PsiExpression, Pair<PsiExpression, PsiType>>() {
public Pair<PsiExpression, PsiType> fun(PsiExpression psiExpression) {
return Pair.create(psiExpression, null);
}
@@ -169,6 +177,16 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
public static void doCreate(PsiClass targetClass, PsiMethod method, List<Pair<PsiExpression, PsiType>> arguments, PsiSubstitutor substitutor,
ExpectedTypeInfo[] expectedTypes, @Nullable PsiElement context) {
doCreate(targetClass, method, shouldBeAbstractImpl(targetClass), arguments, substitutor, expectedTypes, context);
}
private static void doCreate(PsiClass targetClass,
PsiMethod method,
boolean shouldBeAbstract,
List<Pair<PsiExpression, PsiType>> arguments,
PsiSubstitutor substitutor,
ExpectedTypeInfo[] expectedTypes,
@Nullable PsiElement context) {
method = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(method);
@@ -185,7 +203,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
new GuessTypeParameters(JavaPsiFacade.getInstance(project).getElementFactory())
.setupTypeElement(method.getReturnTypeElement(), expectedTypes, substitutor, builder, context, targetClass);
PsiCodeBlock body = method.getBody();
builder.setEndVariableAfter(targetClass.isInterface() || body == null ? method : body.getLBrace());
builder.setEndVariableAfter(shouldBeAbstract || body == null ? method : body.getLBrace());
method = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(method);
if (method == null) return;
@@ -196,7 +214,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
newEditor.getCaretModel().moveToOffset(rangeMarker.getStartOffset());
newEditor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
if (!targetClass.isInterface()) {
if (!shouldBeAbstract) {
startTemplate(newEditor, template, project, new TemplateEditingAdapter() {
public void templateFinished(Template template) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -225,6 +243,14 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
}
}
protected boolean shouldBeAbstract(PsiClass targetClass) {
return shouldBeAbstractImpl(targetClass);
}
private static boolean shouldBeAbstractImpl(PsiClass targetClass) {
return targetClass.isInterface();
}
protected boolean isValidElement(PsiElement element) {
PsiMethodCallExpression callExpression = (PsiMethodCallExpression) element;
PsiReferenceExpression referenceExpression = callExpression.getMethodExpression();
@@ -238,7 +264,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix {
}
@Nullable
private PsiMethodCallExpression getMethodCall() {
protected PsiMethodCallExpression getMethodCall() {
return (PsiMethodCallExpression)myMethodCall.getElement();
}
}
@@ -220,6 +220,11 @@ public final class PsiUtil extends PsiUtilBase {
return parent instanceof PsiDeclarationStatement && parent.getParent() instanceof PsiCodeBlock;
}
public static boolean isAbstractClass(PsiClass clazz) {
PsiModifierList modifierList = clazz.getModifierList();
return modifierList != null && modifierList.hasModifierProperty(PsiModifier.ABSTRACT);
}
/**
* @return codeblock topmost codeblock where variable makes sense
*/
@@ -84,6 +84,7 @@ create.local.from.instanceof.usage.family=Create Local Var from instanceof Usage
create.local.from.instanceof.usage.text=Insert ''({0}){1}'' declaration
create.method.from.usage.family=Create Method from Usage
create.method.from.usage.text=Create Method ''{0}''
create.abstract.method.from.usage.text=Create Abstract Method ''{0}''
create.parameter.from.usage.family=Create Parameter from Usage
create.parameter.from.usage.text=Create Parameter ''{0}''
create.property.from.usage.family=Create Property From Usage