mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
introduce parameter object: add setters/getters, fix visibility for existing class
This commit is contained in:
+2
-2
@@ -35,8 +35,8 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -156,7 +156,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
|
||||
list.deleteChildRange(list.getFirstChild(), list.getLastChild());
|
||||
return;
|
||||
}
|
||||
RefactoringConflictsUtil.setVisibility(list, getVisibility(parentClass, targetClass));
|
||||
VisibilityUtil.setVisibility(list, getVisibility(parentClass, targetClass));
|
||||
}
|
||||
|
||||
protected String getVisibility(PsiClass parentClass, PsiClass targetClass) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -212,7 +211,7 @@ public class GenerateMembersUtil {
|
||||
newMethod = factory.createMethod(method.getName(), substituteType(substitutor, returnType));
|
||||
}
|
||||
|
||||
RefactoringConflictsUtil.setVisibility(newMethod.getModifierList(), VisibilityUtil.getVisibilityModifier(method.getModifierList()));
|
||||
VisibilityUtil.setVisibility(newMethod.getModifierList(), VisibilityUtil.getVisibilityModifier(method.getModifierList()));
|
||||
|
||||
PsiElement navigationElement = method.getNavigationElement();
|
||||
PsiDocComment docComment = ((PsiDocCommentOwner)navigationElement).getDocComment();
|
||||
|
||||
+2
-2
@@ -391,7 +391,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
|
||||
private void addInaccessibilityDescriptions(Set<UsageInfo> usages, MultiMap<PsiElement, String> conflictDescriptions) throws IncorrectOperationException {
|
||||
PsiMethod method = myChangeInfo.getMethod();
|
||||
PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy();
|
||||
RefactoringConflictsUtil.setVisibility(modifierList, myNewVisibility);
|
||||
VisibilityUtil.setVisibility(modifierList, myNewVisibility);
|
||||
|
||||
for (Iterator<UsageInfo> iterator = usages.iterator(); iterator.hasNext();) {
|
||||
UsageInfo usageInfo = iterator.next();
|
||||
@@ -1035,7 +1035,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
|
||||
final String highestVisibility = isOriginal ?
|
||||
myNewVisibility :
|
||||
VisibilityUtil.getHighestVisibility(myNewVisibility, VisibilityUtil.getVisibilityModifier(modifierList));
|
||||
RefactoringConflictsUtil.setVisibility(modifierList, highestVisibility);
|
||||
VisibilityUtil.setVisibility(modifierList, highestVisibility);
|
||||
}
|
||||
|
||||
if (myChangeInfo.isNameChanged) {
|
||||
|
||||
+2
-2
@@ -179,10 +179,10 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
|
||||
final PsiModifierList copy = (PsiModifierList)myMethod.getModifierList().copy();
|
||||
if (myNewVisibility != null) {
|
||||
if (myNewVisibility.equals(VisibilityUtil.ESCALATE_VISIBILITY)) {
|
||||
RefactoringConflictsUtil.setVisibility(copy, PsiModifier.PUBLIC);
|
||||
VisibilityUtil.setVisibility(copy, PsiModifier.PUBLIC);
|
||||
}
|
||||
else {
|
||||
RefactoringConflictsUtil.setVisibility(copy, myNewVisibility);
|
||||
VisibilityUtil.setVisibility(copy, myNewVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-16
@@ -42,7 +42,6 @@ import com.intellij.refactoring.psi.MethodInheritanceUtils;
|
||||
import com.intellij.refactoring.psi.TypeParametersVisitor;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
@@ -231,31 +230,18 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
for (PsiMethod method : methods) {
|
||||
final PsiMethod member = psiClass.findMethodBySignature(method, false);
|
||||
if (member != null) {
|
||||
fixVisibility(usageInfos, member);
|
||||
VisibilityUtil.fixVisibility(usageInfos, member, myNewVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiField field : fields) {
|
||||
final PsiField member = psiClass.findFieldByName(field.getName(), false);
|
||||
if (member != null) {
|
||||
fixVisibility(usageInfos, member);
|
||||
VisibilityUtil.fixVisibility(usageInfos, member, myNewVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixVisibility(UsageInfo[] usageInfos, PsiMember member) {
|
||||
if (VisibilityUtil.ESCALATE_VISIBILITY.equals(myNewVisibility)) {
|
||||
for (UsageInfo info : usageInfos) {
|
||||
final PsiElement element = info.getElement();
|
||||
if (element != null) {
|
||||
VisibilityUtil.escalateVisibility(member, element);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RefactoringConflictsUtil.setVisibility(member.getModifierList(), myNewVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void buildDelegate() {
|
||||
final PsiManager manager = sourceClass.getManager();
|
||||
|
||||
+3
-2
@@ -174,8 +174,9 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
}
|
||||
//todo check accessibility conflicts
|
||||
}
|
||||
for (PsiElement element : pushDownConflicts.getConflicts().keySet()) {
|
||||
conflicts.put(element, pushDownConflicts.getConflicts().get(element));
|
||||
final MultiMap<PsiElement, String> conflictsMap = pushDownConflicts.getConflicts();
|
||||
for (PsiElement element : conflictsMap.keySet()) {
|
||||
conflicts.put(element, conflictsMap.get(element));
|
||||
}
|
||||
checkConflicts(refUsages, conflicts);
|
||||
return showConflicts(conflicts);
|
||||
|
||||
+42
-8
@@ -20,7 +20,9 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -30,8 +32,10 @@ import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
|
||||
import com.intellij.refactoring.ui.RefactoringDialog;
|
||||
import com.intellij.refactoring.ui.VisibilityPanel;
|
||||
import com.intellij.refactoring.util.ParameterTablePanel;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.RecentsManager;
|
||||
import com.intellij.ui.ReferenceEditorComboWithBrowseButton;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -69,7 +73,11 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
private JCheckBox keepMethodAsDelegate;
|
||||
private ReferenceEditorComboWithBrowseButton packageTextField;
|
||||
private ReferenceEditorComboWithBrowseButton existingClassField;
|
||||
private JPanel myVisibilityComponent;
|
||||
private JCheckBox myGenerateAccessorsCheckBox;
|
||||
private VisibilityPanel myVisibilityPanel;
|
||||
private static final String RECENTS_KEY = "IntroduceParameterObject.RECENTS_KEY";
|
||||
private static final String EXISTING_KEY = "IntroduceParameterObject.EXISTING_KEY";
|
||||
|
||||
public IntroduceParameterObjectDialog(PsiMethod sourceMethod) {
|
||||
super(sourceMethod.getProject(), true);
|
||||
@@ -119,9 +127,14 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
createNewClassButton.addActionListener(listener);
|
||||
myCreateInnerClassRadioButton.addActionListener(listener);
|
||||
toggleRadioEnablement();
|
||||
|
||||
myVisibilityPanel = new VisibilityPanel(true, true);
|
||||
myVisibilityPanel.setVisibility(null);
|
||||
myVisibilityComponent.add(myVisibilityPanel, BorderLayout.WEST);
|
||||
}
|
||||
|
||||
private void toggleRadioEnablement() {
|
||||
enableGenerateAccessors();
|
||||
UIUtil.setEnabled(myUseExistingPanel, useExistingClassButton.isSelected(), true);
|
||||
UIUtil.setEnabled(myCreateNewClassPanel, createNewClassButton.isSelected(), true);
|
||||
UIUtil.setEnabled(myInnerClassPanel, myCreateInnerClassRadioButton.isSelected(), true);
|
||||
@@ -137,22 +150,18 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
final boolean keepMethod = keepMethodAsDelegate();
|
||||
final String className;
|
||||
final String packageName;
|
||||
final List<String> getterNames;
|
||||
final boolean createInnerClass = myCreateInnerClassRadioButton.isSelected();
|
||||
if (createInnerClass) {
|
||||
className = getInnerClassName();
|
||||
packageName = "";
|
||||
getterNames = null;
|
||||
} else if (useExistingClass) {
|
||||
final String existingClassName = getExistingClassName();
|
||||
getterNames = new ArrayList<String>();
|
||||
className = StringUtil.getShortName(existingClassName);
|
||||
packageName = StringUtil.getPackageName(existingClassName);
|
||||
}
|
||||
else {
|
||||
packageName = getPackageName();
|
||||
className = getClassName();
|
||||
getterNames = null;
|
||||
}
|
||||
List<ParameterTablePanel.VariableData> parameters = new ArrayList<ParameterTablePanel.VariableData>();
|
||||
for (ParameterTablePanel.VariableData data : parameterInfo) {
|
||||
@@ -161,8 +170,9 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
}
|
||||
}
|
||||
invokeRefactoring(new IntroduceParameterObjectProcessor(className, packageName, sourceMethod,
|
||||
parameters.toArray(new ParameterTablePanel.VariableData[parameters.size()]), getterNames, keepMethod, useExistingClass,
|
||||
createInnerClass));
|
||||
parameters.toArray(new ParameterTablePanel.VariableData[parameters.size()]),
|
||||
keepMethod, useExistingClass,
|
||||
createInnerClass, myVisibilityPanel.getVisibility(), myGenerateAccessorsCheckBox.isSelected()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,11 +301,35 @@ public class IntroduceParameterObjectDialog extends RefactoringDialog {
|
||||
if (selectedClass != null) {
|
||||
final String className = selectedClass.getQualifiedName();
|
||||
existingClassField.setText(className);
|
||||
RecentsManager.getInstance(myProject).registerRecentEntry(EXISTING_KEY, className);
|
||||
}
|
||||
}
|
||||
}, "", PsiManager.getInstance(myProject), true, RECENTS_KEY);
|
||||
}, "", PsiManager.getInstance(myProject), true, EXISTING_KEY);
|
||||
|
||||
existingClassField.getChildComponent().getDocument().addDocumentListener(adapter);
|
||||
existingClassField.getChildComponent().getDocument().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
|
||||
validateButtons();
|
||||
enableGenerateAccessors();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void enableGenerateAccessors() {
|
||||
boolean existingNotALibraryClass = false;
|
||||
if (useExistingClassButton.isSelected()) {
|
||||
final PsiClass selectedClass =
|
||||
JavaPsiFacade.getInstance(myProject).findClass(existingClassField.getText(), GlobalSearchScope.projectScope(myProject));
|
||||
if (selectedClass != null) {
|
||||
final PsiFile containingFile = selectedClass.getContainingFile();
|
||||
if (containingFile != null) {
|
||||
final VirtualFile virtualFile = containingFile.getVirtualFile();
|
||||
if (virtualFile != null) {
|
||||
existingNotALibraryClass = ProjectRootManager.getInstance(myProject).getFileIndex().isInSourceContent(virtualFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myGenerateAccessorsCheckBox.setEnabled(existingNotALibraryClass);
|
||||
}
|
||||
}
|
||||
|
||||
+30
-12
@@ -24,7 +24,7 @@
|
||||
</hspacer>
|
||||
<component id="85290" class="javax.swing.JTextField" binding="sourceMethodTextField">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<grid row="1" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
<gridbag weightx="0.0" weighty="0.0"/>
|
||||
@@ -33,7 +33,7 @@
|
||||
</component>
|
||||
<grid id="79318" layout-manager="GridBagLayout">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="4" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
@@ -168,24 +168,42 @@
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<component id="f0f3" class="javax.swing.JCheckBox" binding="keepMethodAsDelegate">
|
||||
<constraints>
|
||||
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Keep method as &delegate"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="783a4" binding="myParamsPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<grid row="7" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="1.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none" title="Parameters to Extract"/>
|
||||
<children/>
|
||||
</grid>
|
||||
<component id="f0f3" class="javax.swing.JCheckBox" binding="keepMethodAsDelegate">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Keep method as &delegate"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="d3a44" binding="myVisibilityComponent" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="6" column="3" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
<component id="286f3" class="javax.swing.JCheckBox" binding="myGenerateAccessorsCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<gridbag weightx="0.0" weighty="0.0"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="&Generate accessors"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
+138
-157
@@ -16,28 +16,22 @@
|
||||
package com.intellij.refactoring.introduceparameterobject;
|
||||
|
||||
import com.intellij.ide.util.PackageUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.MergeMethodArguments;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.ReplaceParameterAssignmentWithCall;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.ReplaceParameterIncrementDecrement;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.ReplaceParameterReferenceWithCall;
|
||||
import com.intellij.refactoring.introduceparameterobject.usageInfo.*;
|
||||
import com.intellij.refactoring.psi.PropertyUtils;
|
||||
import com.intellij.refactoring.psi.TypeParametersVisitor;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
@@ -47,11 +41,16 @@ import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringProcessor {
|
||||
private static final Logger logger = Logger.getInstance("com.siyeh.rpp.introduceparameterobject.IntroduceParameterObjectProcessor");
|
||||
@@ -59,32 +58,39 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
private final PsiMethod method;
|
||||
private final String className;
|
||||
private final String packageName;
|
||||
private final List<String> getterNames;
|
||||
private final boolean keepMethodAsDelegate;
|
||||
private final boolean myUseExistingClass;
|
||||
private final boolean myCreateInnerClass;
|
||||
private final List<ParameterTablePanel.VariableData> parameters;
|
||||
private final String myNewVisibility;
|
||||
private final boolean myGenerateAccessors;
|
||||
private final List<ParameterChunk> parameters;
|
||||
private final int[] paramsToMerge;
|
||||
private final List<PsiTypeParameter> typeParams;
|
||||
private final Set<PsiParameter> paramsNeedingSetters = new HashSet<PsiParameter>();
|
||||
private final Set<PsiParameter> paramsNeedingGetters = new HashSet<PsiParameter>();
|
||||
private final PsiClass existingClass;
|
||||
private boolean myExistingClassCompatible = true;
|
||||
private PsiMethod myExistingClassCompatibleConstructor;
|
||||
|
||||
public IntroduceParameterObjectProcessor(String className,
|
||||
String packageName,
|
||||
PsiMethod method,
|
||||
ParameterTablePanel.VariableData[] parameters,
|
||||
List<String> getterNames,
|
||||
boolean keepMethodAsDelegate, final boolean useExistingClass, final boolean createInnerClass) {
|
||||
ParameterTablePanel.VariableData[] parameters, boolean keepMethodAsDelegate, final boolean useExistingClass,
|
||||
final boolean createInnerClass,
|
||||
String newVisibility,
|
||||
boolean generateAccessors) {
|
||||
super(method.getProject());
|
||||
this.method = method;
|
||||
this.className = className;
|
||||
this.packageName = packageName;
|
||||
this.getterNames = getterNames;
|
||||
this.keepMethodAsDelegate = keepMethodAsDelegate;
|
||||
myUseExistingClass = useExistingClass;
|
||||
myCreateInnerClass = createInnerClass;
|
||||
this.parameters = new ArrayList<ParameterTablePanel.VariableData>(Arrays.asList(parameters));
|
||||
myNewVisibility = newVisibility;
|
||||
myGenerateAccessors = generateAccessors;
|
||||
this.parameters = new ArrayList<ParameterChunk>();
|
||||
for (ParameterTablePanel.VariableData parameter : parameters) {
|
||||
this.parameters.add(new ParameterChunk(parameter));
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
final PsiParameter[] methodParams = parameterList.getParameters();
|
||||
paramsToMerge = new int[parameters.length];
|
||||
@@ -123,14 +129,8 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
if (existingClass == null) {
|
||||
conflicts.putValue(null, RefactorJBundle.message("cannot.perform.the.refactoring") + "Could not find the selected class");
|
||||
}
|
||||
final String incompatibilityMessage = "Selected class is not compatible with chosen parameters";
|
||||
if (!myExistingClassCompatible) {
|
||||
conflicts
|
||||
.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + incompatibilityMessage);
|
||||
|
||||
}
|
||||
if (!paramsNeedingSetters.isEmpty()) {
|
||||
conflicts.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + incompatibilityMessage);
|
||||
if (myExistingClassCompatibleConstructor == null) {
|
||||
conflicts.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") + "Selected class has no compatible constructors");
|
||||
}
|
||||
}
|
||||
else if (existingClass != null) {
|
||||
@@ -138,16 +138,27 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
RefactorJBundle.message("cannot.perform.the.refactoring") +
|
||||
RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name"));
|
||||
}
|
||||
for (UsageInfo usageInfo : refUsages.get()) {
|
||||
if (usageInfo instanceof FixableUsageInfo) {
|
||||
final String conflictMessage = ((FixableUsageInfo)usageInfo).getConflictMessage();
|
||||
if (conflictMessage != null) {
|
||||
conflicts.putValue(usageInfo.getElement(), conflictMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return showConflicts(conflicts);
|
||||
}
|
||||
|
||||
public void findUsages(@NotNull List<FixableUsageInfo> usages) {
|
||||
if (myUseExistingClass && existingClass != null) {
|
||||
myExistingClassCompatible = existingClassIsCompatible(existingClass, parameters, getterNames);
|
||||
if (!myExistingClassCompatible) return;
|
||||
myExistingClassCompatibleConstructor = existingClassIsCompatible(existingClass, parameters);
|
||||
}
|
||||
findUsagesForMethod(method, usages);
|
||||
|
||||
if (myUseExistingClass && existingClass != null && !(paramsNeedingGetters.isEmpty() && paramsNeedingSetters.isEmpty())) {
|
||||
usages.add(new AppendAccessorsUsageInfo(existingClass, myGenerateAccessors, paramsNeedingGetters, paramsNeedingSetters, parameters));
|
||||
}
|
||||
|
||||
final PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
for (PsiMethod siblingMethod : overridingMethods) {
|
||||
findUsagesForMethod(siblingMethod, usages);
|
||||
@@ -155,7 +166,12 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
|
||||
private void findUsagesForMethod(PsiMethod overridingMethod, List<FixableUsageInfo> usages) {
|
||||
final String fixedParamName = calculateNewParamNameForMethod(overridingMethod);
|
||||
final PsiCodeBlock body = overridingMethod.getBody();
|
||||
final String baseParameterName = StringUtil.decapitalize(className);
|
||||
final String fixedParamName =
|
||||
body != null
|
||||
? JavaCodeStyleManager.getInstance(myProject).suggestUniqueVariableName(baseParameterName, body.getLBrace(), true)
|
||||
: JavaCodeStyleManager.getInstance(myProject).propertyNameToVariableName(baseParameterName, VariableKind.PARAMETER);
|
||||
|
||||
usages.add(new MergeMethodArguments(overridingMethod, className, packageName, fixedParamName, paramsToMerge, typeParams, keepMethodAsDelegate, myCreateInnerClass ? method.getContainingClass() : null));
|
||||
|
||||
@@ -168,27 +184,28 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
final PsiMethod containingMethod = (PsiMethod)parameter.getDeclarationScope();
|
||||
final int index = containingMethod.getParameterList().getParameterIndex(parameter);
|
||||
final PsiParameter replacedParameter = method.getParameterList().getParameters()[index];
|
||||
@NonNls String getter = null;
|
||||
if (getterNames != null) {
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
ParameterTablePanel.VariableData data = parameters.get(i);
|
||||
if (data.variable.equals(parameter)) {
|
||||
getter = getterNames.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final ParameterChunk parameterChunk = ParameterChunk.getChunkByParameter(parameter, parameters);
|
||||
|
||||
@NonNls String getter = parameterChunk != null ? parameterChunk.getter : null;
|
||||
if (getter == null) {
|
||||
getter = PropertyUtil.suggestGetterName(replacedParameter.getName(), replacedParameter.getType());
|
||||
paramsNeedingGetters.add(replacedParameter);
|
||||
}
|
||||
@NonNls String setter = parameterChunk != null ? parameterChunk.setter : null;
|
||||
if (setter == null) {
|
||||
setter = PropertyUtil.suggestSetterName(replacedParameter.getName());
|
||||
}
|
||||
@NonNls final String setter = PropertyUtil.suggestSetterName(replacedParameter.getName());
|
||||
if (RefactoringUtil.isPlusPlusOrMinusMinus(paramUsage.getParent())) {
|
||||
usages.add(new ReplaceParameterIncrementDecrement(paramUsage, fixedParamName, setter, getter));
|
||||
paramsNeedingSetters.add(replacedParameter);
|
||||
if (parameterChunk == null || parameterChunk.setter == null) {
|
||||
paramsNeedingSetters.add(replacedParameter);
|
||||
}
|
||||
}
|
||||
else if (RefactoringUtil.isAssignmentLHS(paramUsage)) {
|
||||
usages.add(new ReplaceParameterAssignmentWithCall(paramUsage, fixedParamName, setter, getter));
|
||||
paramsNeedingSetters.add(replacedParameter);
|
||||
if (parameterChunk == null || parameterChunk.setter == null) {
|
||||
paramsNeedingSetters.add(replacedParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
usages.add(new ReplaceParameterReferenceWithCall(paramUsage, fixedParamName, getter));
|
||||
@@ -196,69 +213,28 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
|
||||
private String calculateNewParamNameForMethod(PsiMethod testMethod) {
|
||||
final Project project = testMethod.getProject();
|
||||
final CodeStyleSettingsManager settingsManager = CodeStyleSettingsManager.getInstance(project);
|
||||
final CodeStyleSettings settings = settingsManager.getCurrentSettings();
|
||||
final String baseParamName = settings.PARAMETER_NAME_PREFIX.length() == 0 ? StringUtil.decapitalize(className) : className;
|
||||
final String newParamName = settings.PARAMETER_NAME_PREFIX + baseParamName + settings.PARAMETER_NAME_SUFFIX;
|
||||
if (!isParamNameUsed(newParamName, testMethod)) {
|
||||
return newParamName;
|
||||
}
|
||||
int count = 1;
|
||||
while (true) {
|
||||
final String testParamName = settings.PARAMETER_NAME_PREFIX + baseParamName + count + settings.PARAMETER_NAME_SUFFIX;
|
||||
if (!isParamNameUsed(testParamName, testMethod)) {
|
||||
return testParamName;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isParamNameUsed(String paramName, PsiMethod testMethod) {
|
||||
final PsiParameterList testParamList = testMethod.getParameterList();
|
||||
final PsiParameter[] testParameters = testParamList.getParameters();
|
||||
for (int i = 0; i < testParameters.length; i++) {
|
||||
if (!isParamToMerge(i)) {
|
||||
if (testParameters[i].getName().equals(paramName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiCodeBlock body = testMethod.getBody();
|
||||
if (body == null) {
|
||||
return false;
|
||||
}
|
||||
final NameUsageVisitor visitor = new NameUsageVisitor(paramName);
|
||||
body.accept(visitor);
|
||||
return visitor.isNameUsed();
|
||||
}
|
||||
|
||||
private boolean isParamToMerge(int i) {
|
||||
for (int j : paramsToMerge) {
|
||||
if (i == j) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void performRefactoring(UsageInfo[] usageInfos) {
|
||||
if (buildClass()) {
|
||||
final PsiClass psiClass = buildClass();
|
||||
if (psiClass != null) {
|
||||
super.performRefactoring(usageInfos);
|
||||
VisibilityUtil.fixVisibility(usageInfos, psiClass, myNewVisibility);
|
||||
if (myExistingClassCompatibleConstructor != null) {
|
||||
VisibilityUtil.fixVisibility(usageInfos, myExistingClassCompatibleConstructor, myNewVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean buildClass() {
|
||||
private PsiClass buildClass() {
|
||||
if (existingClass != null) {
|
||||
return true;
|
||||
return existingClass;
|
||||
}
|
||||
final ParameterObjectBuilder beanClassBuilder = new ParameterObjectBuilder();
|
||||
beanClassBuilder.setProject(myProject);
|
||||
beanClassBuilder.setTypeArguments(typeParams);
|
||||
beanClassBuilder.setClassName(className);
|
||||
beanClassBuilder.setPackageName(packageName);
|
||||
for (ParameterTablePanel.VariableData parameter : parameters) {
|
||||
for (ParameterChunk parameterChunk : parameters) {
|
||||
final ParameterTablePanel.VariableData parameter = parameterChunk.parameter;
|
||||
final boolean setterRequired = paramsNeedingSetters.contains(parameter.variable);
|
||||
beanClassBuilder.addField((PsiParameter)parameter.variable, parameter.name, parameter.type, setterRequired);
|
||||
}
|
||||
@@ -272,7 +248,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
assert classes.length > 0 : classString;
|
||||
final PsiClass innerClass = (PsiClass)containingClass.add(classes[0]);
|
||||
PsiUtil.setModifierProperty(innerClass, PsiModifier.STATIC, true);
|
||||
JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(innerClass);
|
||||
return (PsiClass)JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(innerClass);
|
||||
} else {
|
||||
final PsiFile containingFile = method.getContainingFile();
|
||||
final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
|
||||
@@ -284,17 +260,14 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
final CodeStyleManager codeStyleManager = method.getManager().getCodeStyleManager();
|
||||
final PsiElement shortenedFile = JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(newFile);
|
||||
final PsiElement reformattedFile = codeStyleManager.reformat(shortenedFile);
|
||||
directory.add(reformattedFile);
|
||||
} else {
|
||||
return false;
|
||||
return ((PsiJavaFile)directory.add(reformattedFile)).getClasses()[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
logger.info(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getCommandName() {
|
||||
@@ -303,7 +276,7 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
|
||||
|
||||
private static class ParamUsageVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
private static class ParamUsageVisitor extends JavaRecursiveElementVisitor {
|
||||
private final Set<PsiParameter> paramsToMerge = new HashSet<PsiParameter>();
|
||||
private final Set<PsiReferenceExpression> parameterUsages = new HashSet<PsiReferenceExpression>(4);
|
||||
|
||||
@@ -333,52 +306,17 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
|
||||
private static class NameUsageVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
private boolean nameUsed = false;
|
||||
private final String paramName;
|
||||
|
||||
NameUsageVisitor(String paramName) {
|
||||
super();
|
||||
this.paramName = paramName;
|
||||
}
|
||||
|
||||
public void visitElement(PsiElement element) {
|
||||
if (nameUsed) {
|
||||
return;
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
super.visitVariable(variable);
|
||||
final String variableName = variable.getName();
|
||||
if (paramName.equals(variableName)) {
|
||||
nameUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (expression.getQualifier() == null) {
|
||||
return;
|
||||
}
|
||||
final String referenceName = expression.getReferenceName();
|
||||
if (paramName.equals(referenceName)) {
|
||||
nameUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNameUsed() {
|
||||
return nameUsed;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean existingClassIsCompatible(PsiClass aClass, List<ParameterTablePanel.VariableData> params, @NonNls List<String> getterNames) {
|
||||
@Nullable
|
||||
private static PsiMethod existingClassIsCompatible(PsiClass aClass, List<ParameterChunk> params) {
|
||||
if (params.size() == 1) {
|
||||
final PsiType paramType = params.get(0).type;
|
||||
final ParameterChunk parameterChunk = params.get(0);
|
||||
final PsiType paramType = parameterChunk.parameter.type;
|
||||
if (TypeConversionUtil.isPrimitiveWrapper(aClass.getQualifiedName())) {
|
||||
getterNames.add(paramType.getCanonicalText() + "Value");
|
||||
return true;
|
||||
parameterChunk.setField(aClass.findFieldByName("value", false));
|
||||
parameterChunk.setGetter(paramType.getCanonicalText() + "Value");
|
||||
for (PsiMethod constructor : aClass.getConstructors()) {
|
||||
if (constructorIsCompatible(constructor, params)) return constructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiMethod[] constructors = aClass.getConstructors();
|
||||
@@ -390,42 +328,85 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP
|
||||
}
|
||||
}
|
||||
if (compatibleConstructor == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
final PsiParameterList parameterList = compatibleConstructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
for (PsiParameter param : constructorParams) {
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
final PsiParameter param = constructorParams[i];
|
||||
final ParameterChunk parameterChunk = params.get(i);
|
||||
|
||||
final PsiField field = findFieldAssigned(param, compatibleConstructor);
|
||||
if (field == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
final PsiMethod getter = PropertyUtils.findGetterForField(field);
|
||||
if (getter == null) {
|
||||
return false;
|
||||
|
||||
parameterChunk.setField(field);
|
||||
|
||||
final PsiMethod getterForField = PropertyUtils.findGetterForField(field);
|
||||
if (getterForField != null) {
|
||||
parameterChunk.setGetter(getterForField.getName());
|
||||
}
|
||||
|
||||
final PsiMethod setterForField = PropertyUtils.findSetterForField(field);
|
||||
if (setterForField != null) {
|
||||
parameterChunk.setSetter(setterForField.getName());
|
||||
}
|
||||
getterNames.add(getter.getName());
|
||||
}
|
||||
//TODO: this fails if there are any setters required
|
||||
return true;
|
||||
return compatibleConstructor;
|
||||
}
|
||||
|
||||
private static boolean constructorIsCompatible(PsiMethod constructor, List<ParameterTablePanel.VariableData> params) {
|
||||
if (!constructor.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return false;
|
||||
}
|
||||
private static boolean constructorIsCompatible(PsiMethod constructor, List<ParameterChunk> params) {
|
||||
final PsiParameterList parameterList = constructor.getParameterList();
|
||||
final PsiParameter[] constructorParams = parameterList.getParameters();
|
||||
if (constructorParams.length != params.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < constructorParams.length; i++) {
|
||||
if (!TypeConversionUtil.isAssignable(constructorParams[i].getType(), params.get(i).type)) {
|
||||
if (!TypeConversionUtil.isAssignable(constructorParams[i].getType(), params.get(i).parameter.type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class ParameterChunk {
|
||||
private ParameterTablePanel.VariableData parameter;
|
||||
private PsiField field;
|
||||
private String getter;
|
||||
private String setter;
|
||||
|
||||
public ParameterChunk(ParameterTablePanel.VariableData parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public void setField(PsiField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public void setGetter(String getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public void setSetter(String setter) {
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public PsiField getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ParameterChunk getChunkByParameter(PsiParameter param, List<ParameterChunk> params) {
|
||||
for (ParameterChunk chunk : params) {
|
||||
if (chunk.parameter.variable.equals(param)) {
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiField findFieldAssigned(PsiParameter param, PsiMethod constructor) {
|
||||
final ParamAssignmentFinder visitor = new ParamAssignmentFinder(param);
|
||||
constructor.accept(visitor);
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* User: anna
|
||||
* Date: 02-Nov-2009
|
||||
*/
|
||||
package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.refactoring.RefactorJBundle;
|
||||
import com.intellij.refactoring.introduceparameterobject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AppendAccessorsUsageInfo extends FixableUsageInfo{
|
||||
private final boolean myGenerateAccessors;
|
||||
private final Set<PsiParameter> paramsNeedingSetters;
|
||||
private final Set<PsiParameter> paramsNeedingGetters;
|
||||
private final List<IntroduceParameterObjectProcessor.ParameterChunk> parameters;
|
||||
private static final Logger LOGGER = Logger.getInstance("#" + AppendAccessorsUsageInfo.class.getName());
|
||||
|
||||
|
||||
public AppendAccessorsUsageInfo(PsiElement psiClass, boolean generateAccessors, Set<PsiParameter> paramsNeedingGetters,
|
||||
Set<PsiParameter> paramsNeedingSetters, List<IntroduceParameterObjectProcessor.ParameterChunk> parameters) {
|
||||
super(psiClass);
|
||||
myGenerateAccessors = generateAccessors;
|
||||
this.paramsNeedingGetters = paramsNeedingGetters;
|
||||
this.paramsNeedingSetters = paramsNeedingSetters;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
if (myGenerateAccessors) {
|
||||
appendAccessors(paramsNeedingGetters, true);
|
||||
appendAccessors(paramsNeedingSetters, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendAccessors(final Set<PsiParameter> params, boolean isGetter) {
|
||||
final PsiElement element = getElement();
|
||||
if (element != null) {
|
||||
for (PsiParameter parameter : params) {
|
||||
final IntroduceParameterObjectProcessor.ParameterChunk parameterChunk =
|
||||
IntroduceParameterObjectProcessor.ParameterChunk.getChunkByParameter(parameter, parameters);
|
||||
LOGGER.assertTrue(parameterChunk != null);
|
||||
element.add(isGetter
|
||||
? PropertyUtil.generateGetterPrototype(parameterChunk.getField())
|
||||
: PropertyUtil.generateSetterPrototype(parameterChunk.getField()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConflictMessage() {
|
||||
if (!myGenerateAccessors && (!paramsNeedingSetters.isEmpty() || !paramsNeedingGetters.isEmpty())) {
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
appendConflicts(buf, paramsNeedingGetters);
|
||||
appendConflicts(buf, paramsNeedingSetters);
|
||||
return RefactorJBundle.message("cannot.perform.the.refactoring") + buf.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void appendConflicts(StringBuffer buf, final Set<PsiParameter> paramsNeeding) {
|
||||
if (!paramsNeeding.isEmpty()) {
|
||||
buf.append(paramsNeeding == paramsNeedingGetters ? "Getters" : "Setters");
|
||||
buf.append(" for the following fields are required:\n");
|
||||
buf.append(StringUtil.join(paramsNeeding, new Function<PsiParameter, String>() {
|
||||
public String fun(PsiParameter psiParameter) {
|
||||
final IntroduceParameterObjectProcessor.ParameterChunk chunk =
|
||||
IntroduceParameterObjectProcessor.ParameterChunk.getChunkByParameter(psiParameter, parameters);
|
||||
if (chunk != null) {
|
||||
final PsiField field = chunk.getField();
|
||||
if (field != null) {
|
||||
return field.getName();
|
||||
}
|
||||
}
|
||||
return psiParameter.getName();
|
||||
}
|
||||
}, ", "));
|
||||
buf.append(".\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -18,6 +18,7 @@ package com.intellij.refactoring.introduceparameterobject.usageInfo;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
@@ -93,7 +94,7 @@ public class MergeMethodArguments extends FixableUsageInfo {
|
||||
parametersInfo.add(new ParameterInfoImpl(-1, parameterName, new PsiImmediateClassType(psiClass, subst), null) {
|
||||
@Override
|
||||
public PsiExpression getValue(final PsiCallExpression expr) throws IncorrectOperationException {
|
||||
return psiFacade.getElementFactory().createExpressionFromText(getMergedParam(expr), expr);
|
||||
return (PsiExpression)JavaCodeStyleManager.getInstance(getProject()).shortenClassReferences(psiFacade.getElementFactory().createExpressionFromText(getMergedParam(expr), expr));
|
||||
}
|
||||
});
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
+1
-2
@@ -22,7 +22,6 @@ import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.refactoring.util.EnumConstantsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringConflictsUtil;
|
||||
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -125,7 +124,7 @@ public class MoveJavaMemberHandler implements MoveMemberHandler {
|
||||
assert list != null;
|
||||
list.setModifierProperty(PsiModifier.STATIC, member.hasModifierProperty(PsiModifier.STATIC));
|
||||
list.setModifierProperty(PsiModifier.FINAL, member.hasModifierProperty(PsiModifier.FINAL));
|
||||
RefactoringConflictsUtil.setVisibility(list, VisibilityUtil.getVisibilityModifier(member.getModifierList()));
|
||||
VisibilityUtil.setVisibility(list, VisibilityUtil.getVisibilityModifier(member.getModifierList()));
|
||||
}
|
||||
}
|
||||
member.delete();
|
||||
|
||||
+2
-13
@@ -225,18 +225,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor {
|
||||
|
||||
if(myNewVisibility == null) return;
|
||||
|
||||
if (VisibilityUtil.ESCALATE_VISIBILITY.equals(myNewVisibility)) {
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof MoveMembersUsageInfo) {
|
||||
final PsiElement place = usage.getElement();
|
||||
if (place != null) {
|
||||
VisibilityUtil.escalateVisibility(newMember, place);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RefactoringConflictsUtil.setVisibility(modifierList, myNewVisibility);
|
||||
}
|
||||
VisibilityUtil.fixVisibility(usages, newMember, myNewVisibility);
|
||||
}
|
||||
|
||||
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
|
||||
@@ -264,7 +253,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor {
|
||||
PsiModifierList copy = member.getModifierList();
|
||||
if (copy!=null) copy= (PsiModifierList)copy.copy();
|
||||
if (newVisibility != null) {
|
||||
if (copy!=null) RefactoringConflictsUtil.setVisibility(copy, newVisibility);
|
||||
if (copy!=null) VisibilityUtil.setVisibility(copy, newVisibility);
|
||||
}
|
||||
modifierListCopies.put(member, copy);
|
||||
}
|
||||
|
||||
+7
-5
@@ -42,11 +42,13 @@ public abstract class FixableUsagesRefactoringProcessor extends BaseRefactoringP
|
||||
protected void performRefactoring(UsageInfo[] usageInfos) {
|
||||
RefactoringUtil.sortDepthFirstRightLeftOrder(usageInfos);
|
||||
for (UsageInfo usageInfo : usageInfos) {
|
||||
try {
|
||||
((FixableUsageInfo)usageInfo).fixUsage();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.info(e);
|
||||
if (usageInfo instanceof FixableUsageInfo) {
|
||||
try {
|
||||
((FixableUsageInfo)usageInfo).fixUsage();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,12 +46,6 @@ import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class RefactoringConflictsUtil {
|
||||
public static void setVisibility(PsiModifierList modifierList, @Modifier String newVisibility) throws IncorrectOperationException {
|
||||
modifierList.setModifierProperty(PsiModifier.PRIVATE, false);
|
||||
modifierList.setModifierProperty(PsiModifier.PUBLIC, false);
|
||||
modifierList.setModifierProperty(PsiModifier.PROTECTED, false);
|
||||
modifierList.setModifierProperty(newVisibility, true);
|
||||
}
|
||||
|
||||
public static void analyzeAccessibilityConflicts(@NotNull Set<PsiMember> membersToMove,
|
||||
@NotNull final PsiClass targetClass,
|
||||
@@ -75,7 +69,7 @@ public class RefactoringConflictsUtil {
|
||||
|
||||
if (newVisibility != null) {
|
||||
try {
|
||||
if (modifierList!=null) setVisibility(modifierList, newVisibility);
|
||||
if (modifierList!=null) VisibilityUtil.setVisibility(modifierList, newVisibility);
|
||||
}
|
||||
catch (IncorrectOperationException ex) {
|
||||
/* do nothing and hope for the best */
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Param {
|
||||
private final int[] i;
|
||||
|
||||
public Param(int... i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int[] getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Test {
|
||||
void foo(Param param) {
|
||||
if (param.getI().lenght == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(new Param(1, 2));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Param {
|
||||
private final int i;
|
||||
|
||||
public Param(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(int i) {
|
||||
if (i == 0) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(1, 2);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package p;
|
||||
public class Param {
|
||||
private final int[] i;
|
||||
|
||||
public Param(int... i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int[] getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package p2;
|
||||
|
||||
import p.Param;
|
||||
|
||||
class Test {
|
||||
void foo(Param param) {
|
||||
if (param.getI().lenght == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(new Param(1, 2));
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package p;
|
||||
class Param {
|
||||
private final int[] i;
|
||||
|
||||
Param(int... i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int[] getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package p2;
|
||||
class Test {
|
||||
void foo(int... i) {
|
||||
if (i.lenght == 0) {
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(1, 2);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
public class Param {
|
||||
private final int i;
|
||||
|
||||
public Param(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int getI() {
|
||||
return i;
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(Param param) {
|
||||
if (param.getI() == 0) {
|
||||
param.setI(param.getI() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(new Param(1));
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class Param {
|
||||
private final int i;
|
||||
|
||||
public Param(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(int i) {
|
||||
if (i == 0) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(1);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Param {
|
||||
private final int[] i;
|
||||
|
||||
public Param(int... i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int[] getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(Param param1) {
|
||||
if (param1.getI().lenght == 0) {
|
||||
}
|
||||
Param param = null;
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(new Param(1, 2));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Param {
|
||||
private final int[] i;
|
||||
|
||||
public Param(int... i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int[] getI() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(int... i) {
|
||||
if (i.lenght == 0) {
|
||||
}
|
||||
Param param = null;
|
||||
}
|
||||
|
||||
void bar(){
|
||||
foo(1, 2);
|
||||
}
|
||||
}
|
||||
+36
-14
@@ -14,8 +14,7 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.introduceparameterobject.IntroduceParameterObjectProcessor;
|
||||
import com.intellij.refactoring.util.ParameterTablePanel;
|
||||
import com.intellij.JavaTestUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
|
||||
public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
protected String getTestRoot() {
|
||||
@@ -39,9 +38,8 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
|
||||
final PsiMethod method = aClass.findMethodsByName("foo", false)[0];
|
||||
final ParameterTablePanel.VariableData[] datas = generateParams(method);
|
||||
IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor("Param", "", method, datas,
|
||||
null, delegate, false,
|
||||
createInner);
|
||||
IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor("Param", "", method, datas, delegate, false,
|
||||
createInner, null, false);
|
||||
processor.run();
|
||||
LocalFileSystem.getInstance().refresh(false);
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
@@ -106,17 +104,24 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
doTest(true, false);
|
||||
}
|
||||
|
||||
private void doTestExistingClass(final String existingClassName, final String existingClassPackage) throws Exception {
|
||||
private void doTestExistingClass(final String existingClassName, final String existingClassPackage, final boolean generateAccessors) throws Exception {
|
||||
doTestExistingClass(existingClassName, existingClassPackage, generateAccessors, null);
|
||||
}
|
||||
|
||||
private void doTestExistingClass(final String existingClassName, final String existingClassPackage, final boolean generateAccessors,
|
||||
final String newVisibility) throws Exception {
|
||||
doTest(new PerformAction() {
|
||||
public void performAction(final VirtualFile rootDir, final VirtualFile rootAfter) throws Exception {
|
||||
PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(getProject()));
|
||||
if (aClass == null) {
|
||||
aClass = myJavaFacade.findClass("p2.Test", GlobalSearchScope.projectScope(getProject()));
|
||||
}
|
||||
assertNotNull("Class Test not found", aClass);
|
||||
|
||||
final PsiMethod method = aClass.findMethodsByName("foo", false)[0];
|
||||
IntroduceParameterObjectProcessor processor = new IntroduceParameterObjectProcessor(existingClassName, existingClassPackage, method,
|
||||
generateParams(method),
|
||||
new ArrayList<String>(), false, true,
|
||||
false);
|
||||
generateParams(method), false, true,
|
||||
false, newVisibility, generateAccessors);
|
||||
processor.run();
|
||||
LocalFileSystem.getInstance().refresh(false);
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
@@ -125,17 +130,18 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
}
|
||||
|
||||
public void testIntegerWrapper() throws Exception {
|
||||
doTestExistingClass("Integer", "java.lang");
|
||||
doTestExistingClass("Integer", "java.lang", false);
|
||||
}
|
||||
|
||||
public void testIntegerIncremental() throws Exception {
|
||||
checkExceptionThrown("Integer", "java.lang", "Cannot perform the refactoring.\n" +
|
||||
"Selected class is not compatible with chosen parameters");
|
||||
"Setters for the following fields are required:\n" +
|
||||
"value.\n");
|
||||
}
|
||||
|
||||
private void checkExceptionThrown(String existingClassName, String existingClassPackage, String exceptionMessage) throws Exception {
|
||||
try {
|
||||
doTestExistingClass(existingClassName, existingClassPackage);
|
||||
doTestExistingClass(existingClassName, existingClassPackage, false);
|
||||
}
|
||||
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
|
||||
assertEquals(exceptionMessage, e.getMessage());
|
||||
@@ -144,12 +150,28 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{
|
||||
fail("Conflict was not found");
|
||||
}
|
||||
|
||||
public void testGenerateGetterSetterForExistingBean() throws Exception {
|
||||
doTestExistingClass("Param", "", true);
|
||||
}
|
||||
|
||||
public void testExistingBeanVisibility() throws Exception {
|
||||
doTestExistingClass("Param", "p", false, VisibilityUtil.ESCALATE_VISIBILITY);
|
||||
}
|
||||
|
||||
public void testExistingBeanIfNoGeneration() throws Exception {
|
||||
checkExceptionThrown("Param", "", "Cannot perform the refactoring.\n" + "Setters for the following fields are required:\n" + "i.\n");
|
||||
}
|
||||
|
||||
public void testParamNameConflict() throws Exception {
|
||||
doTestExistingClass("Param", "", true);
|
||||
}
|
||||
|
||||
|
||||
public void testExistentBean() throws Exception {
|
||||
doTestExistingClass("Param", "");
|
||||
doTestExistingClass("Param", "", false);
|
||||
}
|
||||
|
||||
public void testWrongBean() throws Exception {
|
||||
checkExceptionThrown("Param", "", "Cannot perform the refactoring.\n" + "Selected class is not compatible with chosen parameters");
|
||||
checkExceptionThrown("Param", "", "Cannot perform the refactoring.\n" + "Getters for the following fields are required:\n" + "i.\n");
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
@@ -121,4 +122,25 @@ public class VisibilityUtil {
|
||||
public static String toPresentableText(@Modifier String modifier) {
|
||||
return PsiBundle.visibilityPresentation(modifier);
|
||||
}
|
||||
|
||||
public static void fixVisibility(UsageInfo[] usageInfos, PsiMember member, final String newVisibility) {
|
||||
if (newVisibility == null) return;
|
||||
if (ESCALATE_VISIBILITY.equals(newVisibility)) {
|
||||
for (UsageInfo info : usageInfos) {
|
||||
final PsiElement element = info.getElement();
|
||||
if (element != null) {
|
||||
escalateVisibility(member, element);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setVisibility(member.getModifierList(), newVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVisibility(PsiModifierList modifierList, @Modifier String newVisibility) throws IncorrectOperationException {
|
||||
modifierList.setModifierProperty(PsiModifier.PRIVATE, false);
|
||||
modifierList.setModifierProperty(PsiModifier.PUBLIC, false);
|
||||
modifierList.setModifierProperty(PsiModifier.PROTECTED, false);
|
||||
modifierList.setModifierProperty(newVisibility, true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user