mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ExtractClosure from method
This commit is contained in:
@@ -1086,6 +1086,11 @@
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<action id="Groovy.Extract.Closure" class="org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureAction" text="Closure...">
|
||||
<add-to-group group-id="IntroduceActionsGroup" anchor="after" relative-to-action="ExtractMethod"/>
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt shift M"/>
|
||||
</action>
|
||||
|
||||
<group id="Mvc.Actions" popup="true" class="org.jetbrains.plugins.groovy.mvc.MvcActionGroup">
|
||||
<action id="Mvc.Upgrade"
|
||||
class="org.jetbrains.plugins.groovy.mvc.MvcUpgradeAction"
|
||||
|
||||
+2
@@ -166,3 +166,5 @@ reference.to.accessor.0.is.used=Reference to accessor <bold>{0}<bold> cannot be
|
||||
variable.is.accessed.for.writing=Variable ''{0}'' is accessed for writing
|
||||
introduce.closure.parameter.elements.header=Adding parameter to a closure
|
||||
extract.closure.title=Extract closure
|
||||
cannot.process.usage.in.language.{0}=Cannot process usage in {0}
|
||||
you.cannot.pass.as.parameter.0.because.you.remove.1.from.base.method=You cannot pass ''{0}'' as parameter because you remove ''{1}'' from the method. You should deselect "Remove parameter ''{0}'' no longer used" or deselect parameter ''{1}'' in the parameter table.
|
||||
|
||||
+69
-13
@@ -34,9 +34,13 @@ import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
@@ -45,15 +49,17 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefin
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.inline.GroovyInlineMethodUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> implements RefactoringActionHandler {
|
||||
public abstract class ExtractHandlerBase implements RefactoringActionHandler {
|
||||
private static final Logger LOG = Logger.getInstance(ExtractHandlerBase.class);
|
||||
|
||||
public void invokeOnEditor(Project project, Editor editor, PsiFile file, int start, int end) throws ExtractException {
|
||||
@@ -68,12 +74,12 @@ public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> i
|
||||
SelectionModel selectionModel = editor.getSelectionModel();
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
PsiElement[] elements = ExtractUtil.getElementsInOffset(file, start, end);
|
||||
PsiElement[] elements = getElementsInOffset(file, start, end);
|
||||
if (elements.length == 1 && elements[0] instanceof GrExpression) {
|
||||
selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset());
|
||||
}
|
||||
|
||||
GrStatement[] statements = ExtractUtil.getStatementsByElements(elements);
|
||||
GrStatement[] statements = getStatementsByElements(elements);
|
||||
|
||||
if (statements.length == 0) {
|
||||
String message =
|
||||
@@ -90,8 +96,8 @@ public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> i
|
||||
}
|
||||
|
||||
GrStatement statement0 = statements[0];
|
||||
GrMemberOwner owner = ExtractUtil.getMemberOwner(statement0);
|
||||
GrStatementOwner declarationOwner = ExtractUtil.getDeclarationOwner(statement0);
|
||||
GrMemberOwner owner = getMemberOwner(statement0);
|
||||
GrStatementOwner declarationOwner = getDeclarationOwner(statement0);
|
||||
if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) {
|
||||
String message =
|
||||
RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context"));
|
||||
@@ -145,7 +151,7 @@ public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> i
|
||||
boolean hasReturns = returnStatements.size() > 0;
|
||||
List<GrStatement> returnStatementsCopy = new ArrayList<GrStatement>(returnStatements.size());
|
||||
returnStatementsCopy.addAll(returnStatements);
|
||||
boolean isReturnStatement = ExtractUtil.isReturnStatement(statements[statements.length - 1], returnStatementsCopy);
|
||||
boolean isReturnStatement = isReturnStatement(statements[statements.length - 1], returnStatementsCopy);
|
||||
boolean isLastStatementOfMethod = isLastStatementOfMethodOrClosure(statements);
|
||||
if (hasReturns && !isLastStatementOfMethod && !isReturnStatement || hasInterruptingStatements) {
|
||||
String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow");
|
||||
@@ -154,10 +160,8 @@ public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> i
|
||||
|
||||
InitialInfo info = new InitialInfo(inputInfos, outputInfos, elements, statements, owner, returnStatements);
|
||||
|
||||
InfoHelper helper = getSettings(info);
|
||||
if (helper == null) return;
|
||||
|
||||
performRefactoring(helper, owner, declarationOwner, editor, statement0);
|
||||
performRefactoring(info, owner, declarationOwner, editor, statement0);
|
||||
}
|
||||
|
||||
private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) {
|
||||
@@ -175,12 +179,64 @@ public abstract class ExtractHandlerBase<InfoHelper extends ExtractInfoHelper> i
|
||||
return statement0.getManager().areElementsEquivalent(lastFromBlock, lastStatement);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract InfoHelper getSettings(@NotNull final InitialInfo initialInfo);
|
||||
|
||||
public abstract void performRefactoring(@NotNull final InfoHelper helper,
|
||||
public abstract void performRefactoring(@NotNull final InitialInfo initialInfo,
|
||||
@NotNull final GrMemberOwner owner,
|
||||
final GrStatementOwner declarationOwner,
|
||||
final Editor editor,
|
||||
final PsiElement startElement);
|
||||
|
||||
private static GrStatement[] getStatementsByElements(PsiElement[] elements) {
|
||||
ArrayList<GrStatement> statementList = new ArrayList<GrStatement>();
|
||||
for (PsiElement element : elements) {
|
||||
if (element instanceof GrStatement) {
|
||||
statementList.add(((GrStatement) element));
|
||||
}
|
||||
}
|
||||
return statementList.toArray(new GrStatement[statementList.size()]);
|
||||
}
|
||||
|
||||
private static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset) {
|
||||
PsiElement[] elements;
|
||||
GrExpression expr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class);
|
||||
|
||||
if (expr != null) {
|
||||
PsiElement parent = expr.getParent();
|
||||
if (expr.getParent() instanceof GrMethodCallExpression || parent instanceof GrIndexProperty) {
|
||||
expr = ((GrExpression) expr.getParent());
|
||||
}
|
||||
elements = new PsiElement[]{expr};
|
||||
} else {
|
||||
elements = GroovyRefactoringUtil.findStatementsInRange(file, startOffset, endOffset, true);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrMemberOwner getMemberOwner(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
while (parent != null && !(parent instanceof GrMemberOwner)) {
|
||||
if (parent instanceof GroovyFileBase) return (GrMemberOwner) ((GroovyFileBase) parent).getScriptClass();
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return parent != null ? ((GrMemberOwner) parent) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static GrStatementOwner getDeclarationOwner(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
return parent instanceof GrStatementOwner ? ((GrStatementOwner) parent) : null;
|
||||
}
|
||||
|
||||
private static boolean isReturnStatement(GrStatement statement, Collection<GrStatement> returnStatements) {
|
||||
if (statement instanceof GrReturnStatement) return true;
|
||||
if (statement instanceof GrIfStatement) {
|
||||
boolean checked = GroovyInlineMethodUtil.checkTailIfStatement(((GrIfStatement)statement), returnStatements);
|
||||
return checked & returnStatements.size() == 0;
|
||||
|
||||
}
|
||||
if (statement instanceof GrExpression) {
|
||||
return returnStatements.contains(statement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
|
||||
|
||||
/**
|
||||
@@ -34,7 +33,7 @@ public interface ExtractInfoHelper {
|
||||
ParameterInfo[] getParameterInfos();
|
||||
|
||||
@NotNull
|
||||
VariableInfo[] getOutputNames();
|
||||
VariableInfo[] getOutputVariableInfos();
|
||||
|
||||
@NotNull
|
||||
String[] getArgumentNames();
|
||||
@@ -48,6 +47,7 @@ public interface ExtractInfoHelper {
|
||||
@NotNull
|
||||
GrStatement[] getStatements();
|
||||
|
||||
@NotNull
|
||||
GrMemberOwner getOwner();
|
||||
boolean hasReturnValue();
|
||||
|
||||
String getName();
|
||||
}
|
||||
|
||||
+3
-10
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -30,7 +29,7 @@ import java.util.Map;
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractInfoHelperBase implements ExtractInfoHelper {
|
||||
public abstract class ExtractInfoHelperBase implements ExtractInfoHelper {
|
||||
protected final InitialInfo myInitialInfo;
|
||||
protected final Map<String, ParameterInfo> myInputNamesMap;
|
||||
|
||||
@@ -66,8 +65,8 @@ public class ExtractInfoHelperBase implements ExtractInfoHelper {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public VariableInfo[] getOutputNames() {
|
||||
return myInitialInfo.getOutputNames();
|
||||
public VariableInfo[] getOutputVariableInfos() {
|
||||
return myInitialInfo.getOutputVariableInfos();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,12 +106,6 @@ public class ExtractInfoHelperBase implements ExtractInfoHelper {
|
||||
return myInitialInfo.getStatements();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GrMemberOwner getOwner() {
|
||||
return myInitialInfo.getOwner();
|
||||
}
|
||||
|
||||
public boolean hasReturnValue() {
|
||||
return myInitialInfo.hasReturnValue();
|
||||
}
|
||||
|
||||
+120
-218
@@ -16,46 +16,33 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.refactoring.extract;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.ui.ConflictsDialog;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.intentions.utils.DuplicatesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper;
|
||||
import org.jetbrains.plugins.groovy.refactoring.inline.GroovyInlineMethodUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -63,44 +50,45 @@ import java.util.*;
|
||||
* @author ilyas
|
||||
*/
|
||||
public class ExtractUtil {
|
||||
private static final Logger LOG = Logger.getInstance(ExtractUtil.class);
|
||||
|
||||
private ExtractUtil() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement calculateAnchorToInsertBefore(GrMemberOwner owner, PsiElement startElement) {
|
||||
while (startElement != null && !isEnclosingDefinition(owner, startElement)) {
|
||||
if (startElement.getParent() instanceof GroovyFile) {
|
||||
return startElement.getNextSibling();
|
||||
}
|
||||
startElement = startElement.getParent();
|
||||
PsiElement parent = startElement.getParent();
|
||||
if (parent instanceof GroovyFile && ((GroovyFile) parent).getScriptClass() == owner) {
|
||||
return startElement.getNextSibling();
|
||||
public static GrStatement replaceStatement(GrStatementOwner declarationOwner, ExtractInfoHelper helper) {
|
||||
GrStatement realStatement;
|
||||
if (declarationOwner != null && !isSingleExpression(helper.getStatements())) {
|
||||
// Replace set of statements
|
||||
final GrStatement[] newStatement = createResultStatement(helper);
|
||||
// add call statement
|
||||
final GrStatement[] statements = helper.getStatements();
|
||||
LOG.assertTrue(statements.length > 0);
|
||||
realStatement = null;
|
||||
for (GrStatement statement : newStatement) {
|
||||
realStatement = declarationOwner.addStatementBefore(statement, statements[0]);
|
||||
}
|
||||
LOG.assertTrue(realStatement != null);
|
||||
// remove old statements
|
||||
removeOldStatements(declarationOwner, helper);
|
||||
PsiImplUtil.removeNewLineAfter(realStatement);
|
||||
}
|
||||
return startElement == null ? null : startElement.getNextSibling();
|
||||
}
|
||||
|
||||
private static boolean isEnclosingDefinition(GrMemberOwner owner, PsiElement startElement) {
|
||||
if (owner instanceof GrTypeDefinition) {
|
||||
GrTypeDefinition definition = (GrTypeDefinition) owner;
|
||||
return startElement.getParent() == definition.getBody();
|
||||
else {
|
||||
// Expression call replace
|
||||
GrExpression methodCall = createMethodCall(helper);
|
||||
GrExpression oldExpr = (GrExpression)helper.getStatements()[0];
|
||||
realStatement = oldExpr.replaceWithExpression(methodCall, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum MethodAccessQualifier {
|
||||
PUBLIC, PRIVATE, PROTECTED
|
||||
GrReferenceAdjuster.shortenReferences(realStatement);
|
||||
return realStatement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static GrStatement[] createResultStatement(ExtractMethodInfoHelper helper, @NotNull String methodName) {
|
||||
VariableInfo[] outputVars = helper.getOutputNames();
|
||||
private static GrStatement[] createResultStatement(ExtractInfoHelper helper) {
|
||||
VariableInfo[] outputVars = helper.getOutputVariableInfos();
|
||||
|
||||
PsiType type = helper.getOutputType();
|
||||
GrStatement[] statements = helper.getStatements();
|
||||
GrMethodCallExpression callExpression = createMethodCallByHelper(methodName, helper);
|
||||
GrMethodCallExpression callExpression = createMethodCall(helper);
|
||||
|
||||
if ((outputVars.length == 0 || PsiType.VOID.equals(type)) && !helper.hasReturnValue()) return new GrStatement[]{callExpression};
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject());
|
||||
@@ -108,7 +96,7 @@ public class ExtractUtil {
|
||||
return new GrStatement[]{factory.createStatementFromText("return " + callExpression.getText())};
|
||||
}
|
||||
|
||||
assert outputVars.length > 0;
|
||||
LOG.assertTrue(outputVars.length > 0);
|
||||
|
||||
final List<VariableInfo> mustAdd = mustAddVariableDeclaration(statements, outputVars);
|
||||
if (mustAdd.size() == 0) {
|
||||
@@ -158,7 +146,7 @@ public class ExtractUtil {
|
||||
return diffTypes.size() > 1;
|
||||
}
|
||||
|
||||
private static GrStatement createAssignment(VariableInfo[] infos, GrMethodCallExpression callExpression, ExtractMethodInfoHelper helper) {
|
||||
private static GrStatement createAssignment(VariableInfo[] infos, GrMethodCallExpression callExpression, ExtractInfoHelper helper) {
|
||||
StringBuilder text = new StringBuilder();
|
||||
if (infos.length > 1) text.append('(');
|
||||
for (VariableInfo info : infos) {
|
||||
@@ -174,46 +162,7 @@ public class ExtractUtil {
|
||||
return GroovyPsiElementFactory.getInstance(helper.getProject()).createExpressionFromText(text.toString());
|
||||
}
|
||||
|
||||
public static boolean validateMethod(GrMethod method, ExtractMethodInfoHelper helper) {
|
||||
ArrayList<String> conflicts = new ArrayList<String>();
|
||||
GrMemberOwner owner = helper.getOwner();
|
||||
PsiMethod[] methods = ArrayUtil.mergeArrays(owner.getAllMethods(), new PsiMethod[]{method}, PsiMethod.ARRAY_FACTORY);
|
||||
final Map<PsiMethod, List<PsiMethod>> map = DuplicatesUtil.factorDuplicates(methods, new TObjectHashingStrategy<PsiMethod>() {
|
||||
public int computeHashCode(PsiMethod method) {
|
||||
return method.getSignature(PsiSubstitutor.EMPTY).hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(PsiMethod method1, PsiMethod method2) {
|
||||
return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
|
||||
}
|
||||
});
|
||||
|
||||
List<PsiMethod> list = map.get(method);
|
||||
if (list == null) return true;
|
||||
for (PsiMethod psiMethod : list) {
|
||||
if (psiMethod != method) {
|
||||
PsiClass containingClass = psiMethod.getContainingClass();
|
||||
if (containingClass == null) return true;
|
||||
String message = containingClass instanceof GroovyScriptClass ?
|
||||
GroovyRefactoringBundle.message("method.is.already.defined.in.script", GroovyRefactoringUtil.getMethodSignature(method),
|
||||
CommonRefactoringUtil.htmlEmphasize(containingClass.getQualifiedName())) :
|
||||
GroovyRefactoringBundle.message("method.is.already.defined.in.class", GroovyRefactoringUtil.getMethodSignature(method),
|
||||
CommonRefactoringUtil.htmlEmphasize(containingClass.getQualifiedName()));
|
||||
conflicts.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
return conflicts.size() <= 0 || reportConflicts(conflicts, helper.getProject());
|
||||
}
|
||||
|
||||
static boolean reportConflicts(final ArrayList<String> conflicts, final Project project) {
|
||||
ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts);
|
||||
conflictsDialog.show();
|
||||
return conflictsDialog.isOK();
|
||||
}
|
||||
|
||||
|
||||
public static void removeOldStatements(GrStatementOwner owner, ExtractMethodInfoHelper helper) throws IncorrectOperationException {
|
||||
private static void removeOldStatements(GrStatementOwner owner, ExtractInfoHelper helper) throws IncorrectOperationException {
|
||||
owner.removeElements(helper.getInnerElements());
|
||||
}
|
||||
|
||||
@@ -247,49 +196,35 @@ public class ExtractUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean containVariableDeclaration(@NotNull GrStatement[] statements, @NotNull String varName) {
|
||||
GroovyPsiElement element = ResolveUtil.resolveProperty(statements[0], varName);
|
||||
if (element == null) return false;
|
||||
for (GrStatement statement : statements) {
|
||||
if (statement.getTextRange().contains(element.getTextRange())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static Collection<GrVariable> collectUsedLocalVarsOrParamsDeclaredOutside(GrStatement[] statements) {
|
||||
final Collection<GrVariable> result = new HashSet<GrVariable>();
|
||||
|
||||
public static void renameParameterOccurrences(GrMethod method, ExtractMethodInfoHelper helper) throws IncorrectOperationException {
|
||||
GrOpenBlock block = method.getBlock();
|
||||
if (block == null) return;
|
||||
GrStatement[] statements = block.getStatements();
|
||||
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject());
|
||||
for (ParameterInfo info : helper.getParameterInfos()) {
|
||||
final String oldName = info.getOldName();
|
||||
final String newName = info.getName();
|
||||
final ArrayList<GrExpression> result = new ArrayList<GrExpression>();
|
||||
if (!oldName.equals(newName)) {
|
||||
for (final GrStatement statement : statements) {
|
||||
statement.accept(new PsiRecursiveElementVisitor() {
|
||||
public void visitElement(final PsiElement element) {
|
||||
super.visitElement(element);
|
||||
if (element instanceof GrReferenceExpression) {
|
||||
GrReferenceExpression expr = (GrReferenceExpression) element;
|
||||
if (!expr.isQualified() && oldName.equals(expr.getName())) {
|
||||
result.add(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (GrExpression expr : result) {
|
||||
expr.replaceWithExpression(factory.createExpressionFromText(newName), false);
|
||||
final int start = statements[0].getTextRange().getStartOffset();
|
||||
final int end = statements[statements.length - 1].getTextRange().getEndOffset();
|
||||
|
||||
final GroovyRecursiveElementVisitor visitor = new GroovyRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(GrReferenceExpression ref) {
|
||||
final PsiElement resolved = ref.resolve();
|
||||
if ((resolved instanceof GrParameter ||
|
||||
resolved instanceof GrVariable && GroovyRefactoringUtil.isLocalVariable((GrVariable)resolved)) && resolved.isPhysical()) {
|
||||
final int offset = resolved.getTextRange().getStartOffset();
|
||||
//var is declared outside of selected code
|
||||
if (offset < start || end <= offset) {
|
||||
result.add((GrVariable)resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (GrStatement statement : statements) {
|
||||
statement.accept(visitor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static GrMethod createMethodByHelper(@NotNull String name, ExtractMethodInfoHelper helper) {
|
||||
public static GrMethod createMethod(ExtractMethodInfoHelper helper) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
//Add signature
|
||||
@@ -300,7 +235,7 @@ public class ExtractUtil {
|
||||
String typeText = getTypeString(helper, false, modifier);
|
||||
buffer.append(modifier);
|
||||
buffer.append(typeText);
|
||||
buffer.append(name);
|
||||
buffer.append(helper.getName());
|
||||
buffer.append("(");
|
||||
for (String param : getParameterString(helper, true)) {
|
||||
buffer.append(param);
|
||||
@@ -308,27 +243,47 @@ public class ExtractUtil {
|
||||
buffer.append(") { \n");
|
||||
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject());
|
||||
VariableInfo[] outputInfos = helper.getOutputNames();
|
||||
generateBody(helper, type == PsiType.VOID, buffer);
|
||||
|
||||
buffer.append("\n}");
|
||||
|
||||
String methodText = buffer.toString();
|
||||
GrMethod method = factory.createMethodFromText(methodText);
|
||||
LOG.assertTrue(method != null);
|
||||
return method;
|
||||
}
|
||||
|
||||
public static void generateBody(ExtractInfoHelper helper, boolean isVoid, StringBuilder buffer) {
|
||||
VariableInfo[] outputInfos = helper.getOutputVariableInfos();
|
||||
|
||||
ParameterInfo[] infos = helper.getParameterInfos();
|
||||
boolean[] outputIsParameter = new boolean[outputInfos.length];
|
||||
for (int i = 0; i < outputInfos.length; i++) {
|
||||
for (ParameterInfo info : infos) {
|
||||
if (outputInfos[i].getName().equals(info.getOldName())) {
|
||||
outputIsParameter[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> declaredVars = new HashSet<String>();
|
||||
for (ParameterInfo info : infos) {
|
||||
declaredVars.add(info.getName());
|
||||
}
|
||||
|
||||
final Set<VariableInfo> mustAdd = new HashSet<VariableInfo>(mustAddVariableDeclaration(helper.getStatements(), outputInfos));
|
||||
for (VariableInfo info : mustAddVariableDeclaration(helper.getStatements(), outputInfos)) {
|
||||
declaredVars.add(info.getName());
|
||||
}
|
||||
|
||||
List<VariableInfo> genDecl = new ArrayList<VariableInfo>();
|
||||
for (int i = 0; i < outputInfos.length; i++) {
|
||||
VariableInfo info = outputInfos[i];
|
||||
if (type != PsiType.VOID && !outputIsParameter[i] &&
|
||||
!mustAdd.contains(info) &&
|
||||
!containVariableDeclaration(helper.getStatements(), info.getName())) {
|
||||
genDecl.add(info);
|
||||
final Collection<GrVariable> outside = collectUsedLocalVarsOrParamsDeclaredOutside(helper.getStatements());
|
||||
|
||||
for (final GrVariable variable : outside) {
|
||||
if (!declaredVars.contains(variable.getName())) {
|
||||
genDecl.add(new VariableInfo() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return variable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return variable.getDeclaredType();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
final List<GrStatement> statements = generateVarDeclarations(genDecl, helper.getProject(), null);
|
||||
@@ -341,7 +296,7 @@ public class ExtractUtil {
|
||||
buffer.append(element.getText());
|
||||
}
|
||||
//append return statement
|
||||
if (type != PsiType.VOID && outputInfos.length > 0) {
|
||||
if (!isVoid && outputInfos.length > 0) {
|
||||
buffer.append("\n return ");
|
||||
if (outputInfos.length > 1) buffer.append('[');
|
||||
for (VariableInfo info : outputInfos) {
|
||||
@@ -353,15 +308,29 @@ public class ExtractUtil {
|
||||
}
|
||||
else {
|
||||
GrExpression expr = (GrExpression)PsiUtil.skipParentheses(helper.getStatements()[0], false);
|
||||
buffer.append(PsiType.VOID.equals(type) ? "" : "return ").append(expr != null ? expr.getText() : "");
|
||||
boolean addReturn = !isVoid && expr != null && expr.getType() != null && expr.getType() != PsiType.VOID;
|
||||
if (addReturn) {
|
||||
buffer.append("return ");
|
||||
if (expr instanceof GrApplicationStatement) {
|
||||
final GrApplicationStatement appStatement = (GrApplicationStatement)expr;
|
||||
|
||||
buffer.append(appStatement.getInvokedExpression().getText());
|
||||
buffer.append('(');
|
||||
|
||||
final GrCommandArgumentList argList = appStatement.getArgumentList();
|
||||
if (argList != null) {
|
||||
buffer.append(argList.getText());
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
else {
|
||||
buffer.append(expr.getText());
|
||||
}
|
||||
}
|
||||
else {
|
||||
buffer.append(expr != null ? expr.getText() : "");
|
||||
}
|
||||
}
|
||||
|
||||
buffer.append("\n}");
|
||||
|
||||
String methodText = buffer.toString();
|
||||
GrMethod method = factory.createMethodFromText(methodText);
|
||||
assert method != null;
|
||||
return method;
|
||||
}
|
||||
|
||||
public static String[] getParameterString(ExtractInfoHelper helper, boolean useCanonicalText) {
|
||||
@@ -412,56 +381,14 @@ public class ExtractUtil {
|
||||
return typeText;
|
||||
}
|
||||
|
||||
public static GrStatement[] getStatementsByElements(PsiElement[] elements) {
|
||||
ArrayList<GrStatement> statementList = new ArrayList<GrStatement>();
|
||||
for (PsiElement element : elements) {
|
||||
if (element instanceof GrStatement) {
|
||||
statementList.add(((GrStatement) element));
|
||||
}
|
||||
}
|
||||
return statementList.toArray(new GrStatement[statementList.size()]);
|
||||
}
|
||||
|
||||
public static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset) {
|
||||
PsiElement[] elements;
|
||||
GrExpression expr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class);
|
||||
|
||||
if (expr != null) {
|
||||
PsiElement parent = expr.getParent();
|
||||
if (expr.getParent() instanceof GrMethodCallExpression || parent instanceof GrIndexProperty) {
|
||||
expr = ((GrExpression) expr.getParent());
|
||||
}
|
||||
elements = new PsiElement[]{expr};
|
||||
} else {
|
||||
elements = GroovyRefactoringUtil.findStatementsInRange(file, startOffset, endOffset, true);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GrMemberOwner getMemberOwner(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
while (parent != null && !(parent instanceof GrMemberOwner)) {
|
||||
if (parent instanceof GroovyFileBase) return (GrMemberOwner) ((GroovyFileBase) parent).getScriptClass();
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return parent != null ? ((GrMemberOwner) parent) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GrStatementOwner getDeclarationOwner(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
return parent instanceof GrStatementOwner ? ((GrStatementOwner) parent) : null;
|
||||
}
|
||||
|
||||
public static boolean isSingleExpression(GrStatement[] statements) {
|
||||
return statements.length == 1 && statements[0] instanceof GrExpression &&
|
||||
!(statements[0].getParent() instanceof GrVariableDeclarationOwner && statements[0] instanceof GrAssignmentExpression);
|
||||
}
|
||||
|
||||
public static GrMethodCallExpression createMethodCallByHelper(@NotNull String name, ExtractMethodInfoHelper helper) {
|
||||
private static GrMethodCallExpression createMethodCall(ExtractInfoHelper helper) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(name).append("(");
|
||||
buffer.append(helper.getName()).append("(");
|
||||
int number = 0;
|
||||
for (ParameterInfo info : helper.getParameterInfos()) {
|
||||
if (info.passAsParameter()) number++;
|
||||
@@ -482,7 +409,7 @@ public class ExtractUtil {
|
||||
String callText = buffer.toString();
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject());
|
||||
GrExpression expr = factory.createExpressionFromText(callText);
|
||||
assert expr instanceof GrMethodCallExpression;
|
||||
LOG.assertTrue(expr instanceof GrMethodCallExpression, callText);
|
||||
return ((GrMethodCallExpression) expr);
|
||||
}
|
||||
|
||||
@@ -505,35 +432,10 @@ public class ExtractUtil {
|
||||
return statement.getTextOffset();
|
||||
}
|
||||
|
||||
public static boolean canBeStatic(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
while (parent != null && !(parent instanceof PsiFile)) {
|
||||
if (parent instanceof GrMethod) {
|
||||
return ((GrMethod) parent).hasModifierProperty(PsiModifier.STATIC);
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getModifierString(ExtractMethodInfoHelper helper) {
|
||||
String visibility = helper.getVisibility();
|
||||
assert visibility != null && visibility.length() > 0;
|
||||
LOG.assertTrue(visibility != null && visibility.length() > 0);
|
||||
visibility = visibility.equals(PsiModifier.PUBLIC) ? "" : visibility + " ";
|
||||
return visibility + (helper.isStatic() ? "static " : "");
|
||||
}
|
||||
|
||||
public static boolean isReturnStatement(GrStatement statement, Collection<GrStatement> returnStatements) {
|
||||
if (statement instanceof GrReturnStatement) return true;
|
||||
if (statement instanceof GrIfStatement) {
|
||||
boolean checked = GroovyInlineMethodUtil.checkTailIfStatement(((GrIfStatement) statement), returnStatements);
|
||||
return checked & returnStatements.size() == 0;
|
||||
|
||||
}
|
||||
if (statement instanceof GrExpression) {
|
||||
return returnStatements.contains(statement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-10
@@ -42,7 +42,6 @@ public class InitialInfo implements ExtractInfoHelper {
|
||||
private final ParameterInfo[] myParameterInfos;
|
||||
private final VariableInfo[] myOutputNames;
|
||||
private final PsiType myOutputType;
|
||||
private final GrMemberOwner myTargetClass;
|
||||
private final PsiElement[] myInnerElements;
|
||||
private final Project myProject;
|
||||
private final GrStatement[] myStatements;
|
||||
@@ -57,7 +56,6 @@ public class InitialInfo implements ExtractInfoHelper {
|
||||
ArrayList<GrStatement> returnStatements) {
|
||||
myInnerElements = innerElements;
|
||||
myStatements = statements;
|
||||
myTargetClass = targetClass;
|
||||
myOutputNames = outputInfos;
|
||||
|
||||
myHasReturnValue = ContainerUtil.find(returnStatements, new Condition<GrStatement>() {
|
||||
@@ -94,7 +92,7 @@ public class InitialInfo implements ExtractInfoHelper {
|
||||
outputType = outputInfos[0].getType();
|
||||
}
|
||||
else {
|
||||
outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myTargetClass);
|
||||
outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myStatements[0]);
|
||||
}
|
||||
}
|
||||
else if (ExtractUtil.isSingleExpression(statements)) {
|
||||
@@ -137,7 +135,7 @@ public class InitialInfo implements ExtractInfoHelper {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public VariableInfo[] getOutputNames() {
|
||||
public VariableInfo[] getOutputVariableInfos() {
|
||||
return myOutputNames;
|
||||
}
|
||||
|
||||
@@ -170,13 +168,12 @@ public class InitialInfo implements ExtractInfoHelper {
|
||||
return myStatements;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GrMemberOwner getOwner() {
|
||||
return myTargetClass;
|
||||
}
|
||||
|
||||
public boolean hasReturnValue() {
|
||||
return myHasReturnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.lang.refactoring.RefactoringSupportProvider;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.actions.BasePlatformRefactoringAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureAction extends BasePlatformRefactoringAction {
|
||||
@Override
|
||||
protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) {
|
||||
return new ExtractClosureHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAvailableInEditorOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntProcedure;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel;
|
||||
import org.jetbrains.plugins.groovy.refactoring.ui.GrMethodSignatureComponent;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureDialog extends DialogWrapper {
|
||||
|
||||
private final ParameterTablePanel myTable;
|
||||
private final GrMethodSignatureComponent mySignature;
|
||||
private final EditorTextField myNameField;
|
||||
|
||||
private final ExtractClosureHelper myHelper;
|
||||
private final JBCheckBox myFinalCB;
|
||||
private final JBCheckBox myGenerateDelegateCB;
|
||||
|
||||
TObjectIntHashMap<JBCheckBox> toRemoveCBs;
|
||||
private final InitialInfo myInitialInfo;
|
||||
|
||||
public ExtractClosureDialog(InitialInfo initialInfo, GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
super(initialInfo.getProject());
|
||||
myInitialInfo = initialInfo;
|
||||
|
||||
myHelper = new ExtractClosureHelper(initialInfo, owner, toSearchFor, "", false);
|
||||
|
||||
setTitle(ExtractClosureHandler.EXTRACT_CLOSURE);
|
||||
|
||||
myTable = new ParameterTablePanel() {
|
||||
@Override
|
||||
protected void updateSignature() {
|
||||
ExtractClosureDialog.this.updateSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doEnterAction() {
|
||||
clickDefaultButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCancelAction() {
|
||||
ExtractClosureDialog.this.doCancelAction();
|
||||
}
|
||||
};
|
||||
|
||||
mySignature = new GrMethodSignatureComponent("", initialInfo.getProject());
|
||||
myNameField = new EditorTextField("", initialInfo.getProject(), GroovyFileType.GROOVY_FILE_TYPE);
|
||||
myFinalCB = new JBCheckBox(UIUtil.replaceMnemonicAmpersand("Declare &final"));
|
||||
myFinalCB.setFocusable(false);
|
||||
myGenerateDelegateCB = new JBCheckBox(UIUtil.replaceMnemonicAmpersand("De&legate via overloading method"));
|
||||
myGenerateDelegateCB.setFocusable(false);
|
||||
|
||||
TObjectIntHashMap<GrParameter> parametersToRemove = findParametersToRemove(myHelper);
|
||||
toRemoveCBs = new TObjectIntHashMap<JBCheckBox>(parametersToRemove.size());
|
||||
for (Object p : parametersToRemove.keys()) {
|
||||
JBCheckBox cb = new JBCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName()));
|
||||
cb.setFocusable(false);
|
||||
cb.setSelected(false);
|
||||
toRemoveCBs.put(cb, parametersToRemove.get((GrParameter)p));
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ValidationInfo doValidate() {
|
||||
final String text = myNameField.getText().trim();
|
||||
if (!StringUtil.isJavaIdentifier(text)) {
|
||||
return new ValidationInfo(GroovyRefactoringBundle.message("name.is.wrong", text), myNameField);
|
||||
}
|
||||
|
||||
final Ref<ValidationInfo> info = new Ref<ValidationInfo>();
|
||||
toRemoveCBs.forEachEntry(new TObjectIntProcedure<JBCheckBox>() {
|
||||
@Override
|
||||
public boolean execute(JBCheckBox checkbox, int index) {
|
||||
if (!checkbox.isSelected()) return true;
|
||||
|
||||
final ParameterInfo param = myHelper.getParameterInfos()[index];
|
||||
if (!param.passAsParameter()) return true;
|
||||
|
||||
final ParameterInfo initialParam = myInitialInfo.getParameterInfos()[index];
|
||||
final String message = GroovyRefactoringBundle.message("you.cannot.pass.as.parameter.0.because.you.remove.1.from.base.method",
|
||||
param.getName(), initialParam.getName());
|
||||
info.set(new ValidationInfo(message));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return info.get();
|
||||
}
|
||||
|
||||
private void updateSignature() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("{ ");
|
||||
String[] params = ExtractUtil.getParameterString(myHelper, false);
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (i > 0) {
|
||||
b.append(" ");
|
||||
}
|
||||
b.append(params[i]);
|
||||
b.append('\n');
|
||||
}
|
||||
b.append(" ->\n}");
|
||||
mySignature.setSignature(b.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myNameField;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
myTable.init(myHelper);
|
||||
|
||||
final JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance();
|
||||
final Boolean settingsFinals = refactoringSettings.INTRODUCE_PARAMETER_CREATE_FINALS;
|
||||
myFinalCB.setSelected(settingsFinals == null ?
|
||||
CodeStyleSettingsManager.getSettings(myHelper.getProject()).GENERATE_FINAL_PARAMETERS :
|
||||
settingsFinals.booleanValue());
|
||||
myGenerateDelegateCB.setSelected(false);
|
||||
updateSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createNorthPanel() {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
final JBLabel nameLabel = new JBLabel();
|
||||
panel.add(nameLabel, BorderLayout.NORTH);
|
||||
panel.add(myNameField, BorderLayout.CENTER);
|
||||
nameLabel.setText(UIUtil.replaceMnemonicAmpersand("Parameter &name:"));
|
||||
nameLabel.setLabelFor(myNameField);
|
||||
|
||||
final JPanel checkBoxPanel = new JPanel();
|
||||
checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS));
|
||||
|
||||
checkBoxPanel.add(myFinalCB);
|
||||
checkBoxPanel.add(myGenerateDelegateCB);
|
||||
for (Object cb : toRemoveCBs.keys()) {
|
||||
checkBoxPanel.add((Component)cb);
|
||||
}
|
||||
panel.add(checkBoxPanel, BorderLayout.SOUTH);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
final JPanel signaturePanel = new JPanel(new BorderLayout());
|
||||
signaturePanel.setBorder(
|
||||
IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("signature.preview.border.title"), false, false, true));
|
||||
signaturePanel.add(mySignature, BorderLayout.CENTER);
|
||||
|
||||
Splitter splitter = new Splitter(true);
|
||||
|
||||
splitter.setFirstComponent(myTable);
|
||||
splitter.setSecondComponent(signaturePanel);
|
||||
|
||||
mySignature.setPreferredSize(new Dimension(500, 100));
|
||||
mySignature.setSize(new Dimension(500, 100));
|
||||
|
||||
splitter.setShowDividerIcon(false);
|
||||
return splitter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
final JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance();
|
||||
settings.INTRODUCE_PARAMETER_CREATE_FINALS = Boolean.valueOf(myFinalCB.isSelected());
|
||||
|
||||
myHelper.setName(myNameField.getText());
|
||||
myHelper.setDeclareFinal(myFinalCB.isSelected());
|
||||
myHelper.setGenerateDelegate(myGenerateDelegateCB.isSelected());
|
||||
|
||||
TIntArrayList list = new TIntArrayList();
|
||||
for (Object cb : toRemoveCBs.keys()) {
|
||||
final JBCheckBox checkbox = (JBCheckBox)cb;
|
||||
if (checkbox.isSelected()) {
|
||||
list.add(toRemoveCBs.get(checkbox));
|
||||
}
|
||||
}
|
||||
myHelper.setToRemove(list);
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
public ExtractClosureHelper getHelper() {
|
||||
return myHelper;
|
||||
}
|
||||
|
||||
private static TObjectIntHashMap<GrParameter> findParametersToRemove(ExtractClosureHelper helper) {
|
||||
final TObjectIntHashMap<GrParameter> result = new TObjectIntHashMap<GrParameter>();
|
||||
|
||||
final GrStatement[] statements = helper.getStatements();
|
||||
final int start = statements[0].getTextRange().getStartOffset();
|
||||
final int end = statements[statements.length - 1].getTextRange().getEndOffset();
|
||||
|
||||
GrParameter[] parameters = helper.getOwner().getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
GrParameter parameter = parameters[i];
|
||||
if (shouldRemove(parameter, start, end)) {
|
||||
result.put(parameter, i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean shouldRemove(GrParameter parameter, int start, int end) {
|
||||
for (PsiReference reference : ReferencesSearch.search(parameter)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element == null) continue;
|
||||
|
||||
final int offset = element.getTextRange().getStartOffset();
|
||||
if (offset < start || end <= offset) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.refactoring.introduceParameter.ExternalUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureFromClosureProcessor extends ExtractClosureProcessorBase {
|
||||
public ExtractClosureFromClosureProcessor(@NotNull ExtractClosureHelper helper) {
|
||||
super(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
|
||||
//todo
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(UsageInfo[] usages) {
|
||||
//To change body of implemented methods use File | Settings | File Templates. todo
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
final List<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
|
||||
final GrVariable var = (GrVariable)myHelper.getToSearchFor();
|
||||
|
||||
for (PsiReference ref : ReferencesSearch.search(var, GlobalSearchScope.allScope(myHelper.getProject()), true)) {
|
||||
final PsiElement element = ref.getElement();
|
||||
if (element.getLanguage() != GroovyFileType.GROOVY_LANGUAGE) {
|
||||
result.add(new OtherLanguageUsageInfo(ref));
|
||||
continue;
|
||||
}
|
||||
|
||||
final GrCall call = GroovyRefactoringUtil.getCallExpressionByMethodReference(element);
|
||||
if (call == null) continue;
|
||||
|
||||
result.add(new ExternalUsageInfo(element));
|
||||
}
|
||||
|
||||
return result.toArray(new UsageInfo[result.size()]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.IntroduceParameterRefactoring;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.introduceParameter.ChangedMethodCallInfo;
|
||||
import com.intellij.refactoring.introduceParameter.ExternalUsageInfo;
|
||||
import com.intellij.refactoring.introduceParameter.InternalUsageInfo;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterData;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo;
|
||||
import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.AnySupers;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.FieldConflictsResolver;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrExpressionWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.refactoring.introduceParameter.IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts;
|
||||
import static com.intellij.refactoring.introduceParameter.IntroduceParameterUtil.processUsages;
|
||||
import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.*;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureFromMethodProcessor extends ExtractClosureProcessorBase {
|
||||
|
||||
private final GrMethod myMethod;
|
||||
private Editor myEditor;
|
||||
|
||||
public ExtractClosureFromMethodProcessor(@NotNull ExtractClosureHelper helper, Editor editor) {
|
||||
super(helper);
|
||||
myEditor = editor;
|
||||
myMethod = (GrMethod)myHelper.getOwner();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
|
||||
UsageInfo[] usagesIn = refUsages.get();
|
||||
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
final GrStatement[] statements = myHelper.getStatements();
|
||||
|
||||
for (GrStatement statement : statements) {
|
||||
detectAccessibilityConflicts(statement, usagesIn, conflicts, false, myProject);
|
||||
}
|
||||
|
||||
for (UsageInfo info : usagesIn) {
|
||||
if (info instanceof OtherLanguageUsageInfo) {
|
||||
conflicts.putValue(info.getElement(), GroovyRefactoringBundle.message("cannot.process.usage.in.language.{0}", CommonRefactoringUtil.htmlEmphasize(info.getElement().getLanguage().getDisplayName())));
|
||||
}
|
||||
}
|
||||
|
||||
if (!myMethod.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
final AnySupers anySupers = new AnySupers();
|
||||
for (GrStatement statement : statements) {
|
||||
statement.accept(anySupers);
|
||||
}
|
||||
if (anySupers.isResult()) {
|
||||
for (UsageInfo usageInfo : usagesIn) {
|
||||
if (!(usageInfo.getElement() instanceof PsiMethod) && !(usageInfo instanceof InternalUsageInfo)) {
|
||||
if (!PsiTreeUtil.isAncestor(myMethod.getContainingClass(), usageInfo.getElement(), false)) {
|
||||
conflicts.putValue(statements[0], RefactoringBundle
|
||||
.message("parameter.initializer.contains.0.but.not.all.calls.to.method.are.in.its.class",
|
||||
CommonRefactoringUtil.htmlEmphasize(PsiKeyword.SUPER)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return showConflicts(conflicts, usagesIn);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
List<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
|
||||
final PsiMethod toSearchFor = (PsiMethod)myHelper.getToSearchFor();
|
||||
|
||||
for (PsiReference ref1 : MethodReferencesSearch.search(toSearchFor, GlobalSearchScope.projectScope(myProject), true)) {
|
||||
PsiElement ref = ref1.getElement();
|
||||
if (ref.getLanguage() != GroovyFileType.GROOVY_LANGUAGE) {
|
||||
result.add(new OtherLanguageUsageInfo(ref1));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ref instanceof PsiMethod && ((PsiMethod)ref).isConstructor()) {
|
||||
DefaultConstructorImplicitUsageInfo implicitUsageInfo =
|
||||
new DefaultConstructorImplicitUsageInfo((PsiMethod)ref, ((PsiMethod)ref).getContainingClass(), toSearchFor);
|
||||
result.add(implicitUsageInfo);
|
||||
}
|
||||
else if (ref instanceof PsiClass) {
|
||||
result.add(new NoConstructorClassUsageInfo((PsiClass)ref));
|
||||
}
|
||||
else if (!PsiTreeUtil.isAncestor(myMethod, ref, false)) {
|
||||
result.add(new ExternalUsageInfo(ref));
|
||||
}
|
||||
else {
|
||||
result.add(new ChangedMethodCallInfo(ref));
|
||||
}
|
||||
}
|
||||
|
||||
Collection<PsiMethod> overridingMethods = OverridingMethodsSearch.search(toSearchFor, true).findAll();
|
||||
|
||||
for (PsiMethod overridingMethod : overridingMethods) {
|
||||
result.add(new UsageInfo(overridingMethod));
|
||||
}
|
||||
|
||||
final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]);
|
||||
return UsageViewUtil.removeDuplicatedUsages(usageInfos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(UsageInfo[] usages) {
|
||||
final IntroduceParameterData data = new IntroduceParameterDataAdapter();
|
||||
|
||||
processUsages(usages, data);
|
||||
|
||||
final PsiMethod toSearchFor = (PsiMethod)myHelper.getToSearchFor();
|
||||
|
||||
final boolean methodsToProcessAreDifferent = myMethod != toSearchFor;
|
||||
if (myHelper.generateDelegate()) {
|
||||
generateDelegate(myMethod, data.getParameterInitializer(), myProject);
|
||||
if (methodsToProcessAreDifferent) {
|
||||
final GrMethod method = generateDelegate(toSearchFor, data.getParameterInitializer(), myProject);
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && containingClass.isInterface()) {
|
||||
final GrOpenBlock block = method.getBlock();
|
||||
if (block != null) {
|
||||
block.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Changing signature of initial method
|
||||
// (signature of myMethodToReplaceIn will be either changed now or have already been changed)
|
||||
final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(myHelper.getName(), myMethod.getBlock());
|
||||
changeMethodSignatureAndResolveFieldConflicts(new UsageInfo(myMethod), usages, data);
|
||||
if (methodsToProcessAreDifferent) {
|
||||
changeMethodSignatureAndResolveFieldConflicts(new UsageInfo(toSearchFor), usages, data);
|
||||
}
|
||||
|
||||
// Replacing expression occurrences
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof ChangedMethodCallInfo) {
|
||||
PsiElement element = usage.getElement();
|
||||
|
||||
processChangedMethodCall(element, myHelper, myProject);
|
||||
}
|
||||
}
|
||||
|
||||
final GrStatement newStatement = ExtractUtil.replaceStatement(myMethod.getBlock(), myHelper);
|
||||
if (myEditor != null) {
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
|
||||
myEditor.getCaretModel().moveToOffset(ExtractUtil.getCaretOffset(newStatement));
|
||||
}
|
||||
|
||||
fieldConflictsResolver.fix();
|
||||
}
|
||||
|
||||
private class IntroduceParameterDataAdapter implements IntroduceParameterData {
|
||||
|
||||
private final GrClosableBlock myClosure;
|
||||
private final GrExpressionWrapper myWrapper;
|
||||
private final PsiType myType;
|
||||
|
||||
private IntroduceParameterDataAdapter() {
|
||||
myClosure = generateClosure();
|
||||
myWrapper = new GrExpressionWrapper(myClosure);
|
||||
myType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, myMethod);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiMethod getMethodToReplaceIn() {
|
||||
return myMethod;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod getMethodToSearchFor() {
|
||||
return (PsiMethod)myHelper.getToSearchFor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionWrapper getParameterInitializer() {
|
||||
return myWrapper;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getParameterName() {
|
||||
return myHelper.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReplaceFieldsWithGetters() {
|
||||
return IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE; //todo add option to dialog
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeclareFinal() {
|
||||
return myHelper.declareFinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerateDelegate() {
|
||||
return false; //todo
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getForcedType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TIntArrayList getParametersToRemove() {
|
||||
return myHelper.parametersToRemove();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.ide.util.SuperMethodWarningUtil;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.IntroduceTargetChooser;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PairFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.HelpID;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractException;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractHandlerBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.ui.MethodOrClosureScopeChooser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureHandler extends ExtractHandlerBase implements RefactoringActionHandler, MethodOrClosureScopeChooser.JBPopupOwner {
|
||||
public static final String EXTRACT_CLOSURE = "Extract Closure";
|
||||
private JBPopup myPopup;
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, DataContext dataContext) {
|
||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||
if (!selectionModel.hasSelection()) {
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
final List<GrExpression> expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, offset);
|
||||
if (expressions.size() == 1) {
|
||||
final TextRange textRange = expressions.get(0).getTextRange();
|
||||
selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
|
||||
}
|
||||
else {
|
||||
final Pass<GrExpression> callback = new Pass<GrExpression>() {
|
||||
public void pass(final GrExpression selectedValue) {
|
||||
invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset());
|
||||
}
|
||||
};
|
||||
final Function<GrExpression, String> renderer = new Function<GrExpression, String>() {
|
||||
@Override
|
||||
public String fun(GrExpression grExpression) {
|
||||
return grExpression.getText();
|
||||
}
|
||||
};
|
||||
IntroduceTargetChooser.showChooser(editor, expressions, callback, renderer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
|
||||
}
|
||||
|
||||
void invoke(Project project, Editor editor, PsiFile file, int start, int end) {
|
||||
try {
|
||||
invokeOnEditor(project, editor, file, start, end);
|
||||
}
|
||||
catch (ExtractException e) {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), EXTRACT_CLOSURE, HelpID.GROOVY_EXTRACT_CLOSURE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ExtractClosureHelper getSettings(@NotNull InitialInfo initialInfo, GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
final ExtractClosureDialog dialog = new ExtractClosureDialog(initialInfo, owner, toSearchFor);
|
||||
dialog.show();
|
||||
if (!dialog.isOK()) return null;
|
||||
|
||||
return dialog.getHelper();
|
||||
}
|
||||
|
||||
|
||||
private void findScope(@NotNull PsiElement place,
|
||||
@NotNull final Editor editor,
|
||||
@NotNull PairFunction<GrParametersOwner, PsiElement, Object> callback) {
|
||||
final List<GrParametersOwner> scopes = new ArrayList<GrParametersOwner>();
|
||||
while (true) {
|
||||
final GrParametersOwner parent = PsiTreeUtil.getParentOfType(place, GrMethod.class, GrClosableBlock.class);
|
||||
if (parent == null) break;
|
||||
scopes.add(parent);
|
||||
place = parent;
|
||||
}
|
||||
|
||||
if (scopes.size() == 0) {
|
||||
throw new ExtractException(GroovyRefactoringBundle.message("there.is.no.method.or.closure"));
|
||||
}
|
||||
else if (scopes.size() == 1) {
|
||||
final GrParametersOwner owner = scopes.get(0);
|
||||
if (owner instanceof GrMethod) {
|
||||
PsiMethod newMethod = SuperMethodWarningUtil.checkSuperMethod((PsiMethod)owner, RefactoringBundle.message("to.refactor"));
|
||||
if (newMethod == null) return;
|
||||
callback.fun(owner, newMethod);
|
||||
}
|
||||
else {
|
||||
callback.fun(owner, MethodOrClosureScopeChooser.findVariableToUse(owner));
|
||||
}
|
||||
}
|
||||
else {
|
||||
myPopup = MethodOrClosureScopeChooser.create(scopes, editor, this, callback);
|
||||
myPopup.showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void performRefactoring(@NotNull final InitialInfo info,
|
||||
@NotNull GrMemberOwner owner,
|
||||
GrStatementOwner declarationOwner,
|
||||
final Editor editor,
|
||||
PsiElement startElement) {
|
||||
findScope(startElement, editor, new PairFunction<GrParametersOwner, PsiElement, Object>() {
|
||||
@Override
|
||||
public Object fun(GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
final ExtractClosureHelper helper = getSettings(info, owner, toSearchFor);
|
||||
if (helper == null) return null;
|
||||
|
||||
if (helper.getOwner() instanceof GrMethod) {
|
||||
new ExtractClosureFromMethodProcessor(helper, editor).run();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public JBPopup get() {
|
||||
return myPopup;
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiType;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureHelper extends ExtractInfoHelperBase implements ExtractInfoHelper, GrIntroduceParameterSettings {
|
||||
|
||||
private final GrParametersOwner myOwner;
|
||||
private final PsiElement myToSearchFor;
|
||||
|
||||
private String myName;
|
||||
private boolean myFinal;
|
||||
private TIntArrayList toRemove;
|
||||
private boolean myGenerateDelegate;
|
||||
|
||||
public ExtractClosureHelper(InitialInfo info, GrParametersOwner owner, PsiElement toSearchFor, String name, boolean declareFinal) {
|
||||
super(info);
|
||||
myOwner = owner;
|
||||
myToSearchFor = toSearchFor;
|
||||
myName = name;
|
||||
myFinal = declareFinal;
|
||||
}
|
||||
|
||||
public GrParametersOwner getOwner() {
|
||||
return myOwner;
|
||||
}
|
||||
|
||||
public PsiElement getToSearchFor() {
|
||||
return myToSearchFor;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public boolean declareFinal() {
|
||||
return myFinal;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public void setDeclareFinal(boolean aFinal) {
|
||||
myFinal = aFinal;
|
||||
}
|
||||
|
||||
public void setToRemove(TIntArrayList toRemove) {
|
||||
this.toRemove = toRemove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIntArrayList parametersToRemove() {
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceFieldsWithGetters() {
|
||||
return 0;//todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLocalVariable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAllOccurrences() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return JavaPsiFacade.getElementFactory(getProject()).createTypeFromText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, myOwner);
|
||||
}
|
||||
|
||||
public boolean generateDelegate() {
|
||||
return myGenerateDelegate;
|
||||
}
|
||||
|
||||
public void setGenerateDelegate(boolean generateDelegate) {
|
||||
myGenerateDelegate = generateDelegate;
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcessor {
|
||||
protected final ExtractClosureHelper myHelper;
|
||||
|
||||
public ExtractClosureProcessorBase(@NotNull ExtractClosureHelper helper) {
|
||||
super(helper.getProject());
|
||||
myHelper = helper;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
|
||||
return new UsageViewDescriptorAdapter() {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getElements() {
|
||||
return new PsiElement[]{myHelper.getToSearchFor()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProcessedElementsHeader() {
|
||||
return ExtractClosureHandler.EXTRACT_CLOSURE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return ExtractClosureHandler.EXTRACT_CLOSURE;
|
||||
}
|
||||
|
||||
protected GrClosableBlock generateClosure() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
buffer.append('{');
|
||||
for (String p : ExtractUtil.getParameterString(myHelper, true)) {
|
||||
buffer.append(p);
|
||||
}
|
||||
buffer.append("->\n");
|
||||
|
||||
ExtractUtil.generateBody(myHelper, false, buffer);
|
||||
buffer.append('}');
|
||||
|
||||
return GroovyPsiElementFactory.getInstance(myHelper.getProject()).createClosureFromText(buffer.toString(), myHelper.getOwner());
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class OtherLanguageUsageInfo extends UsageInfo {
|
||||
public OtherLanguageUsageInfo(@NotNull PsiReference reference) {
|
||||
super(reference);
|
||||
}
|
||||
}
|
||||
+26
-3
@@ -16,9 +16,14 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.refactoring.extract.method;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
|
||||
/**
|
||||
@@ -30,14 +35,16 @@ public class ExtractMethodInfoHelper extends ExtractInfoHelperBase {
|
||||
private boolean mySpecifyType = true;
|
||||
private String myVisibility;
|
||||
private String myName;
|
||||
private final GrMemberOwner myOwner;
|
||||
|
||||
public ExtractMethodInfoHelper(InitialInfo initialInfo, String name) {
|
||||
public ExtractMethodInfoHelper(InitialInfo initialInfo, String name, GrMemberOwner owner) {
|
||||
super(initialInfo);
|
||||
myOwner = owner;
|
||||
|
||||
myVisibility = PsiModifier.PRIVATE;
|
||||
myName = name;
|
||||
|
||||
myIsStatic = ExtractUtil.canBeStatic(initialInfo.getStatements()[0]);
|
||||
myIsStatic = canBeStatic(initialInfo.getStatements()[0]);
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
@@ -67,4 +74,20 @@ public class ExtractMethodInfoHelper extends ExtractInfoHelperBase {
|
||||
public void setName(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GrMemberOwner getOwner() {
|
||||
return myOwner;
|
||||
}
|
||||
|
||||
private static boolean canBeStatic(GrStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
while (parent != null && !(parent instanceof PsiFile)) {
|
||||
if (parent instanceof GrMethod) {
|
||||
return ((GrMethod) parent).hasModifierProperty(PsiModifier.STATIC);
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+56
-4
@@ -22,19 +22,30 @@ import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.ui.ComboBoxVisibilityPanel;
|
||||
import com.intellij.refactoring.ui.ConflictsDialog;
|
||||
import com.intellij.refactoring.ui.MethodSignatureComponent;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
import org.jetbrains.plugins.groovy.intentions.utils.DuplicatesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel;
|
||||
@@ -51,7 +62,10 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -71,10 +85,10 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
|
||||
private ParameterTablePanel myParameterTablePanel;
|
||||
private final Project myProject;
|
||||
|
||||
public GroovyExtractMethodDialog(InitialInfo info) {
|
||||
public GroovyExtractMethodDialog(InitialInfo info, GrMemberOwner owner) {
|
||||
super(info.getProject(), true);
|
||||
myProject = info.getProject();
|
||||
myHelper = new ExtractMethodInfoHelper(info, "");
|
||||
myHelper = new ExtractMethodInfoHelper(info, "", owner);
|
||||
|
||||
setUpNameField();
|
||||
myParameterTablePanel.init(myHelper);
|
||||
@@ -98,8 +112,8 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
|
||||
protected void doOKAction() {
|
||||
String name = getEnteredName();
|
||||
if (name == null) return;
|
||||
GrMethod method = ExtractUtil.createMethodByHelper(name, myHelper);
|
||||
if (method != null && !ExtractUtil.validateMethod(method, myHelper)) {
|
||||
GrMethod method = ExtractUtil.createMethod(myHelper);
|
||||
if (method != null && !validateMethod(method, myHelper)) {
|
||||
return;
|
||||
}
|
||||
if (myCbSpecifyType.isEnabled()) {
|
||||
@@ -232,6 +246,44 @@ public class GroovyExtractMethodDialog extends DialogWrapper {
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean validateMethod(GrMethod method, ExtractMethodInfoHelper helper) {
|
||||
ArrayList<String> conflicts = new ArrayList<String>();
|
||||
GrMemberOwner owner = helper.getOwner();
|
||||
PsiMethod[] methods = ArrayUtil.mergeArrays(owner.getAllMethods(), new PsiMethod[]{method}, PsiMethod.ARRAY_FACTORY);
|
||||
final Map<PsiMethod, List<PsiMethod>> map = DuplicatesUtil.factorDuplicates(methods, new TObjectHashingStrategy<PsiMethod>() {
|
||||
public int computeHashCode(PsiMethod method) {
|
||||
return method.getSignature(PsiSubstitutor.EMPTY).hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(PsiMethod method1, PsiMethod method2) {
|
||||
return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
|
||||
}
|
||||
});
|
||||
|
||||
List<PsiMethod> list = map.get(method);
|
||||
if (list == null) return true;
|
||||
for (PsiMethod psiMethod : list) {
|
||||
if (psiMethod != method) {
|
||||
PsiClass containingClass = psiMethod.getContainingClass();
|
||||
if (containingClass == null) return true;
|
||||
String message = containingClass instanceof GroovyScriptClass ?
|
||||
GroovyRefactoringBundle.message("method.is.already.defined.in.script", GroovyRefactoringUtil.getMethodSignature(method),
|
||||
CommonRefactoringUtil.htmlEmphasize(containingClass.getQualifiedName())) :
|
||||
GroovyRefactoringBundle.message("method.is.already.defined.in.class", GroovyRefactoringUtil.getMethodSignature(method),
|
||||
CommonRefactoringUtil.htmlEmphasize(containingClass.getQualifiedName()));
|
||||
conflicts.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
return conflicts.size() <= 0 || reportConflicts(conflicts, helper.getProject());
|
||||
}
|
||||
|
||||
private static boolean reportConflicts(final ArrayList<String> conflicts, final Project project) {
|
||||
ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts);
|
||||
conflictsDialog.show();
|
||||
return conflictsDialog.isOK();
|
||||
}
|
||||
|
||||
class DataChangedListener implements EventListener {
|
||||
void dataChanged() {
|
||||
update();
|
||||
|
||||
+93
-62
@@ -17,9 +17,9 @@
|
||||
package org.jetbrains.plugins.groovy.refactoring.extract.method;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
@@ -29,27 +29,29 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractException;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractHandlerBase;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GroovyExtractMethodHandler extends ExtractHandlerBase<ExtractMethodInfoHelper> implements RefactoringActionHandler {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GroovyExtractMethodHandler.class);
|
||||
public class GroovyExtractMethodHandler extends ExtractHandlerBase implements RefactoringActionHandler {
|
||||
protected static String REFACTORING_NAME = GroovyRefactoringBundle.message("extract.method.title");
|
||||
private String myInvokeResult = "ok";
|
||||
|
||||
@@ -73,85 +75,60 @@ public class GroovyExtractMethodHandler extends ExtractHandlerBase<ExtractMethod
|
||||
}
|
||||
}
|
||||
|
||||
public void performRefactoring(@NotNull final ExtractMethodInfoHelper helper,
|
||||
public void performRefactoring(@NotNull final InitialInfo initialInfo,
|
||||
@NotNull final GrMemberOwner owner,
|
||||
final GrStatementOwner declarationOwner,
|
||||
final Editor editor,
|
||||
final PsiElement startElement) {
|
||||
final ExtractMethodInfoHelper helper = getSettings(initialInfo, owner);
|
||||
if (helper == null) return;
|
||||
|
||||
final String methodName = helper.getName();
|
||||
final GrMethod method = ExtractUtil.createMethodByHelper(methodName, helper);
|
||||
final Runnable runnable = new Runnable() {
|
||||
CommandProcessor.getInstance().executeCommand(helper.getProject(), new Runnable() {
|
||||
public void run() {
|
||||
final AccessToken lock = ApplicationManager.getApplication().acquireWriteActionLock(GroovyExtractMethodHandler.class);
|
||||
try {
|
||||
PsiElement anchor = ExtractUtil.calculateAnchorToInsertBefore(owner, startElement);
|
||||
GrMethod newMethod = owner.addMemberDeclaration(method, anchor);
|
||||
ExtractUtil.renameParameterOccurrences(newMethod, helper);
|
||||
GrReferenceAdjuster.shortenReferences(newMethod);
|
||||
GrStatement realStatement;
|
||||
|
||||
if (declarationOwner != null && !ExtractUtil.isSingleExpression(helper.getStatements())) {
|
||||
// Replace set of statements
|
||||
final GrStatement[] newStatement = ExtractUtil.createResultStatement(helper, methodName);
|
||||
// add call statement
|
||||
final GrStatement[] statements = helper.getStatements();
|
||||
assert statements.length > 0;
|
||||
realStatement = null;
|
||||
for (GrStatement statement : newStatement) {
|
||||
realStatement = declarationOwner.addStatementBefore(statement, statements[0]);
|
||||
}
|
||||
assert realStatement != null;
|
||||
// remove old statements
|
||||
ExtractUtil.removeOldStatements(declarationOwner, helper);
|
||||
PsiImplUtil.removeNewLineAfter(realStatement);
|
||||
}
|
||||
else {
|
||||
// Expression call replace
|
||||
GrExpression methodCall = ExtractUtil.createMethodCallByHelper(methodName, helper);
|
||||
GrExpression oldExpr = (GrExpression)helper.getStatements()[0];
|
||||
realStatement = oldExpr.replaceWithExpression(methodCall, true);
|
||||
}
|
||||
GrReferenceAdjuster.shortenReferences(realStatement);
|
||||
|
||||
PsiElement prev = newMethod.getPrevSibling();
|
||||
IElementType elementType = prev.getNode().getElementType();
|
||||
if (!TokenSets.WHITE_SPACES_SET.contains(elementType) || !prev.getText().contains("\n")) {
|
||||
newMethod.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", newMethod.getNode());
|
||||
}
|
||||
createMethod(helper, owner, startElement);
|
||||
GrStatement realStatement = ExtractUtil.replaceStatement(declarationOwner, helper);
|
||||
|
||||
// move to offset
|
||||
if (editor != null) {
|
||||
PsiDocumentManager.getInstance(helper.getProject()).commitDocument(editor.getDocument());
|
||||
editor.getSelectionModel().removeSelection();
|
||||
editor.getCaretModel().moveToOffset(ExtractUtil.getCaretOffset(realStatement));
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
finally {
|
||||
lock.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Project project = helper.getProject();
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
}, REFACTORING_NAME, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractMethodInfoHelper getSettings(@NotNull InitialInfo initialInfo) {
|
||||
private static void createMethod(ExtractMethodInfoHelper helper, GrMemberOwner owner, PsiElement startElement) {
|
||||
final GrMethod method = ExtractUtil.createMethod(helper);
|
||||
PsiElement anchor = calculateAnchorToInsertBefore(owner, startElement);
|
||||
GrMethod newMethod = owner.addMemberDeclaration(method, anchor);
|
||||
renameParameterOccurrences(newMethod, helper);
|
||||
GrReferenceAdjuster.shortenReferences(newMethod);
|
||||
PsiElement prev = newMethod.getPrevSibling();
|
||||
IElementType elementType = prev.getNode().getElementType();
|
||||
if (!TokenSets.WHITE_SPACES_SET.contains(elementType) || !prev.getText().contains("\n")) {
|
||||
newMethod.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", newMethod.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ExtractMethodInfoHelper getSettings(@NotNull InitialInfo initialInfo, GrMemberOwner owner) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(initialInfo, "testMethod");
|
||||
final ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(initialInfo, "testMethod", owner);
|
||||
final PsiType type = helper.getOutputType();
|
||||
if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || type.equalsToText("void")) {
|
||||
if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || PsiType.VOID.equals(type)) {
|
||||
helper.setSpecifyType(false);
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
GroovyExtractMethodDialog dialog = new GroovyExtractMethodDialog(initialInfo);
|
||||
GroovyExtractMethodDialog dialog = new GroovyExtractMethodDialog(initialInfo, owner);
|
||||
dialog.show();
|
||||
if (!dialog.isOK()) return null;
|
||||
|
||||
@@ -166,4 +143,58 @@ public class GroovyExtractMethodHandler extends ExtractHandlerBase<ExtractMethod
|
||||
public String getInvokeResult() {
|
||||
return myInvokeResult;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement calculateAnchorToInsertBefore(GrMemberOwner owner, PsiElement startElement) {
|
||||
while (startElement != null && !isEnclosingDefinition(owner, startElement)) {
|
||||
if (startElement.getParent() instanceof GroovyFile) {
|
||||
return startElement.getNextSibling();
|
||||
}
|
||||
startElement = startElement.getParent();
|
||||
PsiElement parent = startElement.getParent();
|
||||
if (parent instanceof GroovyFile && ((GroovyFile) parent).getScriptClass() == owner) {
|
||||
return startElement.getNextSibling();
|
||||
}
|
||||
}
|
||||
return startElement == null ? null : startElement.getNextSibling();
|
||||
}
|
||||
|
||||
private static boolean isEnclosingDefinition(GrMemberOwner owner, PsiElement startElement) {
|
||||
if (owner instanceof GrTypeDefinition) {
|
||||
GrTypeDefinition definition = (GrTypeDefinition) owner;
|
||||
return startElement.getParent() == definition.getBody();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void renameParameterOccurrences(GrMethod method, ExtractMethodInfoHelper helper) throws IncorrectOperationException {
|
||||
GrOpenBlock block = method.getBlock();
|
||||
if (block == null) return;
|
||||
GrStatement[] statements = block.getStatements();
|
||||
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject());
|
||||
for (ParameterInfo info : helper.getParameterInfos()) {
|
||||
final String oldName = info.getOldName();
|
||||
final String newName = info.getName();
|
||||
final ArrayList<GrExpression> result = new ArrayList<GrExpression>();
|
||||
if (!oldName.equals(newName)) {
|
||||
for (final GrStatement statement : statements) {
|
||||
statement.accept(new PsiRecursiveElementVisitor() {
|
||||
public void visitElement(final PsiElement element) {
|
||||
super.visitElement(element);
|
||||
if (element instanceof GrReferenceExpression) {
|
||||
GrReferenceExpression expr = (GrReferenceExpression) element;
|
||||
if (!expr.isQualified() && oldName.equals(expr.getName())) {
|
||||
result.add(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (GrExpression expr : result) {
|
||||
expr.replaceWithExpression(factory.createExpressionFromText(newName), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,9 +1,12 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -34,7 +37,7 @@ public class GrIntroduceContext {
|
||||
|
||||
public GrIntroduceContext(Project project,
|
||||
Editor editor,
|
||||
GrExpression expression,
|
||||
@Nullable GrExpression expression,
|
||||
PsiElement[] occurrences,
|
||||
PsiElement scope,
|
||||
@Nullable GrVariable var) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSuperR
|
||||
/**
|
||||
* @author Medvedev Max
|
||||
*/
|
||||
class AnySupers extends GroovyRecursiveElementVisitor {
|
||||
public class AnySupers extends GroovyRecursiveElementVisitor {
|
||||
boolean myContainsSupers = false;
|
||||
|
||||
@Override
|
||||
@@ -30,7 +30,7 @@ class AnySupers extends GroovyRecursiveElementVisitor {
|
||||
myContainsSupers = true;
|
||||
}
|
||||
|
||||
boolean isResult() {
|
||||
public boolean isResult() {
|
||||
return myContainsSupers;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-133
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -29,8 +29,6 @@ import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.introduceParameter.*;
|
||||
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.ConflictsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo;
|
||||
import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
@@ -38,23 +36,14 @@ import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TIntProcedure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
@@ -99,7 +88,10 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
|
||||
if (!mySettings.generateDelegate()) {
|
||||
detectAccessibilityConflicts(usagesIn, conflicts);
|
||||
GroovyIntroduceParameterUtil.detectAccessibilityConflicts(myContext.expression, usagesIn, conflicts,
|
||||
mySettings.replaceFieldsWithGetters() != IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE,
|
||||
myProject
|
||||
);
|
||||
}
|
||||
|
||||
final GrMethod toReplaceIn = (GrMethod)myContext.toReplaceIn;
|
||||
@@ -127,41 +119,6 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
return showConflicts(conflicts, usagesIn);
|
||||
}
|
||||
|
||||
private void detectAccessibilityConflicts(final UsageInfo[] usageArray, MultiMap<PsiElement, String> conflicts) {
|
||||
if (myContext.expression == null) return;
|
||||
|
||||
final ReferencedElementsCollector collector = new ReferencedElementsCollector();
|
||||
myContext.expression.accept(collector);
|
||||
final List<PsiElement> result = collector.getResult();
|
||||
if (result.isEmpty()) return;
|
||||
|
||||
for (final UsageInfo usageInfo : usageArray) {
|
||||
if (!(usageInfo instanceof ExternalUsageInfo) || !IntroduceParameterUtil.isMethodUsage(usageInfo)) continue;
|
||||
|
||||
final PsiElement place = usageInfo.getElement();
|
||||
for (PsiElement element : result) {
|
||||
if (element instanceof PsiField &&
|
||||
mySettings.replaceFieldsWithGetters() != IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE) {
|
||||
//check getter access instead
|
||||
final PsiClass psiClass = ((PsiField)element).getContainingClass();
|
||||
LOG.assertTrue(psiClass != null);
|
||||
final PsiMethod method = GroovyPropertyUtils.findGetterForField((PsiField)element);
|
||||
if (method != null) {
|
||||
element = method;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiMember &&
|
||||
!JavaPsiFacade.getInstance(myProject).getResolveHelper().isAccessible((PsiMember)element, place, null)) {
|
||||
String message = RefactoringBundle.message(
|
||||
"0.is.not.accessible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect",
|
||||
RefactoringUIUtil.getDescription(element, true),
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(place), true));
|
||||
conflicts.putValue(element, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
@@ -220,7 +177,7 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
|
||||
PsiType initializerType = mySettings.getSelectedType();
|
||||
|
||||
// Changing external occurences (the tricky part)
|
||||
// Changing external occurrences (the tricky part)
|
||||
|
||||
IntroduceParameterUtil.processUsages(usages, this);
|
||||
|
||||
@@ -229,9 +186,9 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
|
||||
final boolean methodsToProcessAreDifferent = toReplaceIn != toSearchFor;
|
||||
if (mySettings.generateDelegate()) {
|
||||
generateDelegate(toReplaceIn);
|
||||
GroovyIntroduceParameterUtil.generateDelegate(toReplaceIn, myParameterInitializer, myProject);
|
||||
if (methodsToProcessAreDifferent) {
|
||||
final GrMethod method = generateDelegate(toSearchFor);
|
||||
final GrMethod method = GroovyIntroduceParameterUtil.generateDelegate(toSearchFor, myParameterInitializer, myProject);
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && containingClass.isInterface()) {
|
||||
final GrOpenBlock block = method.getBlock();
|
||||
@@ -255,12 +212,12 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
|
||||
if (myContext.var != null) myContext.var.delete();
|
||||
|
||||
// Replacing expression occurences
|
||||
// Replacing expression occurrences
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof ChangedMethodCallInfo) {
|
||||
PsiElement element = usage.getElement();
|
||||
|
||||
processChangedMethodCall(element);
|
||||
GroovyIntroduceParameterUtil.processChangedMethodCall(element, mySettings, myProject);
|
||||
}
|
||||
else if (usage instanceof InternalUsageInfo) {
|
||||
PsiElement element = usage.getElement();
|
||||
@@ -281,86 +238,6 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl
|
||||
fieldConflictsResolver.fix();
|
||||
}
|
||||
|
||||
private GrMethod generateDelegate(PsiMethod prototype) {
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
|
||||
GrMethod result;
|
||||
if (prototype instanceof GrMethod) {
|
||||
result = (GrMethod)prototype.copy();
|
||||
}
|
||||
else {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(prototype.getModifierList().getText()).append(' ');
|
||||
|
||||
if (prototype.getReturnTypeElement() != null ) {
|
||||
builder.append(prototype.getReturnTypeElement().getText());
|
||||
}
|
||||
builder.append(' ').append(prototype.getName());
|
||||
builder.append(prototype.getParameterList().getText());
|
||||
builder.append("{}");
|
||||
result = factory.createMethodFromText(builder.toString());
|
||||
}
|
||||
|
||||
StringBuilder call = new StringBuilder();
|
||||
call.append("def foo(){\n").append(prototype.getName()).append('(');
|
||||
final GrParameter[] parameters = result.getParameters();
|
||||
for (GrParameter parameter : parameters) {
|
||||
call.append(parameter.getName()).append(", ");
|
||||
}
|
||||
call.append(myParameterInitializer.getText());
|
||||
call.append(");\n}");
|
||||
final GrOpenBlock block = factory.createMethodFromText(call.toString()).getBlock();
|
||||
|
||||
result.getBlock().replace(block);
|
||||
final PsiElement parent = prototype.getParent();
|
||||
return (GrMethod)parent.addBefore(result, prototype);
|
||||
}
|
||||
|
||||
private void processChangedMethodCall(PsiElement element) {
|
||||
if (element.getParent() instanceof GrMethodCallExpression) {
|
||||
GrMethodCallExpression methodCall = (GrMethodCallExpression)element.getParent();
|
||||
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
GrExpression expression = factory.createExpressionFromText(mySettings.getName(), null);
|
||||
final GrArgumentList argList = methodCall.getArgumentList();
|
||||
final PsiElement[] exprs = argList.getAllArguments();
|
||||
|
||||
if (exprs.length > 0) {
|
||||
argList.addAfter(expression, exprs[exprs.length - 1]);
|
||||
}
|
||||
else {
|
||||
argList.add(expression);
|
||||
}
|
||||
|
||||
removeParametersFromCall(methodCall, argList);
|
||||
|
||||
}
|
||||
else {
|
||||
LOG.error(element.getParent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeParametersFromCall(GrMethodCallExpression methodCall, GrArgumentList argList) {
|
||||
final GroovyResolveResult resolveResult = methodCall.advancedResolve();
|
||||
final PsiElement resolved = resolveResult.getElement();
|
||||
LOG.assertTrue(resolved instanceof PsiMethod);
|
||||
final GrClosureSignature signature = GrClosureSignatureUtil.createSignature((PsiMethod)resolved, resolveResult.getSubstitutor());
|
||||
final GrClosureSignatureUtil.ArgInfo<PsiElement>[] argInfos =
|
||||
GrClosureSignatureUtil.mapParametersToArguments(signature, argList, methodCall, methodCall.getClosureArguments());
|
||||
LOG.assertTrue(argInfos != null);
|
||||
mySettings.parametersToRemove().forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int value) {
|
||||
final List<PsiElement> args = argInfos[value].args;
|
||||
for (PsiElement arg : args) {
|
||||
arg.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommandName() {
|
||||
return RefactoringBundle.message("introduce.parameter.command", UsageViewUtil.getDescriptiveName(myContext.toReplaceIn));
|
||||
|
||||
+156
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,26 +16,44 @@
|
||||
package org.jetbrains.plugins.groovy.refactoring.introduce.parameter;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.introduceParameter.ExternalUsageInfo;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterData;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterUtil;
|
||||
import com.intellij.refactoring.util.ConflictsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TIntProcedure;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
|
||||
@@ -156,6 +174,143 @@ public class GroovyIntroduceParameterUtil {
|
||||
});
|
||||
}
|
||||
|
||||
public static void detectAccessibilityConflicts(@Nullable GroovyPsiElement elementToProcess,
|
||||
final UsageInfo[] usages,
|
||||
MultiMap<PsiElement, String> conflicts,
|
||||
boolean replaceFieldsWithGetters,
|
||||
Project project) {
|
||||
if (elementToProcess == null) return;
|
||||
|
||||
final ReferencedElementsCollector collector = new ReferencedElementsCollector();
|
||||
elementToProcess.accept(collector);
|
||||
final List<PsiElement> result = collector.getResult();
|
||||
if (result.isEmpty()) return;
|
||||
|
||||
for (final UsageInfo usageInfo : usages) {
|
||||
if (!(usageInfo instanceof ExternalUsageInfo) || !IntroduceParameterUtil.isMethodUsage(usageInfo)) continue;
|
||||
|
||||
final PsiElement place = usageInfo.getElement();
|
||||
for (PsiElement element : result) {
|
||||
if (element instanceof PsiField && replaceFieldsWithGetters) {
|
||||
//check getter access instead
|
||||
final PsiClass psiClass = ((PsiField)element).getContainingClass();
|
||||
LOG.assertTrue(psiClass != null);
|
||||
final PsiMethod method = GroovyPropertyUtils.findGetterForField((PsiField)element);
|
||||
if (method != null) {
|
||||
element = method;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiMember &&
|
||||
!JavaPsiFacade.getInstance(project).getResolveHelper().isAccessible((PsiMember)element, place, null)) {
|
||||
String message = RefactoringBundle.message(
|
||||
"0.is.not.accessible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect",
|
||||
RefactoringUIUtil.getDescription(element, true),
|
||||
RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(place), true));
|
||||
conflicts.putValue(element, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void processChangedMethodCall(PsiElement element, GrIntroduceParameterSettings settings, Project project) {
|
||||
if (!(element.getParent() instanceof GrMethodCallExpression)) {
|
||||
LOG.error(element.getParent());
|
||||
return;
|
||||
}
|
||||
|
||||
GrMethodCallExpression methodCall = (GrMethodCallExpression)element.getParent();
|
||||
|
||||
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
|
||||
final String name = settings.getName();
|
||||
LOG.assertTrue(name != null);
|
||||
GrExpression expression = factory.createExpressionFromText(name, null);
|
||||
final GrArgumentList argList = methodCall.getArgumentList();
|
||||
final PsiElement[] exprs = argList.getAllArguments();
|
||||
|
||||
if (exprs.length > 0) {
|
||||
argList.addAfter(expression, exprs[exprs.length - 1]);
|
||||
}
|
||||
else {
|
||||
argList.add(expression);
|
||||
}
|
||||
|
||||
removeParametersFromCall(methodCall, argList, settings);
|
||||
}
|
||||
|
||||
private static void removeParametersFromCall(GrMethodCallExpression methodCall,
|
||||
GrArgumentList argList,
|
||||
GrIntroduceParameterSettings settings) {
|
||||
final GroovyResolveResult resolveResult = methodCall.advancedResolve();
|
||||
final PsiElement resolved = resolveResult.getElement();
|
||||
LOG.assertTrue(resolved instanceof PsiMethod);
|
||||
final GrClosureSignature signature = GrClosureSignatureUtil.createSignature((PsiMethod)resolved, resolveResult.getSubstitutor());
|
||||
final GrClosureSignatureUtil.ArgInfo<PsiElement>[] argInfos =
|
||||
GrClosureSignatureUtil.mapParametersToArguments(signature, argList, methodCall, methodCall.getClosureArguments());
|
||||
LOG.assertTrue(argInfos != null);
|
||||
settings.parametersToRemove().forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int value) {
|
||||
final List<PsiElement> args = argInfos[value].args;
|
||||
for (PsiElement arg : args) {
|
||||
arg.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static GrMethod generateDelegate(PsiMethod prototype, IntroduceParameterData.ExpressionWrapper initializer, Project project) {
|
||||
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
|
||||
|
||||
GrMethod result;
|
||||
if (prototype instanceof GrMethod) {
|
||||
result = (GrMethod)prototype.copy();
|
||||
}
|
||||
else {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(prototype.getModifierList().getText()).append(' ');
|
||||
|
||||
if (prototype.getReturnTypeElement() != null ) {
|
||||
builder.append(prototype.getReturnTypeElement().getText());
|
||||
}
|
||||
builder.append(' ').append(prototype.getName());
|
||||
builder.append(prototype.getParameterList().getText());
|
||||
builder.append("{}");
|
||||
result = factory.createMethodFromText(builder.toString());
|
||||
}
|
||||
|
||||
StringBuilder call = new StringBuilder();
|
||||
call.append("def foo(){\n");
|
||||
final GrParameter[] parameters = result.getParameters();
|
||||
call.append(prototype.getName());
|
||||
if (initializer.getExpression() instanceof GrClosableBlock) {
|
||||
if (parameters.length > 0) {
|
||||
call.append('(');
|
||||
for (GrParameter parameter : parameters) {
|
||||
call.append(parameter.getName()).append(", ");
|
||||
}
|
||||
call.replace(call.length()-2, call.length(), ")");
|
||||
}
|
||||
call.append(initializer.getText());
|
||||
}
|
||||
else {
|
||||
call.append('(');
|
||||
for (GrParameter parameter : parameters) {
|
||||
call.append(parameter.getName()).append(", ");
|
||||
}
|
||||
call.append(initializer.getText());
|
||||
call.append(")");
|
||||
}
|
||||
call.append("\n}");
|
||||
final GrOpenBlock block = factory.createMethodFromText(call.toString()).getBlock();
|
||||
|
||||
result.getBlock().replace(block);
|
||||
final PsiElement parent = prototype.getParent();
|
||||
final GrMethod method = (GrMethod)parent.addBefore(result, prototype);
|
||||
GrReferenceAdjuster.shortenReferences(method);
|
||||
return method;
|
||||
}
|
||||
|
||||
private static class FieldSearcher extends GroovyRecursiveElementVisitor {
|
||||
PsiClass myClass;
|
||||
private final List<PsiField> result = new ArrayList<PsiField>();
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -52,8 +52,7 @@ import static com.intellij.codeInsight.ChangeContextUtil.*;
|
||||
*/
|
||||
|
||||
public class OldReferencesResolver {
|
||||
private static final Logger LOG =
|
||||
Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.OldReferencesResolver");
|
||||
private static final Logger LOG = Logger.getInstance(OldReferencesResolver.class);
|
||||
|
||||
private final GrCall myContext;
|
||||
private final GrExpression myExpr;
|
||||
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.plugins.groovy.refactoring.extract.closure;
|
||||
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import gnu.trove.TIntArrayList
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner
|
||||
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class ExtractClosureTest extends LightGroovyTestCase {
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "${TestUtils.testDataPath}groovy/refactoring/extractMethod/";
|
||||
}
|
||||
|
||||
|
||||
private void doTest(String before, String after) {
|
||||
doTest(before, after, [], [])
|
||||
}
|
||||
|
||||
private void doTest(String before, String after, List<Integer> toRemove, List<Integer> notToUseAsParams) {
|
||||
myFixture.configureByText 'a.groovy', before
|
||||
def model = myFixture.editor.selectionModel
|
||||
def handler = new ExtractClosureHandler() {
|
||||
@Override
|
||||
protected ExtractClosureHelper getSettings(@NotNull InitialInfo initialInfo, GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
def settings = new ExtractClosureHelper(initialInfo, owner, toSearchFor, "closure", true)
|
||||
settings.setDeclareFinal(false)
|
||||
settings.setGenerateDelegate(false)
|
||||
settings.setName("closure")
|
||||
settings.setToRemove(new TIntArrayList(toRemove as int[]))
|
||||
|
||||
def infos = settings.parameterInfos
|
||||
for (int i: notToUseAsParams) {
|
||||
infos[i].setPassAsParameter(false)
|
||||
}
|
||||
return settings
|
||||
}
|
||||
}
|
||||
|
||||
handler.invoke myFixture.project, myFixture.editor, myFixture.file, model.selectionStart, model.selectionEnd
|
||||
myFixture.checkResult after
|
||||
}
|
||||
|
||||
|
||||
void testSimple() {
|
||||
doTest('''
|
||||
def foo(String s) {
|
||||
s+=2
|
||||
<selection>print s</selection>
|
||||
}
|
||||
|
||||
foo('a')
|
||||
''', '''
|
||||
def foo(String s, Closure closure) {
|
||||
s+=2
|
||||
<selection>closure(s)</selection>
|
||||
}
|
||||
|
||||
foo('a') {String s ->
|
||||
print s
|
||||
}
|
||||
''')
|
||||
}
|
||||
|
||||
void testRemoveUnused() {
|
||||
doTest('''
|
||||
class X {
|
||||
def foo(String s) {
|
||||
<selection>print s</selection>
|
||||
}
|
||||
}
|
||||
|
||||
new X().foo('a')
|
||||
''', '''
|
||||
class X {
|
||||
def foo(Closure closure) {
|
||||
<selection>closure()</selection>
|
||||
}
|
||||
}
|
||||
|
||||
new X().foo {->
|
||||
print 'a'
|
||||
}
|
||||
''', [0], [0])
|
||||
|
||||
}
|
||||
|
||||
void testRemoveUnusedAndGenerateLocal() {
|
||||
doTest('''
|
||||
def foo(String s) {
|
||||
<selection>s+=2
|
||||
print s</selection>
|
||||
}
|
||||
|
||||
foo('a')
|
||||
''', '''
|
||||
def foo(Closure closure) {
|
||||
closure()
|
||||
}
|
||||
|
||||
foo {->
|
||||
String s = 'a'
|
||||
s += 2
|
||||
print s
|
||||
}
|
||||
''', [0], [0])
|
||||
|
||||
}
|
||||
|
||||
void testInsertQualifier() {
|
||||
doTest('''
|
||||
class X {
|
||||
def foo(String s) {
|
||||
<selection>bar()</selection>
|
||||
}
|
||||
def bar(){}
|
||||
}
|
||||
|
||||
new X().foo('a')
|
||||
''', '''
|
||||
class X {
|
||||
def foo(Closure closure) {
|
||||
<selection>closure()</selection>
|
||||
}
|
||||
def bar(){}
|
||||
}
|
||||
|
||||
final X x = new X()
|
||||
x.foo {->
|
||||
x.bar()
|
||||
}
|
||||
''', [0], [])
|
||||
|
||||
}
|
||||
}
|
||||
+1
@@ -106,5 +106,6 @@ public class ExtractMethodTest extends LightGroovyTestCase {
|
||||
public void testAOOBE() {doTest();}
|
||||
|
||||
public void testWildCardReturnType() {doTest();}
|
||||
public void testParamChangedInsideExtractedMethod() {doTest();}
|
||||
|
||||
}
|
||||
+1
@@ -333,4 +333,5 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testClosureArg() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false);}
|
||||
public void testClosureArgWithEmptyArgList() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false);}
|
||||
|
||||
public void testScriptMethod() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false);}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ def i = 6
|
||||
i = testMethod()
|
||||
|
||||
private int testMethod() {
|
||||
int i
|
||||
def i
|
||||
while (true) {
|
||||
println "preved"
|
||||
i = 42
|
||||
|
||||
@@ -11,7 +11,7 @@ protected static def getGeneratedFileNames(String name, int boo) {
|
||||
}
|
||||
|
||||
private static ArrayList<String> testMethod() {
|
||||
ArrayList<String> names
|
||||
def names
|
||||
names = new ArrayList<String>()
|
||||
return names
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
def foo(String s){
|
||||
<begin>s = 'a'
|
||||
print s<end>
|
||||
}
|
||||
-----
|
||||
def foo(String s){
|
||||
testMethod()
|
||||
}
|
||||
|
||||
private testMethod() {
|
||||
String s
|
||||
s = 'a'
|
||||
print s
|
||||
}
|
||||
plugins/groovy/testdata/refactoring/introduceParameterGroovy/delegate1/Delegate1MyClass_after.groovy
Vendored
+16
-1
@@ -1,5 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
def foo() {
|
||||
foo("foo");
|
||||
foo("foo")
|
||||
}
|
||||
|
||||
def foo(String anObject) {
|
||||
|
||||
plugins/groovy/testdata/refactoring/introduceParameterGroovy/delegate2/Delegate2MyClass_after.groovy
Vendored
+16
-1
@@ -1,5 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
def foo(def p) {
|
||||
foo(p, "foo");
|
||||
foo(p, "foo")
|
||||
}
|
||||
|
||||
def foo(def p, String anObject) {
|
||||
|
||||
+17
-2
@@ -1,6 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
class Base {
|
||||
def foo() {
|
||||
foo(123);
|
||||
foo(123)
|
||||
}
|
||||
|
||||
def foo(int anObject){}
|
||||
@@ -8,7 +23,7 @@ class Base {
|
||||
|
||||
class Inh extends Base {
|
||||
def foo() {
|
||||
foo(123);
|
||||
foo(123)
|
||||
}
|
||||
|
||||
def foo(int anObject) {print anObject}
|
||||
|
||||
plugins/groovy/testdata/refactoring/introduceParameterGroovy/scriptMethod/ScriptMethodMyClass.groovy
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
def foo(String s) {
|
||||
print(<selection>s + 1</selection>)
|
||||
}
|
||||
|
||||
foo('a')
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
def foo(def anObject) {
|
||||
<selection>print(anObject)</selection>
|
||||
}
|
||||
|
||||
foo('a' + 1)
|
||||
Reference in New Issue
Block a user