mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
merge extract closure into introduce parameter
This commit is contained in:
@@ -1056,10 +1056,6 @@
|
||||
class="org.jetbrains.plugins.groovy.actions.DumpGroovyStubsAction"
|
||||
text="dump groovy stubs"
|
||||
description="" internal="true"/>
|
||||
<action id="Groovy.Extract.Closure" class="org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureAction"
|
||||
text="Closure...">
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt shift M"/>
|
||||
</action>
|
||||
<add-to-group group-id="Internal"/>
|
||||
</group>
|
||||
|
||||
@@ -1105,11 +1101,6 @@
|
||||
<add-to-group group-id="ToolsMenu" anchor="last"/>
|
||||
</action>
|
||||
|
||||
<!--<action id="Groovy.Extract.Closure" class="org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureAction" text="Closure...">
|
||||
<add-to-group group-id="IntroduceActionsGroup" anchor="after" relative-to-action="ExtractMethod"/>
|
||||
<keyboard-shortcut keymap="$default" first-keystroke="ctrl alt shift M"/>
|
||||
</action>-->
|
||||
|
||||
<group id="Mvc.Actions" popup="true" class="org.jetbrains.plugins.groovy.mvc.MvcActionGroup">
|
||||
<action id="Mvc.Upgrade"
|
||||
class="org.jetbrains.plugins.groovy.mvc.MvcUpgradeAction"
|
||||
|
||||
+2
@@ -50,4 +50,6 @@ public interface ExtractInfoHelper {
|
||||
boolean hasReturnValue();
|
||||
|
||||
String getName();
|
||||
|
||||
PsiElement getContext();
|
||||
}
|
||||
|
||||
+7
-3
@@ -30,11 +30,10 @@ import java.util.Map;
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public abstract class ExtractInfoHelperBase implements ExtractInfoHelper {
|
||||
protected final InitialInfo myInitialInfo;
|
||||
protected final ExtractInfoHelper myInitialInfo;
|
||||
protected final Map<String, ParameterInfo> 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();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-15
@@ -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<GrStatement> statementList = new ArrayList<GrStatement>();
|
||||
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<GrStatement> 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);
|
||||
|
||||
+7
-2
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
+25
-55
@@ -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<JBCheckBox> 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<GrParameter> parametersToRemove = findParametersToRemove(myHelper);
|
||||
TObjectIntHashMap<GrParameter> parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(myInfo);
|
||||
toRemoveCBs = new TObjectIntHashMap<JBCheckBox>(parametersToRemove.size());
|
||||
for (Object p : parametersToRemove.keys()) {
|
||||
JBCheckBox cb = new JBCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName()));
|
||||
@@ -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<JBCheckBox>() {
|
||||
@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<GrParameter> findParametersToRemove(ExtractClosureHelper helper) {
|
||||
final TObjectIntHashMap<GrParameter> result = new TObjectIntHashMap<GrParameter>();
|
||||
|
||||
final GrStatement[] statements = helper.getStatements();
|
||||
final int start = statements[0].getTextRange().getStartOffset();
|
||||
final int end = statements[statements.length - 1].getTextRange().getEndOffset();
|
||||
|
||||
GrParameter[] parameters = helper.getOwner().getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
GrParameter parameter = parameters[i];
|
||||
if (shouldRemove(parameter, start, end)) {
|
||||
result.put(parameter, i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean shouldRemove(GrParameter parameter, int start, int end) {
|
||||
for (PsiReference reference : ReferencesSearch.search(parameter)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element == null) continue;
|
||||
|
||||
final int offset = element.getTextRange().getStartOffset();
|
||||
if (offset < start || end <= offset) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return new ExtractClosureHelperImpl(myInfo,
|
||||
myNameField.getText(),
|
||||
myFinalCB.isSelected(),
|
||||
list,
|
||||
myGenerateDelegateCB.isSelected(),
|
||||
IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -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();
|
||||
}
|
||||
|
||||
-166
@@ -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<GrExpression> expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, offset);
|
||||
if (expressions.size() == 1) {
|
||||
final TextRange textRange = expressions.get(0).getTextRange();
|
||||
selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
|
||||
}
|
||||
else {
|
||||
final Pass<GrExpression> callback = new Pass<GrExpression>() {
|
||||
public void pass(final GrExpression selectedValue) {
|
||||
invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset());
|
||||
}
|
||||
};
|
||||
final Function<GrExpression, String> renderer = new Function<GrExpression, String>() {
|
||||
@Override
|
||||
public String fun(GrExpression grExpression) {
|
||||
return grExpression.getText();
|
||||
}
|
||||
};
|
||||
IntroduceTargetChooser.showChooser(editor, expressions, callback, renderer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
|
||||
}
|
||||
|
||||
void invoke(Project project, Editor editor, PsiFile file, int start, int end) {
|
||||
try {
|
||||
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<GrParametersOwner, PsiElement, Object> callback) {
|
||||
final List<GrParametersOwner> scopes = new ArrayList<GrParametersOwner>();
|
||||
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<GrParametersOwner, PsiElement, Object>() {
|
||||
@Override
|
||||
public Object fun(GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
final ExtractClosureHelper helper = getSettings(info, owner, toSearchFor);
|
||||
if (helper == null) return null;
|
||||
|
||||
if (helper.getOwner() instanceof GrMethod) {
|
||||
new ExtractClosureFromMethodProcessor(helper, editor).run();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public JBPopup get() {
|
||||
return myPopup;
|
||||
}
|
||||
}
|
||||
+23
-30
@@ -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;
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -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) {
|
||||
|
||||
+1
@@ -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();
|
||||
|
||||
+7
-6
@@ -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;
|
||||
}
|
||||
|
||||
+32
-7
@@ -91,14 +91,14 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
expression != null;
|
||||
expression = PsiTreeUtil.getParentOfType(expression, GrExpression.class)) {
|
||||
if (expressions.contains(expression)) continue;
|
||||
if (expressionIsNotCorrect(expression)) continue;
|
||||
if (expressionIsIncorrect(expression)) continue;
|
||||
|
||||
expressions.add(expression);
|
||||
}
|
||||
return expressions;
|
||||
}
|
||||
|
||||
private static boolean expressionIsNotCorrect(GrExpression expression) {
|
||||
private static boolean expressionIsIncorrect(GrExpression expression) {
|
||||
if (expression instanceof GrParenthesizedExpression) return true;
|
||||
if (expression instanceof GrSuperReferenceExpression) return true;
|
||||
if (expression.getType() == PsiType.VOID) return true;
|
||||
@@ -297,23 +297,48 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
return var;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GrVariable findVariable(GrStatement statement) {
|
||||
if (!(statement instanceof GrVariableDeclaration)) return null;
|
||||
final GrVariableDeclaration variableDeclaration = (GrVariableDeclaration)statement;
|
||||
final GrVariable[] variables = variableDeclaration.getVariables();
|
||||
|
||||
GrVariable var = null;
|
||||
if (variables.length == 1) {
|
||||
var = variables[0];
|
||||
}
|
||||
if (var instanceof GrParameter || var instanceof GrField) {
|
||||
return null;
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static GrExpression findExpression(PsiFile file, int startOffset, int endOffset) {
|
||||
GrExpression selectedExpr = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrExpression.class);
|
||||
while (selectedExpr instanceof GrParenthesizedExpression) selectedExpr = ((GrParenthesizedExpression)selectedExpr).getOperand();
|
||||
if (selectedExpr == null) return null;
|
||||
PsiType type = selectedExpr.getType();
|
||||
return findExpression(selectedExpr);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GrExpression findExpression(GrStatement selectedExpr) {
|
||||
if (!(selectedExpr instanceof GrExpression)) return null;
|
||||
|
||||
GrExpression selected = (GrExpression)selectedExpr;
|
||||
while (selected instanceof GrParenthesizedExpression) selected = ((GrParenthesizedExpression)selected).getOperand();
|
||||
if (selected == null) return null;
|
||||
PsiType type = selected.getType();
|
||||
if (type != null) type = TypeConversionUtil.erasure(type);
|
||||
|
||||
if (PsiType.VOID.equals(type)) {
|
||||
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.has.void.type"));
|
||||
}
|
||||
|
||||
if (expressionIsNotCorrect(selectedExpr)) {
|
||||
if (expressionIsIncorrect(selected)) {
|
||||
throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression"));
|
||||
}
|
||||
|
||||
return selectedExpr;
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public interface GrIntroduceSettings {
|
||||
@Nullable
|
||||
String getName();
|
||||
|
||||
boolean replaceAllOccurrences();
|
||||
|
||||
@Nullable
|
||||
|
||||
+20
-19
@@ -81,21 +81,19 @@ import java.util.List;
|
||||
public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcessor {
|
||||
private static final Logger LOG = Logger.getInstance(GrIntroduceClosureParameterProcessor.class);
|
||||
|
||||
private GrIntroduceParameterSettings mySettings;
|
||||
private GrIntroduceParameterContext myContext;
|
||||
private GrIntroduceExpressionSettings mySettings;
|
||||
private GrClosableBlock toReplaceIn;
|
||||
private PsiElement toSearchFor;
|
||||
private GrExpressionWrapper myParameterInitializer;
|
||||
private GroovyPsiElementFactory myFactory = GroovyPsiElementFactory.getInstance(myProject);
|
||||
|
||||
public GrIntroduceClosureParameterProcessor(GrIntroduceParameterSettings settings, GrIntroduceParameterContext context) {
|
||||
super(context.getProject(), null);
|
||||
public GrIntroduceClosureParameterProcessor(GrIntroduceExpressionSettings settings) {
|
||||
super(settings.getProject(), null);
|
||||
mySettings = settings;
|
||||
myContext = context;
|
||||
|
||||
toReplaceIn = (GrClosableBlock)myContext.getToReplaceIn();
|
||||
toSearchFor = myContext.getToSearchFor();
|
||||
myParameterInitializer = new GrExpressionWrapper(this.myContext.getExpression());
|
||||
toReplaceIn = (GrClosableBlock)mySettings.getToReplaceIn();
|
||||
toSearchFor = mySettings.getToSearchFor();
|
||||
myParameterInitializer = new GrExpressionWrapper(mySettings.getExpression());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -123,15 +121,16 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess
|
||||
detectAccessibilityConflicts(usagesIn, conflicts);
|
||||
}
|
||||
|
||||
if (myContext.getExpression() != null && toSearchFor instanceof PsiMember) {
|
||||
final GrExpression expression = mySettings.getExpression();
|
||||
if (expression != null && toSearchFor instanceof PsiMember) {
|
||||
final AnySupers anySupers = new AnySupers();
|
||||
myContext.getExpression().accept(anySupers);
|
||||
expression.accept(anySupers);
|
||||
if (anySupers.isResult()) {
|
||||
final PsiElement containingClass = PsiUtil.getFileOrClassContext(toReplaceIn);
|
||||
for (UsageInfo usageInfo : usagesIn) {
|
||||
if (!(usageInfo.getElement() instanceof PsiMethod) && !(usageInfo instanceof InternalUsageInfo)) {
|
||||
if (!PsiTreeUtil.isAncestor(containingClass, usageInfo.getElement(), false)) {
|
||||
conflicts.putValue(myContext.getExpression(), RefactoringBundle
|
||||
conflicts.putValue(expression, RefactoringBundle
|
||||
.message("parameter.initializer.contains.0.but.not.all.calls.to.method.are.in.its.class", CommonRefactoringUtil.htmlEmphasize(PsiKeyword.SUPER)));
|
||||
break;
|
||||
}
|
||||
@@ -152,10 +151,11 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess
|
||||
|
||||
private void detectAccessibilityConflicts(final UsageInfo[] usageArray, MultiMap<PsiElement, String> 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<PsiElement> 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()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-14
@@ -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;
|
||||
}
|
||||
}
|
||||
+61
@@ -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;
|
||||
}
|
||||
}
|
||||
+79
-115
@@ -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<JCheckBox> toRemoveCBs;
|
||||
|
||||
public GrIntroduceParameterDialog(GrIntroduceParameterContext context, TObjectIntHashMap<GrParameter> parametersToRemove) {
|
||||
super(context.getProject(), true);
|
||||
myContext = context;
|
||||
public GrIntroduceParameterDialog(IntroduceParameterInfo info) {
|
||||
super(info.getProject(), true);
|
||||
myInfo = info;
|
||||
|
||||
TObjectIntHashMap<GrParameter> parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info);
|
||||
toRemoveCBs = new TObjectIntHashMap<JCheckBox>(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]);
|
||||
}
|
||||
}
|
||||
|
||||
+20
-90
@@ -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<GrExpression> callback = new Pass<GrExpression>() {
|
||||
IntroduceTargetChooser.showChooser(editor, expressions, new Pass<GrExpression>() {
|
||||
public void pass(final GrExpression selectedValue) {
|
||||
invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset());
|
||||
}
|
||||
};
|
||||
final Function<GrExpression, String> renderer = new Function<GrExpression, String>() {
|
||||
}, new Function<GrExpression, String>() {
|
||||
@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<GrParametersOwner> scopes = new ArrayList<GrParametersOwner>();
|
||||
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<GrParametersOwner, PsiElement, Object>() {
|
||||
@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<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
|
||||
ReferencesSearch.search(variable, new LocalSearchScope(toReplaceIn)).forEach(new Processor<PsiReference>() {
|
||||
@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<GrParameter> toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(context);
|
||||
final GrIntroduceDialog<GrIntroduceParameterSettings> 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
|
||||
|
||||
+28
-30
@@ -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<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
|
||||
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<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
|
||||
final PsiMethod toSearchFor = ((PsiMethod)myContext.getToSearchFor());
|
||||
final PsiMethod toSearchFor = ((PsiMethod)mySettings.getToSearchFor());
|
||||
|
||||
if (!mySettings.generateDelegate()) {
|
||||
Collection<PsiReference> 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);
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -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();
|
||||
}
|
||||
|
||||
+75
-27
@@ -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<GrParameter> findParametersToRemove(GrIntroduceParameterContext context) {
|
||||
TObjectIntHashMap<GrParameter> toRemove = new TObjectIntHashMap<GrParameter>();
|
||||
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<PsiReference>() {
|
||||
@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<GrParameter> findParametersToRemove(IntroduceParameterInfo helper) {
|
||||
final TObjectIntHashMap<GrParameter> result = new TObjectIntHashMap<GrParameter>();
|
||||
|
||||
final GrStatement[] statements = helper.getStatements();
|
||||
final int start = statements[0].getTextRange().getStartOffset();
|
||||
final int end = statements[statements.length - 1].getTextRange().getEndOffset();
|
||||
|
||||
GrParameter[] parameters = helper.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<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
|
||||
ReferencesSearch.search(var, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
|
||||
@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<PsiField> result = new ArrayList<PsiField>();
|
||||
|
||||
+2
-2
@@ -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();
|
||||
+21
-14
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
+19
-22
@@ -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<Integer> toRemove, List<Integer> notToUseAsParams) {
|
||||
myFixture.configureByText '______________a____________________.groovy', before
|
||||
def model = myFixture.editor.selectionModel
|
||||
def handler = new ExtractClosureHandler() {
|
||||
@Override
|
||||
protected ExtractClosureHelper getSettings(@NotNull InitialInfo initialInfo, GrParametersOwner owner, PsiElement toSearchFor) {
|
||||
def settings = new ExtractClosureHelper(initialInfo, owner, toSearchFor, "closure", true)
|
||||
settings.setDeclareFinal(false)
|
||||
settings.setGenerateDelegate(false)
|
||||
settings.setName("closure")
|
||||
settings.setToRemove(new TIntArrayList(toRemove as int[]))
|
||||
|
||||
def infos = settings.parameterInfos
|
||||
for (int i: notToUseAsParams) {
|
||||
infos[i].setPassAsParameter(false)
|
||||
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
|
||||
<selection>closure(a)</selection>
|
||||
@@ -172,7 +169,7 @@ adventure()
|
||||
def adventure() {
|
||||
|
||||
try {
|
||||
<selection>killMonsters()
|
||||
<selection><caret>killMonsters()
|
||||
collectLoot()</selection>
|
||||
} catch (ArrowToKneeException) {
|
||||
becomeTownGuard()
|
||||
@@ -194,7 +191,7 @@ def adventure(Closure closure) {
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
|
||||
void testExpression() {
|
||||
doTest('''
|
||||
adventure()
|
||||
|
||||
+20
-59
@@ -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<GrParameter> 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<GrParameter> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<caret>def foo(def anObject) {
|
||||
<caret>def foo(String anObject) {
|
||||
print(anObject)
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
def a = {int x, int z, def anObject ->
|
||||
def a = {int x, int z, int anObject ->
|
||||
print anObject + x+z
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user