change signature dialog
authorMaxim Medvedev <maxim.medvedev@jetbrains.com>
Mon, 15 Mar 2010 16:20:33 +0000 (19:20 +0300)
committerMaxim Medvedev <maxim.medvedev@jetbrains.com>
Mon, 15 Mar 2010 16:20:33 +0000 (19:20 +0300)
java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureViewDescriptor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java

index 86ce5b030019d87ee55d17c2ea77c1ff0271f47e..cd453595851e512d4847f8948baf3292c5f91c05 100644 (file)
  */
 package com.intellij.refactoring.changeSignature;
 
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiMethod;
 import com.intellij.refactoring.RefactoringBundle;
 import com.intellij.usageView.UsageViewBundle;
 import com.intellij.usageView.UsageViewDescriptor;
 import com.intellij.usageView.UsageViewUtil;
-import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
 
-class ChangeSignatureViewDescriptor implements UsageViewDescriptor {
+public class ChangeSignatureViewDescriptor implements UsageViewDescriptor {
 
   private final PsiMethod myMethod;
   private final String myProcessedElementsHeader;
index 6baa6a42b2b412260b9972e51a67835d5d71a643..9036d53d1a4ae26b100b8a3cd0902b739c50554f 100644 (file)
                   <text value="Protected"/>
                 </properties>
               </component>
-              <component id="8f6d2" class="javax.swing.JRadioButton" binding="myPrivateRadioButton1" default-binding="true">
+              <component id="8f6d2" class="javax.swing.JRadioButton" binding="myPrivateRadioButton" default-binding="true">
                 <constraints>
                   <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                 </constraints>
index 6b812eb426e72c2c3611927586675f0b6545bfef..22cf9c2333ebbe92de37cc2805de603c790425da 100644 (file)
@@ -17,17 +17,23 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature;
 
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiType;
 import com.intellij.psi.PsiTypeCodeFragment;
+import com.intellij.refactoring.HelpID;
 import com.intellij.refactoring.ui.CodeFragmentTableCellEditor;
 import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer;
+import com.intellij.refactoring.ui.RefactoringDialog;
+import com.intellij.refactoring.util.CanonicalTypes;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
 import com.intellij.ui.EditorTextField;
+import com.intellij.ui.TableUtil;
 import com.intellij.util.ui.Table;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.GroovyFileType;
 import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
@@ -44,13 +50,12 @@ import java.util.List;
 /**
  * @author Maxim.Medvedev
  */
-public class GrChangeSignatureDialog extends DialogWrapper {
+public class GrChangeSignatureDialog extends RefactoringDialog {
   private EditorTextField myNameField;
   private EditorTextField myReturnTypeField;
   private JRadioButton myPublicRadioButton;
-
   private JRadioButton myProtectedRadioButton;
-  private JRadioButton myPrivateRadioButton1;
+  private JRadioButton myPrivateRadioButton;
   private JPanel myParametersPanel;
   private Table myParameterTable;
   private JButton myAddButton;
@@ -61,12 +66,12 @@ public class GrChangeSignatureDialog extends DialogWrapper {
   private JLabel mySignatureLabel;
   private GrParameterTableModel myParameterModel;
   private GrMethod myMethod;
-  private Project myProject;
+//  private Project myProject;
   private PsiTypeCodeFragment myReturnTypeCodeFragment;
+  private GroovyCodeFragment myNameCodeFragment;
 
   public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) {
     super(project, true);
-    myProject = project;
     myMethod = method;
     init();
     configureParameterButtons();
@@ -121,10 +126,8 @@ public class GrChangeSignatureDialog extends DialogWrapper {
     super.init();
   }
 
-  @Override
-  protected void doOKAction() {
-    super.doOKAction();
-
+  private void stopEditing() {
+    TableUtil.stopEditing(myParameterTable);
   }
 
   @Override
@@ -139,7 +142,10 @@ public class GrChangeSignatureDialog extends DialogWrapper {
   }
 
   private void createNameAndReturnTypeEditors() {
-    myNameField = new EditorTextField("", myProject, GroovyFileType.GROOVY_FILE_TYPE);
+    myNameCodeFragment = new GroovyCodeFragment(myProject, "");
+    myNameField = new EditorTextField(PsiDocumentManager.getInstance(myProject).getDocument(myNameCodeFragment), myProject,
+                                      myNameCodeFragment.getFileType());
+
     myReturnTypeCodeFragment = JavaPsiFacade.getInstance(myProject).getElementFactory().createTypeCodeFragment("", myMethod, true, true);
     final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myReturnTypeCodeFragment);
     myReturnTypeField = new EditorTextField(document, myProject, myReturnTypeCodeFragment.getFileType());
@@ -166,8 +172,10 @@ public class GrChangeSignatureDialog extends DialogWrapper {
     myParameterTable.getColumnModel().getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject));
     myParameterTable.getColumnModel().getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject));
 
-    myParameterTable.setRowSelectionInterval(0, 0);
-    myParameterTable.setColumnSelectionInterval(0, 0);
+    if (myParameterTable.getRowCount() > 0) {
+      myParameterTable.setRowSelectionInterval(0, 0);
+      myParameterTable.setColumnSelectionInterval(0, 0);
+    }
 
     myParameterModel.addTableModelListener(new TableModelListener() {
       public void tableChanged(TableModelEvent e) {
@@ -188,13 +196,19 @@ public class GrChangeSignatureDialog extends DialogWrapper {
   }
 
   private String generateSignatureText() {
-    String name = myNameField.getText().trim();
+    String name = getNewName();
     String type = myReturnTypeField.getText().trim();
-    if (type.length() == 0) {
-      type = GrModifier.DEF;
-    }
 
     StringBuilder builder = new StringBuilder();
+    if (myPublicRadioButton.isSelected() && type.length() == 0) {
+      builder.append(GrModifier.DEF);
+    }
+    if (myPrivateRadioButton.isSelected()) {
+      builder.append(GrModifier.PRIVATE).append(' ');
+    }
+    else if (myProtectedRadioButton.isSelected()) {
+      builder.append(GrModifier.PROTECTED).append(' ');
+    }
     builder.append(type).append(' ');
     builder.append(name).append('(');
     final List<GrParameterInfo> infos = myParameterModel.getParameterInfos();
@@ -214,7 +228,7 @@ public class GrChangeSignatureDialog extends DialogWrapper {
   private static void generateParameterText(GrParameterInfo info, StringBuilder builder) {
     final PsiTypeCodeFragment typeFragment = info.getType();
     builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' ');
-    final GroovyCodeFragment nameFragment = info.getName();
+    final GroovyCodeFragment nameFragment = info.getNameFragment();
     builder.append(nameFragment != null ? nameFragment.getText().trim() : "");
     final GroovyCodeFragment defaultInitializer = info.getDefaultInitializer();
 
@@ -223,4 +237,91 @@ public class GrChangeSignatureDialog extends DialogWrapper {
       builder.append(" = ").append(defaultInitializerText);
     }
   }
+
+  @Override
+  protected void doAction() {
+    if (!validateInputData()) {
+      return;
+    }
+
+    stopEditing();
+    String modifier = "";
+    if (myPublicRadioButton.isSelected()) {
+      modifier = GrModifier.PUBLIC;
+    }
+    else if (myPrivateRadioButton.isSelected()) {
+      modifier = GrModifier.PRIVATE;
+    }
+    else if (myProtectedRadioButton.isSelected()) {
+      modifier = GrModifier.PROTECTED;
+    }
+
+    PsiType returnType = null;
+    try {
+      returnType = myReturnTypeCodeFragment.getType();
+    }
+    catch (PsiTypeCodeFragment.TypeSyntaxException e) {
+      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+    }
+    catch (PsiTypeCodeFragment.NoTypeException e) {
+      returnType = PsiType.NULL;
+    }
+
+    String newName = getNewName();
+    final List<GrParameterInfo> parameterInfos = myParameterModel.getParameterInfos();
+    invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeSignatureProcessor.GrChangeInfoImpl(myMethod, modifier,
+                                                                                                                CanonicalTypes.createTypeWrapper(
+                                                                                                                  returnType), newName,
+                                                                                                                parameterInfos)));
+
+  }
+
+  private String getNewName() {
+    return myNameField.getText().trim();
+  }
+
+  private boolean validateInputData() {
+    if (!checkName()) {
+      CommonRefactoringUtil.showErrorHint(myProject, null, "Name is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE);
+      return false;
+    }
+
+    if (!checkType(myReturnTypeCodeFragment)) {
+      CommonRefactoringUtil.showErrorHint(myProject, null, "Return type is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE);
+    }
+
+    for (GrParameterInfo info : myParameterModel.getParameterInfos()) {
+      if (!checkType(info.getType())) {
+        CommonRefactoringUtil
+          .showErrorHint(myProject, null, "Type for parameter " + info.getName() + " is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE);
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private boolean checkType(PsiTypeCodeFragment typeCodeFragment) {
+    try {
+      typeCodeFragment.getType();
+    }
+    catch (PsiTypeCodeFragment.TypeSyntaxException e) {
+      return false;
+    }
+    catch (PsiTypeCodeFragment.NoTypeException e) {
+      return true;
+    }
+    return true;
+  }
+
+  private boolean checkName() {
+    final String newName = getNewName();
+    if (StringUtil.isJavaIdentifier(newName)) return true;
+    try {
+      GroovyPsiElementFactory.getInstance(myProject).createMethodFromText("def " + newName + "(){}");
+    }
+    catch (Throwable e) {
+      return false;
+    }
+    return true;
+  }
 }
\ No newline at end of file
index 76d650d3d2f366124f981934ce71665101533f92..0826dcf688e4f577abcb034cb2a73f6838c073b7 100644 (file)
 package org.jetbrains.plugins.groovy.refactoring.changeSignature;
 
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
 import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.refactoring.changeSignature.ChangeInfo;
+import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor;
+import com.intellij.refactoring.changeSignature.ParameterInfo;
+import com.intellij.refactoring.util.CanonicalTypes;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usageView.UsageViewDescriptor;
+import com.intellij.util.containers.MultiMap;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+
+import java.util.List;
 
 /**
  * @author Maxim.Medvedev
  */
-public class GrChangeSignatureProcessor extends BaseRefactoringProcessor{
-  public GrChangeSignatureProcessor(Project project) {
+public class GrChangeSignatureProcessor extends BaseRefactoringProcessor {
+  private final GrChangeInfoImpl myInfo;
+
+  //private
+
+  public GrChangeSignatureProcessor(Project project, GrChangeInfoImpl changeInfo) {
     super(project);
+    myInfo = changeInfo;
   }
 
   @Override
   protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
-    return null;  //To change body of implemented methods use File | Settings | File Templates.
+    return new ChangeSignatureViewDescriptor(myInfo.getMethod());
   }
 
   @NotNull
@@ -48,12 +63,95 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor{
 
   @Override
   protected void performRefactoring(UsageInfo[] usages) {
-    //To change body of implemented methods use File | Settings | File Templates.
+    changeMethod();
+  }
+
+  private void changeMethod() {
+    final PsiMethod method = myInfo.getMethod();
+    if (myInfo.isChangeName()) {
+      method.setName(myInfo.getNewName());
+    }
+
+    if (myInfo.isChangeVisibility()) {
+      method.getModifierList().setModifierProperty(myInfo.getVisibilityModifier(), true);
+    }
   }
 
   @Override
   protected String getCommandName() {
     return "";
-    //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod()));
+    //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myInfo.getMethod()));
+  }
+
+
+  private MultiMap<PsiElement, String> findConflicts(Ref<UsageInfo[]> refUsages) {
+    return new MultiMap<PsiElement, String>();//todo
+  }
+
+  @Override
+  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
+    return showConflicts(findConflicts(refUsages));
+  }
+
+  static class GrChangeInfoImpl implements ChangeInfo {
+    private GrMethod myMethod;
+    private String myNewName;
+    private CanonicalTypes.Type myReturnType;
+    private String myVisibilityModifier;
+    private List<GrParameterInfo> myParameters;
+    private boolean myChangeParameters = false;
+
+    public GrChangeInfoImpl(GrMethod method,
+                             String visibilityModifier,
+                             CanonicalTypes.Type returnType,
+                             String newName,
+                             List<GrParameterInfo> parameters) {
+      myMethod = method;
+      myVisibilityModifier = visibilityModifier;
+      myReturnType = returnType;
+      myParameters = parameters;
+      myNewName = newName;
+
+      final int oldParameterCount = myMethod.getParameters().length;
+      if (oldParameterCount != myParameters.size()) {
+        myChangeParameters = true;
+      }
+
+      for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
+        GrParameterInfo parameter = parameters.get(i);
+        if (parameter.getOldIndex() != i) {
+          myChangeParameters = true;
+        }
+      }
+    }
+
+    @NotNull
+    public ParameterInfo[] getNewParameters() {
+      return myParameters.toArray(new GrParameterInfo[myParameters.size()]);
+    }
+
+    public boolean isParameterSetOrOrderChanged() {
+      return myChangeParameters;
+    }
+
+    public PsiMethod getMethod() {
+      return myMethod;
+    }
+
+    public boolean isChangeVisibility() {
+      return !myMethod.getModifierList().hasModifierProperty(myVisibilityModifier);
+    }
+
+    public boolean isChangeName() {
+      return !myMethod.getName().equals(myNewName);
+    }
+
+    public String getNewName() {
+      return myNewName;
+    }
+
+    public String getVisibilityModifier() {
+      return myVisibilityModifier;
+    }
   }
 }
index bdf0ff357c4f604db31a49949fc07fc44812be8e..127fea01d7ee478e513352b752234cd6a8ebd631 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiType;
 import com.intellij.psi.PsiTypeCodeFragment;
+import com.intellij.refactoring.changeSignature.ParameterInfo;
 import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
@@ -27,7 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
 /**
  * @author Maxim.Medvedev
  */
-public class GrParameterInfo {
+public class GrParameterInfo implements ParameterInfo{
   private GroovyCodeFragment myName;
   private GroovyCodeFragment myDefaultValue;
   private PsiTypeCodeFragment myType;
@@ -56,11 +57,11 @@ public class GrParameterInfo {
     myDefaultInitializer = new GroovyCodeFragment(project, "");
   }
 
-  public GroovyCodeFragment getName() {
+  public GroovyCodeFragment getNameFragment() {
     return myName;
   }
 
-  public GroovyCodeFragment getDefaultValue() {
+  public GroovyCodeFragment getDefaultValueFragment() {
     return myDefaultValue;
   }
 
@@ -72,7 +73,15 @@ public class GrParameterInfo {
     return myDefaultInitializer;
   }
 
-  public int getPosition() {
+  public String getName() {
+    return myName.getText().trim();
+  }
+
+  public int getOldIndex() {
     return myPosition;
   }
+
+  public String getDefaultValue() {
+    return myDefaultValue.getText().trim();
+  }
 }