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;
/**
* @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;
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();
super.init();
}
- @Override
- protected void doOKAction() {
- super.doOKAction();
-
+ private void stopEditing() {
+ TableUtil.stopEditing(myParameterTable);
}
@Override
}
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());
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) {
}
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();
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();
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
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
@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;
+ }
}
}