From e5f09509afc94e7b711fe2148b7f62e2383bfc58 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 9 Feb 2012 16:44:56 +0400 Subject: [PATCH] introduce parameter dialog --- .../GroovyRefactoringBundle.properties | 1 + .../extract/GroovyExtractChooser.java | 9 + .../extract/closure/ExtractClosureDialog.java | 255 ------------ .../ExtractClosureFromMethodProcessor.java | 2 +- .../closure/ExtractClosureProcessorBase.java | 10 +- .../introduce/GrIntroduceHandlerBase.java | 9 +- .../parameter/GrIntroduceParameterDialog.form | 156 -------- .../parameter/GrIntroduceParameterDialog.java | 362 ++++++++++++++---- .../groovy/refactoring/ui/GrTypeComboBox.java | 22 +- 9 files changed, 319 insertions(+), 507 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.form diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index e9e71a2f1d9f..8deaf46311c3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -167,3 +167,4 @@ you.cannot.pass.as.parameter.0.because.you.remove.1.from.base.method=You cannot rename.groovy.implicit.closure.parameter=Rename implicit closure parameter rename.implicit.closure.parameter.to=Rename implicit closure parameter to\: implicit.closure.parameter=Implicit closure parameter +selected.expression.should.not.be.lvalue=Selected expression should not be left hand side of assignment diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java index 2d44da327f9d..f32ed727f3b3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java @@ -36,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; @@ -49,6 +50,7 @@ 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.inline.GroovyInlineMethodUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import java.util.ArrayList; import java.util.Collection; @@ -107,6 +109,13 @@ public class GroovyExtractChooser { throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.has.void.type")); } + if (ExtractUtil.isSingleExpression(statements) && GrIntroduceHandlerBase.expressionIsIncorrect((GrExpression)statement0)) { + throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression")); + } + + if (ExtractUtil.isSingleExpression(statements) && statement0.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression)statement0.getParent()).getLValue()==statement0) { + throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.should.not.be.lvalue")); + } // collect information about return statements in selected statement set diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java deleted file mode 100644 index 48fc8fec82a5..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureDialog.java +++ /dev/null @@ -1,255 +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.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.codeStyle.CodeStyleSettingsManager; -import com.intellij.refactoring.IntroduceParameterRefactoring; -import com.intellij.refactoring.JavaRefactoringSettings; -import com.intellij.ui.EditorTextField; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.components.JBCheckBox; -import com.intellij.ui.components.JBLabel; -import com.intellij.util.ui.UIUtil; -import gnu.trove.TIntArrayList; -import gnu.trove.TObjectIntHashMap; -import gnu.trove.TObjectIntProcedure; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.GroovyFileType; -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.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.*; -import java.awt.*; - -/** - * @author Max Medvedev - */ -public class ExtractClosureDialog extends DialogWrapper { - - private final ParameterTablePanel myTable; - private final GrMethodSignatureComponent mySignature; - private final EditorTextField myNameField; - - private final IntroduceParameterInfo myInfo; - private final JBCheckBox myFinalCB; - private final JBCheckBox myGenerateDelegateCB; - - TObjectIntHashMap toRemoveCBs; - - public ExtractClosureDialog(IntroduceParameterInfo initialInfo) { - super(initialInfo.getProject()); - - myInfo = initialInfo; - - setTitle("Extract closure"); - - myTable = new ParameterTablePanel() { - @Override - protected void updateSignature() { - ExtractClosureDialog.this.updateSignature(); - } - - @Override - protected void doEnterAction() { - clickDefaultButton(); - } - - @Override - protected void doCancelAction() { - ExtractClosureDialog.this.doCancelAction(); - } - }; - - mySignature = new GrMethodSignatureComponent("", initialInfo.getProject()); - myNameField = new EditorTextField("", initialInfo.getProject(), GroovyFileType.GROOVY_FILE_TYPE); - myFinalCB = new JBCheckBox(UIUtil.replaceMnemonicAmpersand("Declare &final")); - myFinalCB.setFocusable(false); - myGenerateDelegateCB = new JBCheckBox(UIUtil.replaceMnemonicAmpersand("De&legate via overloading method")); - myGenerateDelegateCB.setFocusable(false); - - TObjectIntHashMap parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(myInfo); - toRemoveCBs = new TObjectIntHashMap(parametersToRemove.size()); - for (Object p : parametersToRemove.keys()) { - JBCheckBox cb = new JBCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName())); - cb.setFocusable(false); - toRemoveCBs.put(cb, parametersToRemove.get((GrParameter)p)); - } - - init(); - } - - @Override - protected ValidationInfo doValidate() { - final String text = myNameField.getText().trim(); - if (!StringUtil.isJavaIdentifier(text)) { - return new ValidationInfo(GroovyRefactoringBundle.message("name.is.wrong", text), myNameField); - } - - final Ref info = new Ref(); - toRemoveCBs.forEachEntry(new TObjectIntProcedure() { - @Override - public boolean execute(JBCheckBox checkbox, int index) { - if (!checkbox.isSelected()) return true; - - - final GrParameter param = myInfo.getToReplaceIn().getParameters()[index]; - final ParameterInfo pinfo = findParamByOldName(param.getName()); - if (pinfo == null || !pinfo.passAsParameter()) return true; - - final String message = GroovyRefactoringBundle.message("you.cannot.pass.as.parameter.0.because.you.remove.1.from.base.method", - pinfo.getName(), param.getName()); - info.set(new ValidationInfo(message)); - return false; - } - }); - return info.get(); - } - - @Nullable - private ParameterInfo findParamByOldName(String name) { - for (ParameterInfo info : myInfo.getParameterInfos()) { - if (name.equals(info.getOldName())) return info; - } - return null; - } - - private void updateSignature() { - StringBuilder b = new StringBuilder(); - b.append("{ "); - String[] params = ExtractUtil.getParameterString(myInfo, false); - for (int i = 0; i < params.length; i++) { - if (i > 0) { - b.append(" "); - } - b.append(params[i]); - b.append('\n'); - } - b.append(" ->\n}"); - mySignature.setSignature(b.toString()); - } - - @Override - public JComponent getPreferredFocusedComponent() { - return myNameField; - } - - @Override - protected void init() { - super.init(); - - myTable.init(myInfo); - - final JavaRefactoringSettings refactoringSettings = JavaRefactoringSettings.getInstance(); - final Boolean settingsFinals = refactoringSettings.INTRODUCE_PARAMETER_CREATE_FINALS; - myFinalCB.setSelected(settingsFinals == null ? - CodeStyleSettingsManager.getSettings(myInfo.getProject()).GENERATE_FINAL_PARAMETERS : - settingsFinals.booleanValue()); - myGenerateDelegateCB.setSelected(false); - - final GrParameter[] parameters = myInfo.getToReplaceIn().getParameters(); - toRemoveCBs.forEachEntry(new TObjectIntProcedure() { - @Override - public boolean execute(JBCheckBox checkbox, int index) { - checkbox.setSelected(true); - - final GrParameter param = parameters[index]; - final ParameterInfo pinfo = findParamByOldName(param.getName()); - if (pinfo != null) { - pinfo.setPassAsParameter(false); - } - return true; - } - }); - updateSignature(); - } - - @Override - protected JComponent createNorthPanel() { - final JPanel panel = new JPanel(new BorderLayout()); - final JBLabel nameLabel = new JBLabel(); - panel.add(nameLabel, BorderLayout.NORTH); - panel.add(myNameField, BorderLayout.CENTER); - nameLabel.setText(UIUtil.replaceMnemonicAmpersand("Parameter &name:")); - nameLabel.setLabelFor(myNameField); - - final JPanel checkBoxPanel = new JPanel(); - checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS)); - - checkBoxPanel.add(myFinalCB); - checkBoxPanel.add(myGenerateDelegateCB); - for (Object cb : toRemoveCBs.keys()) { - checkBoxPanel.add((Component)cb); - } - panel.add(checkBoxPanel, BorderLayout.SOUTH); - return panel; - } - - @Override - protected JComponent createCenterPanel() { - final JPanel signaturePanel = new JPanel(new BorderLayout()); - signaturePanel.setBorder( - IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("signature.preview.border.title"), false, false, true)); - signaturePanel.add(mySignature, BorderLayout.CENTER); - - Splitter splitter = new Splitter(true); - - splitter.setFirstComponent(myTable); - splitter.setSecondComponent(signaturePanel); - - mySignature.setPreferredSize(new Dimension(500, 100)); - mySignature.setSize(new Dimension(500, 100)); - - splitter.setShowDividerIcon(false); - return splitter; - } - - @Override - protected void doOKAction() { - final JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); - settings.INTRODUCE_PARAMETER_CREATE_FINALS = Boolean.valueOf(myFinalCB.isSelected()); - - super.doOKAction(); - } - - public GrIntroduceParameterSettings getHelper() { - TIntArrayList list = new TIntArrayList(); - for (Object cb : toRemoveCBs.keys()) { - final JBCheckBox checkbox = (JBCheckBox)cb; - if (checkbox.isSelected()) { - list.add(toRemoveCBs.get(checkbox)); - } - } - - return new ExtractClosureHelperImpl(myInfo, - myNameField.getText(), - myFinalCB.isSelected(), - list, - myGenerateDelegateCB.isSelected(), - IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE - ); - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java index a20e1a72530a..65678e9211ea 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureFromMethodProcessor.java @@ -225,7 +225,7 @@ public class ExtractClosureFromMethodProcessor extends ExtractClosureProcessorBa private final PsiType myType; private IntroduceParameterDataAdapter() { - myClosure = generateClosure(); + myClosure = generateClosure(ExtractClosureFromMethodProcessor.this.myHelper); myWrapper = new GrExpressionWrapper(myClosure); PsiType type = myClosure.getType(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java index 59d6e646b3b2..6af7a66c4a2a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java @@ -60,25 +60,25 @@ public abstract class ExtractClosureProcessorBase extends BaseRefactoringProcess return EXTRACT_CLOSURE; } - protected GrClosableBlock generateClosure() { + public static GrClosableBlock generateClosure(GrIntroduceParameterSettings helper) { StringBuilder buffer = new StringBuilder(); buffer.append('{'); - final String[] params = ExtractUtil.getParameterString(myHelper, true); + final String[] params = ExtractUtil.getParameterString(helper, true); if (params.length > 0) { for (String p : params) { buffer.append(p); } buffer.append("->"); } - if (myHelper.getStatements().length > 1) { + if (helper.getStatements().length > 1) { buffer.append('\n'); } - ExtractUtil.generateBody(myHelper, false, buffer); + ExtractUtil.generateBody(helper, false, buffer); buffer.append('}'); - return GroovyPsiElementFactory.getInstance(myHelper.getProject()).createClosureFromText(buffer.toString(), myHelper.getToReplaceIn()); + return GroovyPsiElementFactory.getInstance(helper.getProject()).createClosureFromText(buffer.toString(), helper.getToReplaceIn()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index ccb528dbcf0e..85c2530e7aee 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -98,10 +98,9 @@ public abstract class GrIntroduceHandlerBase -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java index f8cc8b4afb4b..4a2a94c39c91 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java @@ -15,23 +15,31 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.parameter; -import com.intellij.psi.*; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiType; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; 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.ui.IdeBorderFactory; +import com.intellij.ui.components.JBRadioButton; import com.intellij.util.ui.GridBag; +import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; 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.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; @@ -40,38 +48,42 @@ 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.ExtractUtil; +import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo; +import org.jetbrains.plugins.groovy.refactoring.extract.ParameterTablePanel; import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureFromMethodProcessor; import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureHelperImpl; +import org.jetbrains.plugins.groovy.refactoring.extract.closure.ExtractClosureProcessorBase; 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.GrMethodSignatureComponent; import org.jetbrains.plugins.groovy.refactoring.ui.GrTypeComboBox; import javax.swing.*; import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import static com.intellij.refactoring.IntroduceParameterRefactoring.*; public class GrIntroduceParameterDialog extends RefactoringDialog implements GrIntroduceDialog { - private JPanel myContentPane; private GrTypeComboBox myTypeComboBox; private NameSuggestionsField myNameSuggestionsField; private JCheckBox myDeclareFinalCheckBox; private JCheckBox myDelegateViaOverloadingMethodCheckBox; - private JPanel myCheckBoxContainer; - private JCheckBox myReplaceAllOccurrencesCheckBox; - private JRadioButton myDoNotReplaceRadioButton; - private JRadioButton myReplaceFieldsInaccessibleInRadioButton; - private JRadioButton myReplaceAllFieldsRadioButton; - private JCheckBox myRemoveLocalVariableCheckBox; + private JBRadioButton myDoNotReplaceRadioButton; + private JBRadioButton myReplaceFieldsInaccessibleInRadioButton; + private JBRadioButton myReplaceAllFieldsRadioButton; private JPanel myGetterPanel; - private JLabel myTypeLabel; - private JLabel myNameLabel; - private JCheckBox myChangeVarUsages; private IntroduceParameterInfo myInfo; - TObjectIntHashMap toRemoveCBs; + private TObjectIntHashMap toRemoveCBs; + + private GrMethodSignatureComponent mySignature; + private ParameterTablePanel myTable; + private JPanel mySignaturePanel; public GrIntroduceParameterDialog(IntroduceParameterInfo info) { super(info.getProject(), true); @@ -85,31 +97,271 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI cb.setSelected(true); } - JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); + init(); + } - if (myInfo.getStatements().length == 1 && GrIntroduceHandlerBase.findVariable(myInfo.getStatements()[0]) == null) { - myRemoveLocalVariableCheckBox.setSelected(false); - myRemoveLocalVariableCheckBox.setVisible(false); - } - else { - myRemoveLocalVariableCheckBox.setSelected(settings.INTRODUCE_PARAMETER_DELETE_LOCAL_VARIABLE); - } + @Override + protected void init() { + super.init(); + + JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); initReplaceFieldsWithGetters(settings); myDeclareFinalCheckBox.setSelected(hasFinalModifier()); - - myChangeVarUsages.setVisible(info.getToReplaceIn() instanceof GrClosableBlock && info.getToSearchFor() instanceof GrVariable); - myChangeVarUsages.setSelected(true); - - myDelegateViaOverloadingMethodCheckBox.setVisible(info.getToSearchFor() != null); + myDelegateViaOverloadingMethodCheckBox.setVisible(myInfo.getToSearchFor() != null); setTitle(RefactoringBundle.message("introduce.parameter.title")); - init(); + + myTable.init(myInfo); + + final GrParameter[] parameters = myInfo.getToReplaceIn().getParameters(); + toRemoveCBs.forEachEntry(new TObjectIntProcedure() { + @Override + public boolean execute(JCheckBox checkbox, int index) { + checkbox.setSelected(true); + + final GrParameter param = parameters[index]; + final ParameterInfo pinfo = findParamByOldName(param.getName()); + if (pinfo != null) { + pinfo.setPassAsParameter(false); + } + return true; + } + }); + + updateSignature(); + + if (findExpr() != null || findVar() != null) { + mySignaturePanel.setVisible(false); + } + + myTypeComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + mySignaturePanel.setVisible(myTypeComboBox.isClosureSelected()); + pack(); + } + }); + + pack(); + } + + @Override + protected JComponent createCenterPanel() { + JPanel north = new JPanel(); + north.setLayout(new BoxLayout(north, BoxLayout.Y_AXIS)); + north.add(createNamePanel()); + createCheckBoxes(north); + + myGetterPanel = createFieldPanel(); + north.add(myGetterPanel); + + final JPanel root = new JPanel(new BorderLayout()); + mySignaturePanel = createSignaturePanel(); + root.add(mySignaturePanel, BorderLayout.CENTER); + root.add(north, BorderLayout.NORTH); + + return root; + } + + private JPanel createSignaturePanel() { + mySignature = new GrMethodSignatureComponent("", myProject); + myTable = new ParameterTablePanel() { + @Override + protected void updateSignature() { + GrIntroduceParameterDialog.this.updateSignature(); + } + + @Override + protected void doEnterAction() { + clickDefaultButton(); + } + + @Override + protected void doCancelAction() { + GrIntroduceParameterDialog.this.doCancelAction(); + } + }; + + mySignature.setBorder(IdeBorderFactory.createTitledBorder(GroovyRefactoringBundle.message("signature.preview.border.title"), false, false, true)); + + Splitter splitter = new Splitter(true); + + splitter.setFirstComponent(myTable); + splitter.setSecondComponent(mySignature); + + mySignature.setPreferredSize(new Dimension(500, 100)); + mySignature.setSize(new Dimension(500, 100)); + + splitter.setShowDividerIcon(false); + return splitter; + } + + private void updateSignature() { + StringBuilder b = new StringBuilder(); + b.append("{ "); + String[] params = ExtractUtil.getParameterString(myInfo, false); + for (int i = 0; i < params.length; i++) { + if (i > 0) { + b.append(" "); + } + b.append(params[i]); + b.append('\n'); + } + b.append(" ->\n}"); + mySignature.setSignature(b.toString()); + } + + @Override + protected ValidationInfo doValidate() { + final String text = myNameSuggestionsField.getEnteredName(); + if (!StringUtil.isJavaIdentifier(text)) { + return new ValidationInfo(GroovyRefactoringBundle.message("name.is.wrong", text), myNameSuggestionsField); + } + + final Ref info = new Ref(); + toRemoveCBs.forEachEntry(new TObjectIntProcedure() { + @Override + public boolean execute(JCheckBox checkbox, int index) { + if (!checkbox.isSelected()) return true; + + final GrParameter param = myInfo.getToReplaceIn().getParameters()[index]; + final ParameterInfo pinfo = findParamByOldName(param.getName()); + if (pinfo == null || !pinfo.passAsParameter()) return true; + + final String message = GroovyRefactoringBundle.message("you.cannot.pass.as.parameter.0.because.you.remove.1.from.base.method", + pinfo.getName(), param.getName()); + info.set(new ValidationInfo(message)); + return false; + } + }); + return info.get(); + } + + @Nullable + private ParameterInfo findParamByOldName(String name) { + for (ParameterInfo info : myInfo.getParameterInfos()) { + if (name.equals(info.getOldName())) return info; + } + return null; + } + + private JPanel createFieldPanel() { + myDoNotReplaceRadioButton = new JBRadioButton(UIUtil.replaceMnemonicAmpersand("Do n&ot replace")); + myReplaceFieldsInaccessibleInRadioButton = new JBRadioButton(UIUtil.replaceMnemonicAmpersand("Replace fields &inaccessible in usage context")); + myReplaceAllFieldsRadioButton = new JBRadioButton(UIUtil.replaceMnemonicAmpersand("&Replace all fields")); + + myDoNotReplaceRadioButton.setFocusable(false); + myReplaceFieldsInaccessibleInRadioButton.setFocusable(false); + myReplaceAllFieldsRadioButton.setFocusable(false); + + final ButtonGroup group = new ButtonGroup(); + group.add(myDoNotReplaceRadioButton); + group.add(myReplaceFieldsInaccessibleInRadioButton); + group.add(myReplaceAllFieldsRadioButton); + + final JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.add(myDoNotReplaceRadioButton); + panel.add(myReplaceFieldsInaccessibleInRadioButton); + panel.add(myReplaceAllFieldsRadioButton); + + panel.setBorder(IdeBorderFactory.createTitledBorder(UIUtil.replaceMnemonicAmpersand("Replace fields used in expression with their getters"), false, false, true)); + + return panel; + } + + private JPanel createNamePanel() { + final GridBag c = new GridBag().setDefaultAnchor(GridBagConstraints.WEST).setDefaultInsets(1, 1, 1, 1); + final JPanel namePanel = new JPanel(new GridBagLayout()); + final JLabel nameLabel = new JLabel(UIUtil.replaceMnemonicAmpersand("&Name:")); + c.nextLine().next().weightx(0).fillCellNone(); + namePanel.add(nameLabel, c); + + myNameSuggestionsField = createNameField(findVar(), findExpr()); + c.next().weightx(1).fillCellHorizontally(); + namePanel.add(myNameSuggestionsField, c); + nameLabel.setLabelFor(myNameSuggestionsField); + + final JLabel typeLabel = new JLabel(UIUtil.replaceMnemonicAmpersand("&Type:")); + c.nextLine().next().weightx(0).fillCellNone(); + namePanel.add(typeLabel, c); + + myTypeComboBox = createTypeComboBox(findVar(), findExpr()); + c.next().weightx(1).fillCellHorizontally(); + namePanel.add(myTypeComboBox, c); + typeLabel.setLabelFor(myTypeComboBox); + + return namePanel; + } + + private void createCheckBoxes(JPanel panel) { + myDeclareFinalCheckBox = new JCheckBox(UIUtil.replaceMnemonicAmpersand("Declare &final")); + myDeclareFinalCheckBox.setFocusable(false); + panel.add(myDeclareFinalCheckBox); + + myDelegateViaOverloadingMethodCheckBox = new JCheckBox(UIUtil.replaceMnemonicAmpersand("De&legate via overloading method")); + myDelegateViaOverloadingMethodCheckBox.setFocusable(false); + panel.add(myDelegateViaOverloadingMethodCheckBox); + + for (Object o : toRemoveCBs.keys()) { + final JCheckBox cb = (JCheckBox)o; + cb.setFocusable(false); + panel.add(cb); + } + } + + private GrTypeComboBox createTypeComboBox(GrVariable var, GrExpression expr) { + GrTypeComboBox box; + if (var != null) { + box = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType()); + } + else if (expr != null) { + box = GrTypeComboBox.createTypeComboBoxFromExpression(expr); + } + else { + box = GrTypeComboBox.createEmptyTypeComboBox(); + } + + final ExtractClosureHelperImpl mockHelper = new ExtractClosureHelperImpl(myInfo, "__test___n_", false, new TIntArrayList(), false, 0); + final PsiType returnType = ExtractClosureProcessorBase.generateClosure(mockHelper).getReturnType(); + + box.addClosureTypesFrom(returnType, mockHelper.getContext()); + if (expr == null && var == null) { + box.setSelectedIndex(box.getItemCount() - 1); + } + return box; + } + + private NameSuggestionsField createNameField(GrVariable var, GrExpression expr) { + String[] possibleNames; + if (expr != null) { + final GrIntroduceContext + introduceContext = new GrIntroduceContextImpl(myProject, null, expr, var, PsiElement.EMPTY_ARRAY, myInfo.getToReplaceIn()); + final GroovyFieldValidator validator = new GroovyFieldValidator(introduceContext); + possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(expr, validator, true); + } + else if (var != null) { + final GrIntroduceContext introduceContext = + new GrIntroduceContextImpl(myProject, null, expr, var, PsiElement.EMPTY_ARRAY, myInfo.getToReplaceIn()); + final GroovyFieldValidator validator = new GroovyFieldValidator(introduceContext); + possibleNames = GroovyNameSuggestionUtil.suggestVariableNameByType(var.getType(), validator); + } + else { + possibleNames = new String[]{"closure"}; + } + + if (var != null) { + String[] arr = new String[possibleNames.length + 1]; + arr[0] = var.getName(); + System.arraycopy(possibleNames, 0, arr, 1, possibleNames.length); + possibleNames = arr; + } + return new NameSuggestionsField(possibleNames, myProject, GroovyFileType.GROOVY_FILE_TYPE); } private void initReplaceFieldsWithGetters(JavaRefactoringSettings settings) { - final PsiField[] usedFields = GroovyIntroduceParameterUtil.findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass()); myGetterPanel.setVisible(usedFields.length > 0); switch (settings.INTRODUCE_PARAMETER_REPLACE_FIELDS_WITH_GETTERS) { @@ -182,27 +434,11 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI private void saveSettings() { final JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); settings.INTRODUCE_PARAMETER_CREATE_FINALS = myDeclareFinalCheckBox.isSelected(); - if (myRemoveLocalVariableCheckBox.isVisible()) { - settings.INTRODUCE_PARAMETER_DELETE_LOCAL_VARIABLE = myRemoveLocalVariableCheckBox.isSelected(); - } if (myGetterPanel.isVisible()) { settings.INTRODUCE_PARAMETER_REPLACE_FIELDS_WITH_GETTERS = getReplaceFieldsWithGetter(); } } - @Override - protected JComponent createCenterPanel() { - final GridBag c = new GridBag().setDefaultAnchor(GridBagConstraints.WEST).setLine(4); - for (Object o : toRemoveCBs.keys()) { - c.nextLine(); - myCheckBoxContainer.add(((JCheckBox)o), c); - } - - myNameLabel.setLabelFor(myNameSuggestionsField); - myTypeLabel.setLabelFor(myTypeComboBox); - return myContentPane; - } - @Override public GrIntroduceParameterSettings getSettings() { return null; @@ -235,42 +471,6 @@ public class GrIntroduceParameterDialog extends RefactoringDialog implements GrI return list; } - private void createUIComponents() { - 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.createEmptyTypeComboBox(); - } - - myTypeComboBox.addType(JavaPsiFacade.getElementFactory(myProject).createTypeFromText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, myInfo.getContext())); - - String[] possibleNames; - final GrIntroduceContext introduceContext = new GrIntroduceContextImpl(myProject, null, expr, var, PsiElement.EMPTY_ARRAY, myInfo.getToReplaceIn()); - final GroovyFieldValidator validator = new GroovyFieldValidator(introduceContext); - if (expr != null) { - possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(expr, validator, true); - } - else if (var != null) { - possibleNames = GroovyNameSuggestionUtil.suggestVariableNameByType(var.getType(), validator); - } - else { - possibleNames = ArrayUtil.EMPTY_STRING_ARRAY; - } - - if (var != null) { - String[] arr = new String[possibleNames.length + 1]; - arr[0] = var.getName(); - System.arraycopy(possibleNames, 0, arr, 1, possibleNames.length); - possibleNames = arr; - } - myNameSuggestionsField = new NameSuggestionsField(possibleNames, myProject, GroovyFileType.GROOVY_FILE_TYPE); - } @Nullable private GrVariable findVar() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java index 80005da4ff5a..5a41e8ec0109 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java @@ -25,6 +25,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.*; @@ -99,8 +100,10 @@ public class GrTypeComboBox extends ComboBox { } } - public void addType(PsiType type) { - addItem(new PsiTypeItem(type)); + public void addClosureTypesFrom(PsiType type, PsiElement context) { + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject()); + final PsiType cl = factory.createTypeFromText(GroovyCommonClassNames.GROOVY_LANG_CLOSURE + '<' + type.getCanonicalText() + '>', context); + addItem(new PsiTypeItem(cl, true)); } @Nullable @@ -110,6 +113,10 @@ public class GrTypeComboBox extends ComboBox { return ((PsiTypeItem)selected).getType(); } + public boolean isClosureSelected() { + return ((PsiTypeItem)getSelectedItem()).isClosure(); + } + private static Map getCompatibleTypeNames(@NotNull PsiType type, @Nullable PsiType min, @@ -165,8 +172,15 @@ public class GrTypeComboBox extends ComboBox { @Nullable private final PsiType myType; + private final boolean isClosure; + private PsiTypeItem(final PsiType type) { + this(type, false); + } + + private PsiTypeItem(final PsiType type, boolean closure) { myType = type; + isClosure = closure; } @Nullable @@ -200,5 +214,9 @@ public class GrTypeComboBox extends ComboBox { public String toString() { return myType == null ? "def" : myType.getPresentableText(); } + + public boolean isClosure() { + return isClosure; + } } }