From 040cd95ebe983a3b642983d85e2944b51fbe4cb5 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 9 Feb 2012 11:41:22 +0400 Subject: [PATCH] merge extract closure into introduce parameter --- plugins/groovy/src/META-INF/plugin.xml | 9 - .../extract/ExtractInfoHelper.java | 2 + .../extract/ExtractInfoHelperBase.java | 10 +- .../extract/GroovyExtractChooser.java | 36 ++-- .../refactoring/extract/InitialInfo.java | 9 +- .../extract/closure/ExtractClosureDialog.java | 80 +++----- .../ExtractClosureFromClosureProcessor.java | 3 +- .../ExtractClosureFromMethodProcessor.java | 11 +- .../closure/ExtractClosureHandler.java | 166 --------------- ...per.java => ExtractClosureHelperImpl.java} | 53 +++-- .../closure/ExtractClosureProcessorBase.java | 12 +- .../method/GroovyExtractMethodHandler.java | 3 +- .../introduce/GrIntroduceContext.java | 1 + .../introduce/GrIntroduceContextImpl.java | 13 +- .../introduce/GrIntroduceHandlerBase.java | 39 +++- .../introduce/GrIntroduceSettings.java | 1 + .../GrIntroduceClosureParameterProcessor.java | 39 ++-- .../GrIntroduceExpressionSettings.java} | 25 +-- .../GrIntroduceExpressionSettingsImpl.java | 61 ++++++ .../parameter/GrIntroduceParameterDialog.java | 194 +++++++----------- .../GrIntroduceParameterHandler.java | 110 ++-------- .../GrIntroduceParameterProcessor.java | 58 +++--- .../GrIntroduceParameterSettings.java | 14 +- .../GroovyIntroduceParameterUtil.java | 102 ++++++--- ...ntext.java => IntroduceParameterInfo.java} | 4 +- ...l.java => IntroduceParameterInfoImpl.java} | 35 ++-- .../groovy/refactoring/ui/GrTypeComboBox.java | 13 +- .../extract/closure/ExtractClosureTest.groovy | 41 ++-- .../GrIntroduceParameterTest.java | 79 ++----- .../ScriptMethodMyClass_after.groovy | 2 +- .../RemoveUnusedParam_after.groovy | 2 +- 31 files changed, 524 insertions(+), 703 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHandler.java rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/{ExtractClosureHelper.java => ExtractClosureHelperImpl.java} (66%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/{extract/closure/ExtractClosureAction.java => introduce/parameter/GrIntroduceExpressionSettings.java} (50%) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/{GrIntroduceParameterContext.java => IntroduceParameterInfo.java} (85%) rename plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/{GrIntroduceParameterContextImpl.java => IntroduceParameterInfoImpl.java} (50%) diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 56e5c6d0d4fc..bbc62718cff7 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -1056,10 +1056,6 @@ class="org.jetbrains.plugins.groovy.actions.DumpGroovyStubsAction" text="dump groovy stubs" description="" internal="true"/> - - - @@ -1105,11 +1101,6 @@ - - myInputNamesMap; - public ExtractInfoHelperBase( - InitialInfo initialInfo) { + public ExtractInfoHelperBase(ExtractInfoHelper initialInfo) { myInitialInfo = initialInfo; final ParameterInfo[] infos = initialInfo.getParameterInfos(); @@ -109,4 +108,9 @@ public abstract class ExtractInfoHelperBase implements ExtractInfoHelper { public boolean hasReturnValue() { return myInitialInfo.hasReturnValue(); } + + @Override + public PsiElement getContext() { + return myInitialInfo.getContext(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java index 2df703e94008..2d44da327f9d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java @@ -24,6 +24,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; @@ -61,15 +63,21 @@ import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil.*; public class GroovyExtractChooser { private static final Logger LOG = Logger.getInstance(GroovyExtractChooser.class); - public static InitialInfo invoke(Project project, Editor editor, PsiFile file, int start, int end) throws GrRefactoringError { + public static InitialInfo invoke(Project project, Editor editor, PsiFile file, int start, int end, boolean forceStatements) throws GrRefactoringError { + PsiDocumentManager.getInstance(project).commitAllDocuments(); + if (!(file instanceof GroovyFileBase)) { throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files")); } + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { + throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found")); + } + SelectionModel selectionModel = editor.getSelectionModel(); PsiDocumentManager.getInstance(project).commitAllDocuments(); - PsiElement[] elements = getElementsInOffset(file, start, end); + PsiElement[] elements = getElementsInOffset(file, start, end, forceStatements); if (elements.length == 1 && elements[0] instanceof GrExpression) { selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset()); } @@ -166,26 +174,25 @@ public class GroovyExtractChooser { ArrayList statementList = new ArrayList(); for (PsiElement element : elements) { if (element instanceof GrStatement) { - statementList.add(((GrStatement) element)); + statementList.add(((GrStatement)element)); } } return statementList.toArray(new GrStatement[statementList.size()]); } - private static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset) { - PsiElement[] elements; + private static PsiElement[] getElementsInOffset(PsiFile file, int startOffset, int endOffset, boolean forceStatements) { GrExpression expr = findElementInRange(file, startOffset, endOffset, GrExpression.class); + if (!forceStatements && expr != null) return new PsiElement[]{expr}; - 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 = findStatementsInRange(file, startOffset, endOffset, true); + if (expr == null) { + return findStatementsInRange(file, startOffset, endOffset, true); } - return elements; + + PsiElement parent = expr.getParent(); + if (expr.getParent() instanceof GrMethodCallExpression || parent instanceof GrIndexProperty) { + expr = ((GrExpression)expr.getParent()); + } + return new PsiElement[]{expr}; } private static boolean isReturnStatement(GrStatement statement, Collection returnStatements) { @@ -193,7 +200,6 @@ public class GroovyExtractChooser { if (statement instanceof GrIfStatement) { boolean checked = GroovyInlineMethodUtil.checkTailIfStatement(((GrIfStatement)statement), returnStatements); return checked & returnStatements.size() == 0; - } if (statement instanceof GrExpression) { return returnStatements.contains(statement); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java index 7ebd9544c6ba..54216fcb7ce2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java @@ -90,7 +90,7 @@ public class InitialInfo implements ExtractInfoHelper { outputType = outputInfos[0].getType(); } else { - outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, myStatements[0]); + outputType = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, getContext()); } } else if (ExtractUtil.isSingleExpression(statements)) { @@ -113,7 +113,7 @@ public class InitialInfo implements ExtractInfoHelper { types.add(((GrExpression)statement).getType()); } } - outputType = TypesUtil.getLeastUpperBoundNullable(types, statements[0].getManager()); + outputType = TypesUtil.getLeastUpperBoundNullable(types, getContext().getManager()); } return outputType; @@ -174,4 +174,9 @@ public class InitialInfo implements ExtractInfoHelper { public String getName() { throw new UnsupportedOperationException(); } + + @Override + public PsiElement getContext() { + return myStatements[0]; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java index e37b5fa30bbb..48fc8fec82a5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java @@ -19,10 +19,8 @@ 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.IntroduceParameterRefactoring; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.ui.EditorTextField; import com.intellij.ui.IdeBorderFactory; @@ -34,14 +32,14 @@ import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntProcedure; import org.jetbrains.annotations.Nullable; 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.introduce.parameter.GrIntroduceParameterSettings; +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.IntroduceParameterInfo; import org.jetbrains.plugins.groovy.refactoring.ui.GrMethodSignatureComponent; import javax.swing.*; @@ -56,18 +54,18 @@ public class ExtractClosureDialog extends DialogWrapper { private final GrMethodSignatureComponent mySignature; private final EditorTextField myNameField; - private final ExtractClosureHelper myHelper; + private final IntroduceParameterInfo myInfo; private final JBCheckBox myFinalCB; private final JBCheckBox myGenerateDelegateCB; TObjectIntHashMap toRemoveCBs; - public ExtractClosureDialog(InitialInfo initialInfo, GrParametersOwner owner, PsiElement toSearchFor) { + public ExtractClosureDialog(IntroduceParameterInfo initialInfo) { super(initialInfo.getProject()); - myHelper = new ExtractClosureHelper(initialInfo, owner, toSearchFor, "", false); + myInfo = initialInfo; - setTitle(ExtractClosureHandler.EXTRACT_CLOSURE); + setTitle("Extract closure"); myTable = new ParameterTablePanel() { @Override @@ -93,7 +91,7 @@ public class ExtractClosureDialog extends DialogWrapper { myGenerateDelegateCB = new JBCheckBox(UIUtil.replaceMnemonicAmpersand("De&legate via overloading method")); myGenerateDelegateCB.setFocusable(false); - TObjectIntHashMap parametersToRemove = findParametersToRemove(myHelper); + TObjectIntHashMap parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(myInfo); toRemoveCBs = new TObjectIntHashMap(parametersToRemove.size()); for (Object p : parametersToRemove.keys()) { JBCheckBox cb = new JBCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName())); @@ -118,7 +116,7 @@ public class ExtractClosureDialog extends DialogWrapper { if (!checkbox.isSelected()) return true; - final GrParameter param = myHelper.getOwner().getParameters()[index]; + final GrParameter param = myInfo.getToReplaceIn().getParameters()[index]; final ParameterInfo pinfo = findParamByOldName(param.getName()); if (pinfo == null || !pinfo.passAsParameter()) return true; @@ -133,7 +131,7 @@ public class ExtractClosureDialog extends DialogWrapper { @Nullable private ParameterInfo findParamByOldName(String name) { - for (ParameterInfo info : myHelper.getParameterInfos()) { + for (ParameterInfo info : myInfo.getParameterInfos()) { if (name.equals(info.getOldName())) return info; } return null; @@ -142,7 +140,7 @@ public class ExtractClosureDialog extends DialogWrapper { private void updateSignature() { StringBuilder b = new StringBuilder(); b.append("{ "); - String[] params = ExtractUtil.getParameterString(myHelper, false); + String[] params = ExtractUtil.getParameterString(myInfo, false); for (int i = 0; i < params.length; i++) { if (i > 0) { b.append(" "); @@ -163,16 +161,16 @@ public class ExtractClosureDialog extends DialogWrapper { protected void init() { super.init(); - myTable.init(myHelper); + myTable.init(myInfo); final JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance(); final Boolean settingsFinals = refactoringSettings.INTRODUCE_PARAMETER_CREATE_FINALS; myFinalCB.setSelected(settingsFinals == null ? - CodeStyleSettingsManager.getSettings(myHelper.getProject()).GENERATE_FINAL_PARAMETERS : + CodeStyleSettingsManager.getSettings(myInfo.getProject()).GENERATE_FINAL_PARAMETERS : settingsFinals.booleanValue()); myGenerateDelegateCB.setSelected(false); - final GrParameter[] parameters = myHelper.getOwner().getParameters(); + final GrParameter[] parameters = myInfo.getToReplaceIn().getParameters(); toRemoveCBs.forEachEntry(new TObjectIntProcedure() { @Override public boolean execute(JBCheckBox checkbox, int index) { @@ -234,10 +232,10 @@ public class ExtractClosureDialog extends DialogWrapper { 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()); + super.doOKAction(); + } + public GrIntroduceParameterSettings getHelper() { TIntArrayList list = new TIntArrayList(); for (Object cb : toRemoveCBs.keys()) { final JBCheckBox checkbox = (JBCheckBox)cb; @@ -245,41 +243,13 @@ public class ExtractClosureDialog extends DialogWrapper { list.add(toRemoveCBs.get(checkbox)); } } - myHelper.setToRemove(list); - super.doOKAction(); - } - public ExtractClosureHelper getHelper() { - return myHelper; - } - - private static TObjectIntHashMap findParametersToRemove(ExtractClosureHelper helper) { - final TObjectIntHashMap result = new TObjectIntHashMap(); - - 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; + return new ExtractClosureHelperImpl(myInfo, + myNameField.getText(), + myFinalCB.isSelected(), + list, + myGenerateDelegateCB.isSelected(), + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE + ); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromClosureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromClosureProcessor.java index ca8bf33e1253..0ebdeb8b0bce 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromClosureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromClosureProcessor.java @@ -27,6 +27,7 @@ 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 org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings; import java.util.ArrayList; import java.util.List; @@ -35,7 +36,7 @@ import java.util.List; * @author Max Medvedev */ public class ExtractClosureFromClosureProcessor extends ExtractClosureProcessorBase { - public ExtractClosureFromClosureProcessor(@NotNull ExtractClosureHelper helper) { + public ExtractClosureFromClosureProcessor(@NotNull GrIntroduceParameterSettings helper) { super(helper); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java index c0f238a56a49..a20e1a72530a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java @@ -16,7 +16,6 @@ package org.jetbrains.plugins.groovy.refactoring.extract.closure; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; @@ -51,6 +50,7 @@ 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 org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings; import java.util.ArrayList; import java.util.Collection; @@ -66,14 +66,12 @@ import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.Groov public class ExtractClosureFromMethodProcessor extends ExtractClosureProcessorBase { private final GrMethod myMethod; - private Editor myEditor; private final GrStatementOwner myDeclarationOwner; - public ExtractClosureFromMethodProcessor(@NotNull ExtractClosureHelper helper, Editor editor) { + public ExtractClosureFromMethodProcessor(@NotNull GrIntroduceParameterSettings helper) { super(helper); - myEditor = editor; myDeclarationOwner = GroovyRefactoringUtil.getDeclarationOwner(helper.getStatements()[0]); - myMethod = (GrMethod)myHelper.getOwner(); + myMethod = (GrMethod)myHelper.getToReplaceIn(); } @Override @@ -211,10 +209,11 @@ public class ExtractClosureFromMethodProcessor extends ExtractClosureProcessorBa } final GrStatement newStatement = ExtractUtil.replaceStatement(myDeclarationOwner, myHelper); + /* if (myEditor != null) { PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument()); myEditor.getCaretModel().moveToOffset(ExtractUtil.getCaretOffset(newStatement)); - } + }*/ fieldConflictsResolver.fix(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHandler.java deleted file mode 100644 index b174a252c3cd..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHandler.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.HelpID; -import org.jetbrains.plugins.groovy.refactoring.extract.GroovyExtractChooser; -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 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 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 callback = new Pass() { - public void pass(final GrExpression selectedValue) { - invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset()); - } - }; - final Function renderer = new Function() { - @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 { - final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, start, end); - performRefactoring(initialInfo, editor); - } - catch (GrRefactoringError 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 callback) { - final List scopes = new ArrayList(); - while (true) { - final GrParametersOwner parent = PsiTreeUtil.getParentOfType(place, GrMethod.class/*, GrClosableBlock.class*/); //todo implement extract closure from closure - if (parent == null) break; - scopes.add(parent); - place = parent; - } - - if (scopes.size() == 0) { - throw new GrRefactoringError(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); - } - } - - - public void performRefactoring(@NotNull final InitialInfo info, final Editor editor) { - findScope(info.getStatements()[0], editor, new PairFunction() { - @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; - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java similarity index 66% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelper.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java index 188b10ca1388..711dd7bd3860 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java @@ -20,35 +20,44 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import gnu.trove.TIntArrayList; +import org.jetbrains.annotations.NotNull; 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; +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.IntroduceParameterInfo; /** * @author Max Medvedev */ -public class ExtractClosureHelper extends ExtractInfoHelperBase implements ExtractInfoHelper, GrIntroduceParameterSettings { - +public class ExtractClosureHelperImpl extends ExtractInfoHelperBase implements GrIntroduceParameterSettings { private final GrParametersOwner myOwner; private final PsiElement myToSearchFor; - private String myName; - private boolean myFinal; - private TIntArrayList toRemove; - private boolean myGenerateDelegate; + private final String myName; + private final boolean myFinal; + private final TIntArrayList myToRemove; + private final boolean myGenerateDelegate; + private final int myReplaceFieldsWithGetters; - public ExtractClosureHelper(InitialInfo info, GrParametersOwner owner, PsiElement toSearchFor, String name, boolean declareFinal) { + public ExtractClosureHelperImpl(IntroduceParameterInfo info, + String name, + boolean declareFinal, + TIntArrayList toRemove, + boolean generateDelegate, + int replaceFieldsWithGetters) { super(info); - myOwner = owner; - myToSearchFor = toSearchFor; + myOwner = info.getToReplaceIn(); + myToSearchFor = info.getToSearchFor(); myName = name; myFinal = declareFinal; + myToRemove = toRemove; + myGenerateDelegate = generateDelegate; + myReplaceFieldsWithGetters = replaceFieldsWithGetters; } - public GrParametersOwner getOwner() { + @NotNull + public GrParametersOwner getToReplaceIn() { return myOwner; } @@ -64,26 +73,14 @@ public class ExtractClosureHelper extends ExtractInfoHelperBase implements Extra 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; + return myToRemove; } @Override public int replaceFieldsWithGetters() { - return 0;//todo + return myReplaceFieldsWithGetters; } @Override @@ -104,8 +101,4 @@ public class ExtractClosureHelper extends ExtractInfoHelperBase implements Extra public boolean generateDelegate() { return myGenerateDelegate; } - - public void setGenerateDelegate(boolean generateDelegate) { - myGenerateDelegate = generateDelegate; - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java index ff479ad934e1..59d6e646b3b2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java @@ -24,14 +24,16 @@ 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; +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings; /** * @author Max Medvedev */ public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcessor { - protected final ExtractClosureHelper myHelper; + protected final GrIntroduceParameterSettings myHelper; + private static final String EXTRACT_CLOSURE = "Extract closure"; - public ExtractClosureProcessorBase(@NotNull ExtractClosureHelper helper) { + public ExtractClosureProcessorBase(@NotNull GrIntroduceParameterSettings helper) { super(helper.getProject()); myHelper = helper; } @@ -48,14 +50,14 @@ public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcess @Override public String getProcessedElementsHeader() { - return ExtractClosureHandler.EXTRACT_CLOSURE; + return EXTRACT_CLOSURE; } }; } @Override protected String getCommandName() { - return ExtractClosureHandler.EXTRACT_CLOSURE; + return EXTRACT_CLOSURE; } protected GrClosableBlock generateClosure() { @@ -77,6 +79,6 @@ public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcess ExtractUtil.generateBody(myHelper, false, buffer); buffer.append('}'); - return GroovyPsiElementFactory.getInstance(myHelper.getProject()).createClosureFromText(buffer.toString(), myHelper.getOwner()); + return GroovyPsiElementFactory.getInstance(myHelper.getProject()).createClosureFromText(buffer.toString(), myHelper.getToReplaceIn()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java index 7550c38b4a9e..6fdd10d4fddb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java @@ -73,7 +73,8 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } try { - final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, model.getSelectionStart(), model.getSelectionEnd()); + final InitialInfo initialInfo = + GroovyExtractChooser.invoke(project, editor, file, model.getSelectionStart(), model.getSelectionEnd(), true); performRefactoring(initialInfo, editor); } catch (GrRefactoringError e) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java index c696f23f7940..0c7fd56db06a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContext.java @@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres * @author Max Medvedev */ public interface GrIntroduceContext { + @NotNull Project getProject(); Editor getEditor(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContextImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContextImpl.java index e53cb5f4aeb0..257e7df8ef50 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContextImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceContextImpl.java @@ -38,12 +38,12 @@ public class GrIntroduceContextImpl implements GrIntroduceContext { @Nullable private final GrVariable var; @NotNull private final PsiElement place; - public GrIntroduceContextImpl(Project project, - Editor editor, - @Nullable GrExpression expression, - @Nullable GrVariable var, - PsiElement[] occurrences, - PsiElement scope) { + public GrIntroduceContextImpl(@NotNull Project project, + Editor editor, + @Nullable GrExpression expression, + @Nullable GrVariable var, + @NotNull PsiElement[] occurrences, + PsiElement scope) { LOG.assertTrue(expression != null || var != null); this.project = project; @@ -55,6 +55,7 @@ public class GrIntroduceContextImpl implements GrIntroduceContext { this.place = expression == null ? var : expression; } + @NotNull public Project getProject() { return project; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index 1a4ea3aff3ac..ccb528dbcf0e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -91,14 +91,14 @@ public abstract class GrIntroduceHandlerBase conflicts) { //todo whole method - if (myContext.getExpression() == null) return; + final GrExpression expression = mySettings.getExpression(); + if (expression == null) return; final ReferencedElementsCollector collector = new ReferencedElementsCollector(); - myContext.getExpression().accept(collector); + expression.accept(collector); final List result = collector.getResult(); if (result.isEmpty()) return; @@ -223,14 +223,14 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess } if (mySettings.replaceAllOccurrences()) { - PsiElement[] exprs = myContext.getOccurrences(); + PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings); for (PsiElement expr : exprs) { result.add(new InternalUsageInfo(expr)); } } else { - if (myContext.getExpression() != null) { - result.add(new InternalUsageInfo(myContext.getExpression())); + if (mySettings.getExpression() != null) { + result.add(new InternalUsageInfo(mySettings.getExpression())); } } @@ -314,8 +314,9 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess processClosure(usages); } - if (myContext.getVar() != null && mySettings.removeLocalVariable()) { - myContext.getVar().delete(); + final GrVariable var = mySettings.getVar(); + if (var != null && mySettings.removeLocalVariable()) { + var.delete(); } } @@ -611,7 +612,7 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess @Override protected String getCommandName() { - return RefactoringBundle.message("introduce.parameter.command", UsageViewUtil.getDescriptiveName(myContext.getToReplaceIn())); + return RefactoringBundle.message("introduce.parameter.command", UsageViewUtil.getDescriptiveName(mySettings.getToReplaceIn())); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettings.java similarity index 50% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureAction.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettings.java index b77ed8198775..48c2d02d98da 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureAction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettings.java @@ -13,24 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.extract.closure; +package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; -import com.intellij.lang.refactoring.RefactoringSupportProvider; -import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.actions.BasePlatformRefactoringAction; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; /** * @author Max Medvedev */ -public class ExtractClosureAction extends BasePlatformRefactoringAction { - @Override - protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) { - return new ExtractClosureHandler(); - } +public interface GrIntroduceExpressionSettings extends GrIntroduceParameterSettings { + + @Nullable + GrVariable getVar(); + + @Nullable + GrExpression getExpression(); - @Override - protected boolean isAvailableInEditorOnly() { - return true; - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java new file mode 100644 index 000000000000..7a73ff4c2750 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java @@ -0,0 +1,61 @@ +/* + * 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.introduce.parameter; + +import com.intellij.psi.PsiType; +import gnu.trove.TIntArrayList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureHelperImpl; + +/** + * @author Max Medvedev + */ +public class GrIntroduceExpressionSettingsImpl extends ExtractClosureHelperImpl implements GrIntroduceExpressionSettings { + private final GrExpression myExpr; + private final GrVariable myVar; + private final PsiType mySelectedType; + + public GrIntroduceExpressionSettingsImpl(IntroduceParameterInfo info, + String name, + boolean declareFinal, + TIntArrayList toRemove, + boolean generateDelegate, + int replaceFieldsWithGetters, + GrExpression expr, + GrVariable var, + PsiType selectedType) { + super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters); + myExpr = expr; + myVar = var; + mySelectedType = selectedType; + } + + @Override + public GrVariable getVar() { + return myVar; + } + + @Override + public GrExpression getExpression() { + return myExpr; + } + + @Override + public PsiType getSelectedType() { + return mySelectedType; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java index 115ec4461220..f8cc8b4afb4b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java @@ -15,35 +15,37 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.refactoring.ui.RefactoringDialog; +import com.intellij.util.ArrayUtil; import com.intellij.util.ui.GridBag; import gnu.trove.TIntArrayList; import gnu.trove.TObjectIntHashMap; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.GrVariable; 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.params.GrParameter; 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.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.HelpID; +import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureFromMethodProcessor; +import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureHelperImpl; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceDialog; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyFieldValidator; import org.jetbrains.plugins.groovy.refactoring.ui.GrTypeComboBox; @@ -68,12 +70,14 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI private JLabel myTypeLabel; private JLabel myNameLabel; private JCheckBox myChangeVarUsages; - private GrIntroduceParameterContext myContext; + private IntroduceParameterInfo myInfo; TObjectIntHashMap toRemoveCBs; - public GrIntroduceParameterDialog(GrIntroduceParameterContext context, TObjectIntHashMap parametersToRemove) { - super(context.getProject(), true); - myContext = context; + public GrIntroduceParameterDialog(IntroduceParameterInfo info) { + super(info.getProject(), true); + myInfo = info; + + TObjectIntHashMap parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info); toRemoveCBs = new TObjectIntHashMap(parametersToRemove.size()); for (Object p : parametersToRemove.keys()) { JCheckBox cb = new JCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName())); @@ -83,11 +87,7 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); - if (context.getOccurrences().length < 2) { //todo - myReplaceAllOccurrencesCheckBox.setSelected(true); - myReplaceAllOccurrencesCheckBox.setVisible(false); - } - if (myContext.getVar() == null) { + if (myInfo.getStatements().length == 1 && GrIntroduceHandlerBase.findVariable(myInfo.getStatements()[0]) == null) { myRemoveLocalVariableCheckBox.setSelected(false); myRemoveLocalVariableCheckBox.setVisible(false); } @@ -99,10 +99,10 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI myDeclareFinalCheckBox.setSelected(hasFinalModifier()); - myChangeVarUsages.setVisible(context.getToReplaceIn() instanceof GrClosableBlock && context.getToSearchFor() instanceof GrVariable); + myChangeVarUsages.setVisible(info.getToReplaceIn() instanceof GrClosableBlock && info.getToSearchFor() instanceof GrVariable); myChangeVarUsages.setSelected(true); - myDelegateViaOverloadingMethodCheckBox.setVisible(context.getToSearchFor() != null); + myDelegateViaOverloadingMethodCheckBox.setVisible(info.getToSearchFor() != null); setTitle(RefactoringBundle.message("introduce.parameter.title")); init(); @@ -110,7 +110,7 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI private void initReplaceFieldsWithGetters(JavaRefactoringSettings settings) { - final PsiField[] usedFields = GroovyIntroduceParameterUtil.findUsedFieldsWithGetters(myContext.getExpression(), getContainingClass()); + final PsiField[] usedFields = GroovyIntroduceParameterUtil.findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass()); myGetterPanel.setVisible(usedFields.length > 0); switch (settings.INTRODUCE_PARAMETER_REPLACE_FIELDS_WITH_GETTERS) { case REPLACE_FIELDS_WITH_GETTERS_ALL: @@ -127,7 +127,7 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI @Nullable private PsiClass getContainingClass() { - final GrParametersOwner toReplaceIn = myContext.getToReplaceIn(); + final GrParametersOwner toReplaceIn = myInfo.getToReplaceIn(); if (toReplaceIn instanceof GrMethod) { return ((GrMethod)toReplaceIn).getContainingClass(); } @@ -144,27 +144,39 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI @Override protected void doAction() { saveSettings(); - GrIntroduceParameterSettings settings = new GrIntroduceParameterSettingsImpl( - myNameSuggestionsField.getEnteredName(), - myReplaceAllOccurrencesCheckBox.isSelected(), - myTypeComboBox.getSelectedType(), - myDeclareFinalCheckBox.isSelected(), - myDelegateViaOverloadingMethodCheckBox.isSelected(), - getParametersToRemove(), - getReplaceFieldsWithGetter(), - myRemoveLocalVariableCheckBox.isSelected()); + final GrParametersOwner toReplaceIn = myInfo.getToReplaceIn(); + final PsiType selectedType = myTypeComboBox.getSelectedType(); - final BaseRefactoringProcessor processor; - if (myContext.getToReplaceIn() instanceof GrMethod) { - processor = new GrIntroduceParameterProcessor(settings, myContext); + final GrExpression expr = findExpr(); + final GrVariable var = findVar(); + + if ((expr == null && var == null) || selectedType != null && selectedType.equalsToText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE)) { + GrIntroduceParameterSettings settings = new ExtractClosureHelperImpl(myInfo, + myNameSuggestionsField.getEnteredName(), + myDeclareFinalCheckBox.isSelected(), + getParametersToRemove(), + myDelegateViaOverloadingMethodCheckBox.isSelected(), + getReplaceFieldsWithGetter()); + invokeRefactoring(new ExtractClosureFromMethodProcessor(settings)); } else { - if (!myChangeVarUsages.isSelected() && myContext.getToSearchFor() != null) { - myContext = new GrIntroduceParameterContextImpl(myContext, myContext.getToReplaceIn(), null); + + GrIntroduceExpressionSettings settings = new GrIntroduceExpressionSettingsImpl(myInfo, + myNameSuggestionsField.getEnteredName(), + myDeclareFinalCheckBox.isSelected(), + getParametersToRemove(), + myDelegateViaOverloadingMethodCheckBox.isSelected(), + getReplaceFieldsWithGetter(), + expr, + var, + myTypeComboBox.getSelectedType()); + if (toReplaceIn instanceof GrMethod) { + invokeRefactoring(new GrIntroduceParameterProcessor(settings)); + } + else { + invokeRefactoring(new GrIntroduceClosureParameterProcessor(settings)); } - processor = new GrIntroduceClosureParameterProcessor(settings, myContext); } - invokeRefactoring(processor); } private void saveSettings() { @@ -224,101 +236,53 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI } private void createUIComponents() { - if (myContext.getVar() != null) { - myTypeComboBox = GrTypeComboBox.createTypeComboBoxWithDefType(myContext.getVar().getDeclaredType()); + final GrVariable var = findVar(); + final GrExpression expr = findExpr(); + if (var != null) { + myTypeComboBox = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType()); + } + else if (expr != null) { + myTypeComboBox = GrTypeComboBox.createTypeComboBoxFromExpression(expr); } else { - myTypeComboBox = GrTypeComboBox.createTypeComboBoxFromExpression(myContext.getExpression()); + myTypeComboBox = GrTypeComboBox.createEmptyTypeComboBox(); } + myTypeComboBox.addType(JavaPsiFacade.getElementFactory(myProject).createTypeFromText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, myInfo.getContext())); + String[] possibleNames; - final GrIntroduceContext - introduceContext = new GrIntroduceContextImpl(myProject, null, myContext.getExpression(), myContext.getVar(), PsiElement.EMPTY_ARRAY, - myContext.getToReplaceIn()); + final GrIntroduceContext introduceContext = new GrIntroduceContextImpl(myProject, null, expr, var, PsiElement.EMPTY_ARRAY, myInfo.getToReplaceIn()); final GroovyFieldValidator validator = new GroovyFieldValidator(introduceContext); - if (myContext.getExpression() != null) { - possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(myContext.getExpression(), validator, true); + if (expr != null) { + possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(expr, validator, true); + } + else if (var != null) { + possibleNames = GroovyNameSuggestionUtil.suggestVariableNameByType(var.getType(), validator); } else { - possibleNames = GroovyNameSuggestionUtil.suggestVariableNameByType(myContext.getVar().getType(), validator); + possibleNames = ArrayUtil.EMPTY_STRING_ARRAY; } - if (myContext.getVar() != null) { + + if (var != null) { String[] arr = new String[possibleNames.length + 1]; - arr[0] = myContext.getVar().getName(); + arr[0] = var.getName(); System.arraycopy(possibleNames, 0, arr, 1, possibleNames.length); possibleNames = arr; } - myNameSuggestionsField = new NameSuggestionsField(possibleNames, myContext.getProject(), GroovyFileType.GROOVY_FILE_TYPE); + myNameSuggestionsField = new NameSuggestionsField(possibleNames, myProject, GroovyFileType.GROOVY_FILE_TYPE); } - static class GrIntroduceParameterSettingsImpl implements GrIntroduceParameterSettings { + @Nullable + private GrVariable findVar() { + final GrStatement[] statements = myInfo.getStatements(); + if (statements.length > 1) return null; + return GrIntroduceHandlerBase.findVariable(statements[0]); + } - private String myName; - private boolean myReplaceAllOccurrences; - private PsiType mySelectedType; - private boolean myDeclareFinal; - private boolean myIsGenerateDelegate; - private TIntArrayList myParameterToRemove; - private int myReplaceFieldWithGetters; - private boolean myRemoveLocalVariable; - - GrIntroduceParameterSettingsImpl(String name, - boolean replaceAllOccurrences, - PsiType selectedType, - boolean declareFinal, - boolean isGenerateDelegate, - TIntArrayList parameterToRemove, - int replaceFieldWithGetters, - boolean removeLocalVariable) { - myName = name; - myReplaceAllOccurrences = replaceAllOccurrences; - mySelectedType = selectedType; - myDeclareFinal = declareFinal; - myIsGenerateDelegate = isGenerateDelegate; - myParameterToRemove = parameterToRemove; - myReplaceFieldWithGetters = replaceFieldWithGetters; - myRemoveLocalVariable = removeLocalVariable; - } - - @Override - public String getName() { - return myName; - } - - @Override - public boolean replaceAllOccurrences() { - return myReplaceAllOccurrences; - } - - @Override - public PsiType getSelectedType() { - return mySelectedType; - } - - @Override - public boolean declareFinal() { - return myDeclareFinal; - } - - @Override - public boolean removeLocalVariable() { - return myRemoveLocalVariable; - } - - @Override - public boolean generateDelegate() { - return myIsGenerateDelegate; - } - - @NotNull - @Override - public TIntArrayList parametersToRemove() { - return myParameterToRemove; - } - - @Override - public int replaceFieldsWithGetters() { - return myReplaceFieldWithGetters; - } + @Nullable + private GrExpression findExpr() { + final GrStatement[] statements = myInfo.getStatements(); + if (statements.length > 1) return null; + return GrIntroduceHandlerBase.findExpression(statements[0]); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java index 9e3e2385ed24..3cc0a8d14ced 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java @@ -17,16 +17,16 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; import com.intellij.ide.util.SuperMethodWarningUtil; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.application.ApplicationManager; 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.*; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.searches.ReferencesSearch; +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; @@ -34,11 +34,8 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.Function; import com.intellij.util.PairFunction; -import com.intellij.util.Processor; -import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -46,18 +43,14 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; 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.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceDialog; +import org.jetbrains.plugins.groovy.refactoring.extract.GroovyExtractChooser; +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.Collections; import java.util.List; import static org.jetbrains.plugins.groovy.refactoring.HelpID.GROOVY_INTRODUCE_PARAMETER; @@ -66,8 +59,6 @@ import static org.jetbrains.plugins.groovy.refactoring.HelpID.GROOVY_INTRODUCE_P * @author Maxim.Medvedev */ public class GrIntroduceParameterHandler implements RefactoringActionHandler, MethodOrClosureScopeChooser.JBPopupOwner { - private static final Logger LOG = Logger.getInstance(GrIntroduceParameterHandler.class); - private JBPopup myEnclosingMethodsPopup; public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) { @@ -91,18 +82,16 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset()); } else { - final Pass callback = new Pass() { + IntroduceTargetChooser.showChooser(editor, expressions, new Pass() { public void pass(final GrExpression selectedValue) { invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset()); } - }; - final Function renderer = new Function() { + }, new Function() { @Override public String fun(GrExpression grExpression) { return grExpression.getText(); } - }; - IntroduceTargetChooser.showChooser(editor, expressions, callback, renderer + } ); return; } @@ -112,33 +101,17 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me private void invoke(final Project project, final Editor editor, PsiFile file, int startOffset, int endOffset) { try { - PsiDocumentManager.getInstance(project).commitAllDocuments(); - if (!(file instanceof GroovyFileBase)) { - throw new GrRefactoringError(GroovyRefactoringBundle.message("only.in.groovy.files")); - } - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) { - throw new GrRefactoringError(RefactoringBundle.message("readonly.occurences.found")); - } - - GrExpression selectedExpr = GrIntroduceHandlerBase.findExpression(file, startOffset, endOffset); - final GrVariable variable = GrIntroduceHandlerBase.findVariable(file, startOffset, endOffset); - if (variable == null && selectedExpr == null) { - throw new GrRefactoringError(null); - } - - findScope(selectedExpr, variable, editor, project); + final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, startOffset, endOffset, false); + findScope(initialInfo, editor); } catch (GrRefactoringError e) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), RefactoringBundle.message("introduce.parameter.title"), - GROOVY_INTRODUCE_PARAMETER); + if (ApplicationManager.getApplication().isUnitTestMode()) throw e; + CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), RefactoringBundle.message("introduce.parameter.title"), GROOVY_INTRODUCE_PARAMETER); } } - private void findScope(@Nullable final GrExpression expression, @Nullable final GrVariable variable, @NotNull final Editor editor, @NotNull final Project project) { - LOG.assertTrue(expression != null || variable != null); - - PsiElement place = expression == null ? variable : expression; - + private void findScope(@NotNull final InitialInfo initialInfo, @NotNull final Editor editor) { + PsiElement place = initialInfo.getContext(); final List scopes = new ArrayList(); while (true) { final GrParametersOwner parent = PsiTreeUtil.getParentOfType(place, GrMethod.class, GrClosableBlock.class); @@ -160,13 +133,13 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me else { toSearchFor = MethodOrClosureScopeChooser.findVariableToUse(owner); } - getContext(project, editor, expression, variable, owner, toSearchFor); + showDialog(new IntroduceParameterInfoImpl(initialInfo, owner, toSearchFor)); } else { myEnclosingMethodsPopup = MethodOrClosureScopeChooser.create(scopes, editor, this, new PairFunction() { @Override public Object fun(GrParametersOwner owner, PsiElement element) { - getContext(project, editor, expression, variable, owner, element); + showDialog(new IntroduceParameterInfoImpl(initialInfo, owner, element)); return null; } }); @@ -179,56 +152,13 @@ public class GrIntroduceParameterHandler implements RefactoringActionHandler, Me return myEnclosingMethodsPopup; } - protected void getContext(@NotNull Project project, - @NotNull Editor editor, - @Nullable GrExpression expression, - @Nullable GrVariable variable, - @NotNull GrParametersOwner toReplaceIn, - @Nullable PsiElement toSearchFor) { - LOG.assertTrue(expression != null || variable != null); - - GrIntroduceContext context; - if (variable == null) { - final PsiElement[] occurrences = findOccurrences(expression, toReplaceIn); - context = new GrIntroduceContextImpl(project, editor, expression, variable, occurrences, toReplaceIn); - } - else { - final List list = Collections.synchronizedList(new ArrayList()); - ReferencesSearch.search(variable, new LocalSearchScope(toReplaceIn)).forEach(new Processor() { - @Override - public boolean process(PsiReference psiReference) { - final PsiElement element = psiReference.getElement(); - if (element != null) { - list.add(element); - } - return true; - } - }); - context = new GrIntroduceContextImpl(project, editor, variable.getInitializerGroovy(), variable, list.toArray(new PsiElement[list.size()]), toReplaceIn); - } - showDialog(new GrIntroduceParameterContextImpl(context, toReplaceIn, toSearchFor)); + //method to hack in tests + protected void showDialog(IntroduceParameterInfo info) { + new GrIntroduceParameterDialog(info).show(); } - protected void showDialog(GrIntroduceParameterContext context) { - TObjectIntHashMap toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(context); - final GrIntroduceDialog dialog = new GrIntroduceParameterDialog(context, toRemove); - dialog.show(); - } - - @NotNull - private static PsiElement[] findOccurrences(@NotNull GrExpression expression, PsiElement scope) { - final PsiElement expr = PsiUtil.skipParentheses(expression, false); - if (expr == null) return PsiElement.EMPTY_ARRAY; - - final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(expr, scope); - if (occurrences == null || occurrences.length == 0) { - throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found")); - } - return occurrences; - } - @Override public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { // Does nothing diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java index 5006c28d30ec..9ebb29214d0b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java @@ -38,6 +38,7 @@ import com.intellij.util.containers.MultiMap; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; 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.typedef.members.GrMethod; @@ -51,18 +52,16 @@ import java.util.Collection; public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor implements IntroduceParameterData { private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterProcessor"); - private final GrIntroduceParameterSettings mySettings; - private final GrIntroduceParameterContext myContext; + private final GrIntroduceExpressionSettings mySettings; private IntroduceParameterData.ExpressionWrapper myParameterInitializer; - public GrIntroduceParameterProcessor(GrIntroduceParameterSettings settings, GrIntroduceParameterContext context) { - super(context.getProject()); + public GrIntroduceParameterProcessor(GrIntroduceExpressionSettings settings) { + super(settings.getProject()); this.mySettings = settings; - this.myContext = context; - LOG.assertTrue(myContext.getToReplaceIn() instanceof GrMethod); - LOG.assertTrue(myContext.getToSearchFor() instanceof PsiMethod); - myParameterInitializer = new GrExpressionWrapper(this.myContext.getExpression()); + LOG.assertTrue(mySettings.getToReplaceIn() instanceof GrMethod); + LOG.assertTrue(mySettings.getToSearchFor() instanceof PsiMethod); + myParameterInitializer = new GrExpressionWrapper(mySettings.getExpression()); } @NotNull @@ -72,7 +71,7 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl @NotNull @Override public PsiElement[] getElements() { - return new PsiElement[]{myContext.getToSearchFor()}; + return new PsiElement[]{mySettings.getToSearchFor()}; } @Override @@ -88,21 +87,21 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl MultiMap conflicts = new MultiMap(); if (!mySettings.generateDelegate()) { - GroovyIntroduceParameterUtil.detectAccessibilityConflicts(myContext.getExpression(), usagesIn, conflicts, + GroovyIntroduceParameterUtil.detectAccessibilityConflicts(mySettings.getExpression(), usagesIn, conflicts, mySettings.replaceFieldsWithGetters() != IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, myProject ); } - final GrMethod toReplaceIn = (GrMethod)myContext.getToReplaceIn(); - if (myContext.getExpression() != null && !toReplaceIn.hasModifierProperty(PsiModifier.PRIVATE)) { + final GrMethod toReplaceIn = (GrMethod)mySettings.getToReplaceIn(); + if (mySettings.getExpression() != null && !toReplaceIn.hasModifierProperty(PsiModifier.PRIVATE)) { final AnySupers anySupers = new AnySupers(); - myContext.getExpression().accept(anySupers); + mySettings.getExpression().accept(anySupers); if (anySupers.isResult()) { for (UsageInfo usageInfo : usagesIn) { if (!(usageInfo.getElement() instanceof PsiMethod) && !(usageInfo instanceof InternalUsageInfo)) { if (!PsiTreeUtil.isAncestor(toReplaceIn.getContainingClass(), usageInfo.getElement(), false)) { - conflicts.putValue(myContext.getExpression(), + conflicts.putValue(mySettings.getExpression(), RefactoringBundle.message("parameter.initializer.contains.0.but.not.all.calls.to.method.are.in.its.class", CommonRefactoringUtil.htmlEmphasize(PsiKeyword.SUPER))); break; @@ -124,7 +123,7 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl protected UsageInfo[] findUsages() { ArrayList result = new ArrayList(); - final PsiMethod toSearchFor = ((PsiMethod)myContext.getToSearchFor()); + final PsiMethod toSearchFor = ((PsiMethod)mySettings.getToSearchFor()); if (!mySettings.generateDelegate()) { Collection refs = @@ -140,7 +139,7 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl else if (ref instanceof PsiClass) { result.add(new NoConstructorClassUsageInfo((PsiClass)ref)); } - else if (!PsiTreeUtil.isAncestor(myContext.getToReplaceIn(), ref, false)) { + else if (!PsiTreeUtil.isAncestor(mySettings.getToReplaceIn(), ref, false)) { result.add(new ExternalUsageInfo(ref)); } else { @@ -150,14 +149,14 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl } if (mySettings.replaceAllOccurrences()) { - PsiElement[] exprs = myContext.getOccurrences(); + PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings); for (PsiElement expr : exprs) { result.add(new InternalUsageInfo(expr)); } } else { - if (myContext.getExpression() != null) { - result.add(new InternalUsageInfo(myContext.getExpression())); + if (mySettings.getExpression() != null) { + result.add(new InternalUsageInfo(mySettings.getExpression())); } } @@ -181,8 +180,8 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl IntroduceParameterUtil.processUsages(usages, this); - final GrMethod toReplaceIn = (GrMethod)myContext.getToReplaceIn(); - final PsiMethod toSearchFor = (PsiMethod)myContext.getToSearchFor(); + final GrMethod toReplaceIn = (GrMethod)mySettings.getToReplaceIn(); + final PsiMethod toSearchFor = (PsiMethod)mySettings.getToSearchFor(); final boolean methodsToProcessAreDifferent = toReplaceIn != toSearchFor; if (mySettings.generateDelegate()) { @@ -210,8 +209,6 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts(new UsageInfo(toSearchFor), usages, this); } - if (myContext.getVar() != null) myContext.getVar().delete(); - // Replacing expression occurrences for (UsageInfo usage : usages) { if (usage instanceof ChangedMethodCallInfo) { @@ -232,32 +229,33 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl } } - if (myContext.getVar() != null && mySettings.removeLocalVariable()) { - myContext.getVar().delete(); + final GrVariable var = mySettings.getVar(); + if (var != null && mySettings.removeLocalVariable()) { + var.delete(); } fieldConflictsResolver.fix(); } @Override protected String getCommandName() { - return RefactoringBundle.message("introduce.parameter.command", UsageViewUtil.getDescriptiveName(myContext.getToReplaceIn())); + return RefactoringBundle.message("introduce.parameter.command", UsageViewUtil.getDescriptiveName(mySettings.getToReplaceIn())); } @NotNull @Override public Project getProject() { - return myContext.getProject(); + return mySettings.getProject(); } @Override public PsiMethod getMethodToReplaceIn() { - return (PsiMethod)myContext.getToReplaceIn(); + return (PsiMethod)mySettings.getToReplaceIn(); } @NotNull @Override public PsiMethod getMethodToSearchFor() { - return (PsiMethod)myContext.getToSearchFor(); + return (PsiMethod)mySettings.getToSearchFor(); } @Override @@ -292,7 +290,7 @@ public class GrIntroduceParameterProcessor extends BaseRefactoringProcessor impl final PsiType selectedType = mySettings.getSelectedType(); if (selectedType != null) return selectedType; final PsiManager manager = PsiManager.getInstance(myProject); - final GlobalSearchScope resolveScope = myContext.getToReplaceIn().getResolveScope(); + final GlobalSearchScope resolveScope = mySettings.getToReplaceIn().getResolveScope(); return PsiType.getJavaLangObject(manager, resolveScope); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterSettings.java index 152864587131..c963e3bbed52 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterSettings.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterSettings.java @@ -15,14 +15,20 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; +import com.intellij.psi.PsiElement; import gnu.trove.TIntArrayList; +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.refactoring.extract.ExtractInfoHelper; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceSettings; /** * @author Maxim.Medvedev */ -public interface GrIntroduceParameterSettings extends GrIntroduceSettings { +public interface GrIntroduceParameterSettings extends GrIntroduceSettings, ExtractInfoHelper { boolean generateDelegate(); + TIntArrayList parametersToRemove(); /** @@ -33,4 +39,10 @@ public interface GrIntroduceParameterSettings extends GrIntroduceSettings { boolean declareFinal(); boolean removeLocalVariable(); + + @NotNull + GrParametersOwner getToReplaceIn(); + + @Nullable + PsiElement getToSearchFor(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java index bdb6e3c6de75..7cc13ffe3f5f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java @@ -18,9 +18,9 @@ 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.LocalSearchScope; 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; @@ -42,6 +42,8 @@ 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.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; 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; @@ -56,8 +58,13 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe 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 org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -69,35 +76,13 @@ public class GroovyIntroduceParameterUtil { private GroovyIntroduceParameterUtil() { } - public static PsiField[] findUsedFieldsWithGetters(GrExpression expression, PsiClass containingClass) { + public static PsiField[] findUsedFieldsWithGetters(GrStatement[] statements, PsiClass containingClass) { if (containingClass == null) return PsiField.EMPTY_ARRAY; final FieldSearcher searcher = new FieldSearcher(containingClass); - expression.accept(searcher); - return searcher.getResult(); - } - - public static TObjectIntHashMap findParametersToRemove(GrIntroduceParameterContext context) { - TObjectIntHashMap toRemove = new TObjectIntHashMap(); - if (context.getVar() == null) { - final GrParametersOwner parametersOwner = context.getToReplaceIn(); - final GrParameter[] parameters = parametersOwner.getParameters(); - final GrExpression expr = context.getExpression(); - for (int i = 0; i < parameters.length; i++) { - GrParameter parameter = parameters[i]; - final boolean shouldRemove = ReferencesSearch.search(parameter).forEach(new Processor() { - @Override - public boolean process(PsiReference ref) { - final PsiElement element = ref.getElement(); - if (element == null) return false; - return PsiTreeUtil.isAncestor(expr, element, false); - } - }); - if (shouldRemove) { - toRemove.put(parameter, i); - } - } + for (GrStatement statement : statements) { + statement.accept(searcher); } - return toRemove; + return searcher.getResult(); } @Nullable @@ -311,6 +296,69 @@ public class GroovyIntroduceParameterUtil { return method; } + public static TObjectIntHashMap findParametersToRemove(IntroduceParameterInfo helper) { + final TObjectIntHashMap result = new TObjectIntHashMap(); + + final GrStatement[] statements = helper.getStatements(); + final int start = statements[0].getTextRange().getStartOffset(); + final int end = statements[statements.length - 1].getTextRange().getEndOffset(); + + GrParameter[] parameters = helper.getToReplaceIn().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; + } + + static PsiElement[] getOccurrences(GrIntroduceExpressionSettings settings) { + final GrParametersOwner scope = settings.getToReplaceIn(); + + final GrExpression expression = settings.getExpression(); + if (expression != null) { + final PsiElement expr = PsiUtil.skipParentheses(expression, false); + if (expr == null) return PsiElement.EMPTY_ARRAY; + + final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(expr, scope); + if (occurrences == null || occurrences.length == 0) { + throw new GrRefactoringError(GroovyRefactoringBundle.message("no.occurrences.found")); + } + return occurrences; + } + else { + final GrVariable var = settings.getVar(); + LOG.assertTrue(var != null); + final List list = Collections.synchronizedList(new ArrayList()); + ReferencesSearch.search(var, new LocalSearchScope(scope)).forEach(new Processor() { + @Override + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + if (element != null) { + list.add(element); + } + return true; + } + }); + return list.toArray(new PsiElement[list.size()]); + } + } + + private static class FieldSearcher extends GroovyRecursiveElementVisitor { PsiClass myClass; private final List result = new ArrayList(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfo.java similarity index 85% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContext.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfo.java index 8ec808e75b94..63dc8ab53a94 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContext.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfo.java @@ -17,12 +17,12 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; import com.intellij.psi.PsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper; /** * @author Max Medvedev */ -public interface GrIntroduceParameterContext extends GrIntroduceContext { +public interface IntroduceParameterInfo extends ExtractInfoHelper { PsiElement getToSearchFor(); GrParametersOwner getToReplaceIn(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContextImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfoImpl.java similarity index 50% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContextImpl.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfoImpl.java index acea16b220d7..534203eb6212 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterContextImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/IntroduceParameterInfoImpl.java @@ -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. @@ -17,28 +17,35 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; import com.intellij.psi.PsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelper; +import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase; +import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; /** - * @author Maxim.Medvedev + * @author Max Medvedev */ -public class GrIntroduceParameterContextImpl extends GrIntroduceContextImpl implements GrIntroduceParameterContext { - private final PsiElement toSearchFor; - private final GrParametersOwner toReplaceIn; +public class IntroduceParameterInfoImpl extends ExtractInfoHelperBase implements IntroduceParameterInfo, ExtractInfoHelper { + private final GrParametersOwner myOwner; + private final PsiElement myToSearchFor; - public GrIntroduceParameterContextImpl(GrIntroduceContext context, GrParametersOwner toReplaceIn, PsiElement toSearchFor) { - super(context.getProject(), context.getEditor(), context.getExpression(), context.getVar(), context.getOccurrences(), - context.getScope()); - this.toReplaceIn = toReplaceIn; - this.toSearchFor = toSearchFor; + public IntroduceParameterInfoImpl(InitialInfo info, GrParametersOwner owner, PsiElement toSearchFor) { + super(info); + myOwner = owner; + myToSearchFor = toSearchFor; } + @Override + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override public PsiElement getToSearchFor() { - return toSearchFor; + return myToSearchFor; } + @Override public GrParametersOwner getToReplaceIn() { - return toReplaceIn; + return myOwner; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java index a29883534c4a..80005da4ff5a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.refactoring.ui; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.ui.ComboBox; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; @@ -26,16 +27,16 @@ 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.refactoring.GroovyRefactoringUtil; -import javax.swing.*; import java.util.*; /** * @author Maxim.Medvedev */ -public class GrTypeComboBox extends JComboBox { +public class GrTypeComboBox extends ComboBox { private static final Logger LOG = Logger.getInstance(GrTypeComboBox.class); + public static GrTypeComboBox createTypeComboBoxWithDefType(@Nullable PsiType type) { return new GrTypeComboBox(type, null, true, null, null, false); } @@ -57,6 +58,10 @@ public class GrTypeComboBox extends JComboBox { } } + public static GrTypeComboBox createEmptyTypeComboBox() { + return new GrTypeComboBox(null, null, false, null, null, false); + } + /** * @param type * @param min @@ -94,6 +99,10 @@ public class GrTypeComboBox extends JComboBox { } } + public void addType(PsiType type) { + addItem(new PsiTypeItem(type)); + } + @Nullable public PsiType getSelectedType() { final Object selected = getSelectedItem(); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureTest.groovy index 696d8c902666..e0fc82bc952e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureTest.groovy @@ -16,12 +16,12 @@ package org.jetbrains.plugins.groovy.refactoring.extract.closure; -import com.intellij.psi.PsiElement +import com.intellij.refactoring.IntroduceParameterRefactoring 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.refactoring.introduce.parameter.GrIntroduceParameterHandler +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GrIntroduceParameterSettings +import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.IntroduceParameterInfo import org.jetbrains.plugins.groovy.util.TestUtils /** @@ -40,25 +40,22 @@ public class ExtractClosureTest extends LightGroovyTestCase { private void doTest(String before, String after, List toRemove, List 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) + def handler = new GrIntroduceParameterHandler() { + @Override + protected void showDialog(IntroduceParameterInfo info) { + + GrIntroduceParameterSettings helper = new ExtractClosureHelperImpl(info, "closure", false, + new TIntArrayList(toRemove as int[]), false, + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE) + for (p in notToUseAsParams) { + helper.parameterInfos[p].setPassAsParameter(false) } - return settings + new ExtractClosureFromMethodProcessor(helper).run() } } - - handler.invoke myFixture.project, myFixture.editor, myFixture.file, model.selectionStart, model.selectionEnd + + handler.invoke myFixture.project, myFixture.editor, myFixture.file, null myFixture.checkResult after } @@ -155,7 +152,7 @@ def foo(int x, int y) { } foo(2, 3) -''',''' +''', ''' def foo(Closure closure) { int a = 5 closure(a) @@ -172,7 +169,7 @@ adventure() def adventure() { try { - killMonsters() + killMonsters() collectLoot() } catch (ArrowToKneeException) { becomeTownGuard() @@ -194,7 +191,7 @@ def adventure(Closure closure) { } ''' } - + void testExpression() { doTest(''' adventure() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java index 7c4d6213c87e..5de6df11474f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java @@ -22,15 +22,17 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.IntroduceParameterRefactoring; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import gnu.trove.TIntArrayList; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; 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.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.*; import org.jetbrains.plugins.groovy.util.TestUtils; @@ -40,7 +42,7 @@ import java.io.File; * @author Maxim.Medvedev */ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { - + protected String getBasePath() { return TestUtils.getTestDataPath() + "refactoring/introduceParameterGroovy/" + getTestName(true) + '/'; } @@ -114,17 +116,14 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { try { final GrIntroduceParameterHandler hackedHandler = new GrIntroduceParameterHandler() { @Override - protected void showDialog(final GrIntroduceParameterContext context) { - final GrIntroduceParameterSettings hackedSettings = - getSettings(context, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate); - BaseRefactoringProcessor processor; - if (context.getToReplaceIn() instanceof GrMethod) { - processor = new GrIntroduceParameterProcessor(hackedSettings, context); + protected void showDialog(IntroduceParameterInfo info) { + final GrIntroduceExpressionSettings hackedSettings = getSettings(info, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate); + if (info.getToReplaceIn() instanceof GrMethod) { + new GrIntroduceParameterProcessor(hackedSettings).run(); } else { - processor = new GrIntroduceClosureParameterProcessor(hackedSettings, context); + new GrIntroduceClosureParameterProcessor(hackedSettings).run(); } - processor.run(); } }; hackedHandler.invoke(project, editor, file, null); @@ -143,61 +142,23 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { }, "introduce Parameter", null); } - private static GrIntroduceParameterSettings getSettings(final GrIntroduceParameterContext context, + private static GrIntroduceExpressionSettings getSettings(final IntroduceParameterInfo context, final boolean removeUnusedParameters, final int replaceFieldsWithGetters, final boolean declareFinal, final boolean generateDelegate) { - return new GrIntroduceParameterSettings() { - @Override - public boolean generateDelegate() { - return generateDelegate; - } - @Override - public TIntArrayList parametersToRemove() { - if (removeUnusedParameters) { - final TObjectIntHashMap parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(context); - TIntArrayList list = new TIntArrayList(parametersToRemove.size()); - for (Object o : parametersToRemove.keys()) { - list.add(parametersToRemove.get((GrParameter)o)); - } - return list; - } - return new TIntArrayList(0); + TIntArrayList toRemove = new TIntArrayList(); + if (removeUnusedParameters) { + final TObjectIntHashMap map = GroovyIntroduceParameterUtil.findParametersToRemove(context); + for (int i : map.getValues()) { + toRemove.add(i); } - - @Override - public int replaceFieldsWithGetters() { - return replaceFieldsWithGetters; - } - - @Override - public boolean declareFinal() { - return declareFinal; - } - - @Override - public boolean removeLocalVariable() { - return false; - } - - @Override - public String getName() { - return "anObject"; - } - - @Override - public boolean replaceAllOccurrences() { - return true; - } - - @Override - public PsiType getSelectedType() { - PsiType type = context.getVar() == null ? context.getExpression().getType() : context.getVar().getDeclaredType(); - return TypesUtil.unboxPrimitiveTypeWrapper(type); - } - }; + } + GrExpression expr = GrIntroduceHandlerBase.findExpression(context.getStatements()[0]); + GrVariable var = GrIntroduceHandlerBase.findVariable(context.getStatements()[0]); + final PsiType type = TypesUtil.unboxPrimitiveTypeWrapper(var == null ? expr.getType() : var.getType()); + return new GrIntroduceExpressionSettingsImpl(context, "anObject", declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, expr, var, type); } diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/scriptMethod/ScriptMethodMyClass_after.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/scriptMethod/ScriptMethodMyClass_after.groovy index e31b07320d7f..081a631fc6ce 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/scriptMethod/ScriptMethodMyClass_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/scriptMethod/ScriptMethodMyClass_after.groovy @@ -1,4 +1,4 @@ -def foo(def anObject) { +def foo(String anObject) { print(anObject) } diff --git a/plugins/groovy/testdata/refactoring/introduceParameterInClosure/RemoveUnusedParam_after.groovy b/plugins/groovy/testdata/refactoring/introduceParameterInClosure/RemoveUnusedParam_after.groovy index d8055c742263..eb46490f4b6c 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameterInClosure/RemoveUnusedParam_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameterInClosure/RemoveUnusedParam_after.groovy @@ -1,4 +1,4 @@ -def a = {int x, int z, def anObject -> +def a = {int x, int z, int anObject -> print anObject + x+z }