introduce parameter object: add setters/getters, fix visibility for existing class

This commit is contained in:
anna
2009-11-03 19:31:40 +03:00
parent 6b9a260f4f
commit 1347a2332e
34 changed files with 584 additions and 248 deletions
@@ -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();
@@ -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) {
@@ -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);
}
}
@@ -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();
@@ -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);
@@ -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);
}
}
@@ -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 &amp;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 &amp;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="&amp;Generate accessors"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -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);
@@ -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");
}
}
}
@@ -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();
@@ -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();
@@ -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);
}
@@ -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 */
@@ -0,0 +1,11 @@
public class Param {
private final int[] i;
public Param(int... i) {
this.i = i;
}
public int[] getI() {
return i;
}
}
@@ -0,0 +1,10 @@
class Test {
void foo(Param param) {
if (param.getI().lenght == 0) {
}
}
void bar(){
foo(new Param(1, 2));
}
}
@@ -0,0 +1,11 @@
public class Param {
private final int i;
public Param(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
@@ -0,0 +1,11 @@
class Test {
void foo(int i) {
if (i == 0) {
i++;
}
}
void bar(){
foo(1, 2);
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -0,0 +1,12 @@
package p;
class Param {
private final int[] i;
Param(int... i) {
this.i = i;
}
public int[] getI() {
return i;
}
}
@@ -0,0 +1,11 @@
package p2;
class Test {
void foo(int... i) {
if (i.lenght == 0) {
}
}
void bar(){
foo(1, 2);
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -0,0 +1,7 @@
public class Param {
private final int i;
public Param(int i) {
this.i = i;
}
}
@@ -0,0 +1,11 @@
class Test {
void foo(int i) {
if (i == 0) {
i++;
}
}
void bar(){
foo(1);
}
}
@@ -0,0 +1,11 @@
public class Param {
private final int[] i;
public Param(int... i) {
this.i = i;
}
public int[] getI() {
return i;
}
}
@@ -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));
}
}
@@ -0,0 +1,11 @@
public class Param {
private final int[] i;
public Param(int... i) {
this.i = i;
}
public int[] getI() {
return i;
}
}
@@ -0,0 +1,11 @@
class Test {
void foo(int... i) {
if (i.lenght == 0) {
}
Param param = null;
}
void bar(){
foo(1, 2);
}
}
@@ -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);
}
}