extract enum ( IDEA-11228 )

This commit is contained in:
anna
2010-06-03 12:38:51 +04:00
parent c3410784a4
commit 863fbfddb8
28 changed files with 565 additions and 166 deletions

View File

@@ -34,14 +34,16 @@ import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.ReferenceEditorComboWithBrowseButton;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.util.ArrayList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
import java.util.Map;
@SuppressWarnings({"OverridableMethodCallInConstructor"})
class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeListener<PsiMember, MemberInfo> {
@@ -53,6 +55,8 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
private final JTextField sourceClassTextField;
private JCheckBox myGenerateAccessorsCb;
private final VisibilityPanel myVisibilityPanel;
private JCheckBox extractAsEnum;
private List<MemberInfo> enumConstants = new ArrayList<MemberInfo>();
ExtractClassDialog(PsiClass sourceClass, PsiMember selectedMember) {
super(sourceClass.getProject(), true);
@@ -93,10 +97,19 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
}
};
memberInfo = MemberInfo.extractClassMembers(this.sourceClass, filter, false);
extractAsEnum = new JCheckBox("Extract as enum");
boolean hasConstants = false;
for (MemberInfo info : memberInfo) {
if (info.getMember().equals(selectedMember)) {
final PsiMember member = info.getMember();
if (member.equals(selectedMember)) {
info.setChecked(true);
}
if (!hasConstants && member instanceof PsiField && member.hasModifierProperty(PsiModifier.FINAL) && member.hasModifierProperty(PsiModifier.STATIC)) {
hasConstants = true;
}
}
if (!hasConstants) {
extractAsEnum.setVisible(false);
}
super.init();
sourceClassTextField.setText(sourceClass.getQualifiedName());
@@ -111,7 +124,13 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
final String newClassName = getClassName();
final String packageName = getPackageName();
final ExtractClassProcessor processor = new ExtractClassProcessor(sourceClass, fields, methods, classes, packageName, newClassName, myVisibilityPanel.getVisibility(), isGenerateAccessors());
Collections.sort(enumConstants, new Comparator<MemberInfo>() {
public int compare(MemberInfo o1, MemberInfo o2) {
return o1.getMember().getTextOffset() - o2.getMember().getTextOffset();
}
});
final ExtractClassProcessor processor = new ExtractClassProcessor(sourceClass, fields, methods, classes, packageName, newClassName, myVisibilityPanel.getVisibility(), isGenerateAccessors(),
isExtractAsEnum() ? enumConstants : Collections.<MemberInfo>emptyList());
invokeRefactoring(processor);
}
@@ -180,6 +199,10 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
return myGenerateAccessorsCb.isSelected();
}
public boolean isExtractAsEnum() {
return extractAsEnum.isVisible() && extractAsEnum.isEnabled() && extractAsEnum.isSelected();
}
protected String getDimensionServiceKey() {
return "RefactorJ.ExtractClass";
}
@@ -200,6 +223,7 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
final JPanel classNamePanel = new JPanel(new BorderLayout());
classNamePanel.add(classNameLabel, BorderLayout.NORTH);
classNamePanel.add(classNameField, BorderLayout.CENTER);
classNamePanel.add(extractAsEnum, BorderLayout.SOUTH);
box.add(classNamePanel);
box.add(Box.createVerticalStrut(5));
@@ -221,12 +245,40 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel(new BorderLayout());
final MemberSelectionPanel memberSelectionPanel =
new MemberSelectionPanel(RefactorJBundle.message("members.to.extract.label"), memberInfo, null);
new MemberSelectionPanel(RefactorJBundle.message("members.to.extract.label"), memberInfo, "as enum"){
@Override
protected MemberSelectionTable createMemberSelectionTable(final List<MemberInfo> memberInfo, String abstractColumnHeader) {
return new MemberSelectionTable(memberInfo, abstractColumnHeader) {
@Nullable
@Override
protected Object getAbstractColumnValue(MemberInfo memberInfo) {
if (isExtractAsEnum()) {
final PsiMember member = memberInfo.getMember();
if (isConstantField(member)) {
return Boolean.valueOf(enumConstants.contains(memberInfo));
}
}
return null;
}
@Override
protected boolean isAbstractColumnEditable(int rowIndex) {
final MemberInfo info = memberInfo.get(rowIndex);
if (info.isChecked()) {
final PsiMember member = info.getMember();
if (isConstantField(member)) {
if (enumConstants.isEmpty()) return true;
final MemberInfo currentEnumConstant = enumConstants.get(0);
if (((PsiField)currentEnumConstant.getMember()).getType().equals(((PsiField)member).getType())) return true;
}
}
return false;
}
};
}
};
final MemberSelectionTable table = memberSelectionPanel.getTable();
table.setMemberInfoModel(new DelegatingMemberInfoModel<PsiMember, MemberInfo>(table.getMemberInfoModel()) {
public Boolean isFixedAbstract(MemberInfo member) {
return Boolean.TRUE;
}
@Override
public int checkForProblems(@NotNull final MemberInfo member) {
@@ -274,7 +326,11 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
});
panel.add(memberSelectionPanel, BorderLayout.CENTER);
table.addMemberInfoChangeListener(this);
extractAsEnum.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
table.repaint();
}
});
myGenerateAccessorsCb = new JCheckBox("Generate accessors");
myGenerateAccessorsCb.setMnemonic('G');
panel.add(myGenerateAccessorsCb, BorderLayout.SOUTH);
@@ -283,6 +339,13 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
return panel;
}
private static boolean isConstantField(PsiMember member) {
return member instanceof PsiField &&
member.hasModifierProperty(PsiModifier.STATIC) &&
member.hasModifierProperty(PsiModifier.FINAL) &&
((PsiField)member).hasInitializer();
}
public JComponent getPreferredFocusedComponent() {
return classNameField;
}
@@ -295,5 +358,34 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
public void memberInfoChanged(MemberInfoChange memberInfoChange) {
validateButtons();
myMember2CauseMap.clear();
if (extractAsEnum.isVisible()) {
for (Object info : memberInfoChange.getChangedMembers()) {
if (((MemberInfo)info).isToAbstract()) {
enumConstants.add((MemberInfo)info);
} else {
enumConstants.remove((MemberInfo)info);
}
}
extractAsEnum.setEnabled(canExtractEnum());
}
}
private boolean canExtractEnum() {
final List<PsiField> fields = new ArrayList<PsiField>();
final List<PsiClass> innerClasses = new ArrayList<PsiClass>();
final List<PsiMethod> methods = new ArrayList<PsiMethod>();
for (MemberInfo info : memberInfo) {
if (info.isChecked()) {
final PsiMember member = info.getMember();
if (member instanceof PsiField) {
fields.add((PsiField)member);
} else if (member instanceof PsiMethod) {
methods.add((PsiMethod)member);
} else if (member instanceof PsiClass) {
innerClasses.add((PsiClass)member);
}
}
}
return !new BackpointerUsageVisitor(fields, innerClasses, methods, sourceClass).backpointerRequired();
}
}

View File

@@ -43,7 +43,9 @@ 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.RefactoringUIUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.util.IncorrectOperationException;
@@ -66,6 +68,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
private final String newPackageName;
private final String myNewVisibility;
private final boolean myGenerateAccessors;
private final List<PsiField> enumConstants;
private final String newClassName;
private final String delegateFieldName;
private final boolean requiresBackpointer;
@@ -77,7 +80,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
List<PsiClass> innerClasses,
String newPackageName,
String newClassName) {
this(sourceClass, fields, methods, innerClasses, newPackageName, newClassName, null, false);
this(sourceClass, fields, methods, innerClasses, newPackageName, newClassName, null, false, Collections.<MemberInfo>emptyList());
}
public ExtractClassProcessor(PsiClass sourceClass,
@@ -87,12 +90,16 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
String packageName,
String newClassName,
String newVisibility,
boolean generateAccessors) {
boolean generateAccessors, List<MemberInfo> enumConstants) {
super(sourceClass.getProject());
this.sourceClass = sourceClass;
this.newPackageName = packageName;
myNewVisibility = newVisibility;
myGenerateAccessors = generateAccessors;
this.enumConstants = new ArrayList<PsiField>();
for (MemberInfo constant : enumConstants) {
this.enumConstants.add((PsiField)constant.getMember());
}
this.fields = new ArrayList<PsiField>(fields);
this.methods = new ArrayList<PsiMethod>(methods);
this.innerClasses = new ArrayList<PsiClass>(classes);
@@ -146,6 +153,21 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
conflicts.putValue(field, "Field \'" + field.getName() + "\' needs setter");
}
}
for (final PsiField enumConstant : enumConstants) {
final PsiExpression initializer = enumConstant.getInitializer();
assert initializer != null;
initializer.accept(new JavaRecursiveElementWalkingVisitor(){
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement resolved = expression.resolve();
if (!enumConstants.contains(resolved) && fields.contains(resolved)) {
conflicts.putValue(initializer, "Enum constant " + RefactoringUIUtil.getDescription(enumConstant, false) +
" would forward reference on field " + RefactoringUIUtil.getDescription(resolved, false));
}
}
});
}
return showConflicts(conflicts, refUsages.get());
}
@@ -250,16 +272,14 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
if (moveInitializerToConstructor[0]) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
PsiMethod constructor;
final PsiMethod[] constructors = psiClass.getConstructors();
PsiMethod[] constructors = psiClass.getConstructors();
if (constructors.length == 0) {
constructor = elementFactory.createConstructor();
constructor.setName(psiClass.getName());
constructor = (PsiMethod)psiClass.add(constructor);
} else {
constructor = constructors[0];
final PsiMethod constructor = (PsiMethod)elementFactory.createConstructor().setName(psiClass.getName());
constructors = new PsiMethod[] {(PsiMethod)psiClass.add(constructor)};
}
for (PsiMethod constructor : constructors) {
MoveInstanceMembersUtil.moveInitializerToConstructor(elementFactory, constructor, member);
}
MoveInstanceMembersUtil.moveInitializerToConstructor(elementFactory, constructor, member);
}
}
}
@@ -607,7 +627,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
}
else {
usages.add(isStatic
? new ReplaceStaticVariableAccess(exp, qualifiedName)
? new ReplaceStaticVariableAccess(exp, qualifiedName, enumConstants.contains(field))
: new ReplaceInstanceVariableAccess(exp, delegateFieldName, getter, field.getName()));
}
@@ -630,6 +650,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
extractedClassBuilder.setPackageName(newPackageName);
extractedClassBuilder.setOriginalClassName(sourceClass.getQualifiedName());
extractedClassBuilder.setRequiresBackPointer(requiresBackpointer);
extractedClassBuilder.setExtractAsEnum(enumConstants);
for (PsiField field : fields) {
extractedClassBuilder.addField(field);
}

View File

@@ -26,6 +26,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.psi.MethodInheritanceUtils;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
@@ -54,6 +55,8 @@ class ExtractedClassBuilder {
private JavaCodeStyleManager myJavaCodeStyleManager;
private Set<PsiField> myFieldsNeedingSetters;
private Set<PsiField> myFieldsNeedingGetter;
private List<PsiField> enumConstantFields;
private PsiType myEnumParameterType;
public void setClassName(String className) {
this.className = className;
@@ -105,10 +108,8 @@ class ExtractedClassBuilder {
if (packageName.length() > 0) out.append("package " + packageName + ';');
out.append("public ");
if (hasAbstractMethod()) {
out.append("abstract ");
}
out.append("class ");
fields.removeAll(enumConstantFields);
out.append(hasEnumConstants() ? "enum " : "class ");
out.append(className);
if (!typeParams.isEmpty()) {
out.append('<');
@@ -152,7 +153,13 @@ class ExtractedClassBuilder {
out.append(' ' + backPointerName + ";");
}
outputFieldsAndInitializers(out);
if (needConstructor() || requiresBackPointer) {
if (hasEnumConstants()) {
final String fieldName = getValueFieldName();
out.append("\n").append("private ").append(myEnumParameterType.getCanonicalText()).append(" ").append(fieldName).append(";\n");
out.append("public ").append(myEnumParameterType.getCanonicalText()).append(" ")
.append(getterName()).append("(){\nreturn ").append(fieldName).append(";\n}\n");
}
if (hasEnumConstants() || needConstructor() || requiresBackPointer) {
outputConstructor(out);
}
outputMethods(out);
@@ -161,13 +168,17 @@ class ExtractedClassBuilder {
return out.toString();
}
private boolean hasAbstractMethod() {
for (PsiMethod method : methods) {
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
return true;
}
}
return false;
private String getterName() {//todo unique getterName: see also com.intellij.refactoring.extractclass.usageInfo.ReplaceStaticVariableAccess
return PropertyUtil.suggestGetterName("value", myEnumParameterType);
}
private boolean hasEnumConstants() {
return !enumConstantFields.isEmpty();
}
private String getValueFieldName() {
final String myValue = myJavaCodeStyleManager.variableNameToPropertyName("value", VariableKind.FIELD);
return myJavaCodeStyleManager.suggestUniqueVariableName(myValue, enumConstantFields.get(0), true);
}
private void calculateBackpointerName() {
@@ -221,7 +232,7 @@ class ExtractedClassBuilder {
private void outputMethods(StringBuffer out) {
for (PsiMethod method : methods) {
outputMutatedMethod(out, method);
method.accept(new Mutator(out));
}
}
@@ -231,16 +242,6 @@ class ExtractedClassBuilder {
}
}
private void outputMutatedInitializer(StringBuffer out, PsiClassInitializer initializer) {
final PsiElementVisitor visitor = new Mutator(out);
initializer.accept(visitor);
}
private void outputMutatedMethod(StringBuffer out, PsiMethod method) {
final PsiElementVisitor visitor = new Mutator(out);
method.accept(visitor);
}
private void outputMutatedInnerClass(StringBuffer out, PsiClass innerClass, boolean makePublic) {
if (makePublic) {
try {
@@ -250,12 +251,26 @@ class ExtractedClassBuilder {
LOGGER.error(e);
}
}
final PsiElementVisitor visitor = new Mutator(out);
innerClass.accept(visitor);
innerClass.accept(new Mutator(out));
}
private void outputFieldsAndInitializers(StringBuffer out) {
private void outputFieldsAndInitializers(final StringBuffer out) {
if (hasEnumConstants()) {
out.append(StringUtil.join(enumConstantFields, new Function<PsiField, String>() {
public String fun(PsiField field) {
final StringBuffer fieldStr = new StringBuffer(field.getName().toUpperCase() + "(");
final PsiExpression initializer = field.getInitializer();
if (initializer != null) {
initializer.accept(new Mutator(fieldStr));
}
fieldStr.append(")");
return fieldStr.toString();
}
}, ", "));
out.append(";");
}
final List<PsiClassInitializer> remainingInitializers = new ArrayList<PsiClassInitializer>(initializers);
for (final PsiField field : fields) {
final Iterator<PsiClassInitializer> initializersIterator = remainingInitializers.iterator();
@@ -263,12 +278,12 @@ class ExtractedClassBuilder {
while (initializersIterator.hasNext()) {
final PsiClassInitializer initializer = initializersIterator.next();
if (initializer.getTextRange().getStartOffset() < fieldOffset) {
outputMutatedInitializer(out, initializer);
initializer.accept(new Mutator(out));
initializersIterator.remove();
}
}
outputField(field, out);
field.accept(new Mutator(out));
if (myFieldsNeedingGetter != null && myFieldsNeedingGetter.contains(field)) {
out.append(PropertyUtil.generateGetterPrototype(field).getText());
@@ -281,27 +296,13 @@ class ExtractedClassBuilder {
}
}
for (PsiClassInitializer initializer : remainingInitializers) {
outputMutatedInitializer(out, initializer);
initializer.accept(new Mutator(out));
}
}
private String calculateStrippedName(PsiVariable variable) {
String name = variable.getName();
if (name == null) {
return null;
}
if (variable instanceof PsiField) {
name = myJavaCodeStyleManager.variableNameToPropertyName(name, variable.hasModifierProperty(PsiModifier.STATIC)
? VariableKind.STATIC_FIELD
: VariableKind.FIELD);
}
return name;
}
private void outputConstructor(@NonNls StringBuffer out) {
out.append("\tpublic " + className + '(');
out.append("\t").append(hasEnumConstants() ? "" : "public ").append(className).append('(');
if (requiresBackPointer) {
final String parameterName = myJavaCodeStyleManager.propertyNameToVariableName(backPointerName, VariableKind.PARAMETER);
out.append(originalClassName);
@@ -318,6 +319,8 @@ class ExtractedClassBuilder {
out.append('>');
}
out.append(' ' + parameterName);
} else if (hasEnumConstants()) {
out.append(myEnumParameterType.getCanonicalText()).append(" ").append("value");
}
out.append(")");
@@ -331,14 +334,13 @@ class ExtractedClassBuilder {
out.append("\t\t" + backPointerName + " = " + parameterName + ";");
}
} else if (hasEnumConstants()) {
final String fieldName = getValueFieldName();
out.append(fieldName.equals("value") ? "this." : "").append(fieldName).append(" = value;");
}
out.append("\t}");
}
private void outputField(PsiField field, @NonNls StringBuffer out) {
field.accept(new Mutator(out));
}
public void setRequiresBackPointer(boolean requiresBackPointer) {
this.requiresBackPointer = requiresBackPointer;
}
@@ -358,15 +360,21 @@ class ExtractedClassBuilder {
}
private boolean fieldIsExtracted(PsiField field) {
for (PsiField psiField : fields) {
if (psiField.equals(field)) {
return true;
}
}
final ArrayList<PsiField> extractedFields = new ArrayList<PsiField>(fields);
extractedFields.addAll(enumConstantFields);
if (extractedFields.contains(field)) return true;
final PsiClass containingClass = field.getContainingClass();
return innerClasses.contains(containingClass);
}
public void setExtractAsEnum(List<PsiField> extractAsEnum) {
this.enumConstantFields = extractAsEnum;
if (hasEnumConstants()) {
myEnumParameterType = enumConstantFields.get(0).getType();
}
}
private class Mutator extends JavaElementVisitor {
@NonNls
private final StringBuffer out;
@@ -402,11 +410,14 @@ class ExtractedClassBuilder {
if (fieldIsExtracted(field)) {
final String name = field.getName();
if (qualifier != null && name.equals(expression.getReferenceName())) {
out.append("this.");
if (enumConstantFields.contains(field)) {
out.append(name.toUpperCase()).append(".").append(getterName()).append("()");
} else {
if (qualifier != null && name.equals(expression.getReferenceName())) {
out.append("this.");
}
out.append(name);
}
out.append(name);
}
else {
if (field.hasModifierProperty(PsiModifier.STATIC)) {

View File

@@ -16,6 +16,7 @@
package com.intellij.refactoring.extractclass.usageInfo;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.refactoring.psi.MutationUtils;
import com.intellij.refactoring.util.FixableUsageInfo;
import com.intellij.util.IncorrectOperationException;
@@ -23,14 +24,17 @@ import com.intellij.util.IncorrectOperationException;
public class ReplaceStaticVariableAccess extends FixableUsageInfo {
private final PsiReferenceExpression expression;
private final String delegateClass;
private final boolean myEnumConstant;
public ReplaceStaticVariableAccess(PsiReferenceExpression expression, String delegateClass) {
public ReplaceStaticVariableAccess(PsiReferenceExpression expression, String delegateClass, boolean enumConstant) {
super(expression);
this.expression = expression;
this.delegateClass = delegateClass;
}
myEnumConstant = enumConstant;
}
public void fixUsage() throws IncorrectOperationException {
MutationUtils.replaceExpression(delegateClass + '.' + expression.getReferenceName(), expression);
MutationUtils.replaceExpression(delegateClass + '.' + expression.getReferenceName() + (myEnumConstant ? "." + PropertyUtil.suggestGetterName("value", expression.getType())+
"()" : ""), expression);
}
}

View File

@@ -44,13 +44,17 @@ public class MemberSelectionPanel extends JPanel {
setBorder(border);
setLayout(new BorderLayout());
myTable = new MemberSelectionTable(memberInfo, abstractColumnHeader);
myTable = createMemberSelectionTable(memberInfo, abstractColumnHeader);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable);
add(scrollPane, BorderLayout.CENTER);
}
protected MemberSelectionTable createMemberSelectionTable(List<MemberInfo> memberInfo, String abstractColumnHeader) {
return new MemberSelectionTable(memberInfo, abstractColumnHeader);
}
public MemberSelectionTable getTable() {
return myTable;
}

View File

@@ -33,6 +33,7 @@ import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.ui.RowIcon;
import com.intellij.util.IconUtil;
import com.intellij.util.VisibilityIcons;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
@@ -47,6 +48,7 @@ public class MemberSelectionTable extends AbstractMemberSelectionTable<PsiMember
super(memberInfos, memberInfoModel, abstractColumnHeader);
}
@Nullable
@Override
protected Object getAbstractColumnValue(MemberInfo memberInfo) {
if (!(memberInfo.getMember() instanceof PsiMethod)) return null;

View File

@@ -0,0 +1,12 @@
public enum EEnum {
FOO("foo"), BAR(FOO.getValue());
private String value;
public String getValue() {
return value;
}
EEnum(String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,2 @@
class Test {
}

View File

@@ -0,0 +1,4 @@
class Test {
public static final String FOO = "foo";
public static final String BAR = FOO;
}

View File

@@ -0,0 +1,4 @@
class Test {
public static final String FOO = "foo";
public static final String BAR = FOO;
}

View File

@@ -0,0 +1,4 @@
class Test {
public static final String FOO = "foo";
public static final String BAR = FOO;
}

View File

@@ -0,0 +1,12 @@
public enum EEnum {
FOO("foo");
private String value;
public String getValue() {
return value;
}
EEnum(String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,2 @@
class Test {
}

View File

@@ -0,0 +1,3 @@
class Test {
public static final String FOO = "foo";
}

View File

@@ -0,0 +1,16 @@
public enum EEnum {
FOO("foo");
private String value;
public String getValue() {
return value;
}
EEnum(String value) {
this.value = value;
}
void foo() {
System.out.println(FOO.getValue());
}
}

View File

@@ -0,0 +1,6 @@
class Test {
public static final String FOO = "foo";
void foo() {
System.out.println(FOO);
}
}

View File

@@ -0,0 +1,12 @@
public enum EEnum {
FOO("foo");
private String value;
public String getValue() {
return value;
}
EEnum(String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,5 @@
class Test {
void foo() {
System.out.println(EEnum.FOO.getValue());
}
}

View File

@@ -0,0 +1,6 @@
class Test {
public static final String FOO = "foo";
void foo() {
System.out.println(FOO);
}
}

View File

@@ -0,0 +1,13 @@
public enum EEnum {
FOO("foo");
public int value = 0;
private String value1;
public String getValue() {
return value1;
}
EEnum(String value) {
value1 = value;
}
}

View File

@@ -0,0 +1,2 @@
class Test {
}

View File

@@ -0,0 +1,4 @@
class Test {
public static final String FOO = "foo";
public int value = 0;
}

View File

@@ -14,10 +14,12 @@ import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.extractclass.ExtractClassProcessor;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import junit.framework.Assert;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.TreeSet;
public class ExtractClassTest extends MultiFileTestCase{
@@ -135,7 +137,7 @@ public class ExtractClassTest extends MultiFileTestCase{
private static void doTest(final PsiClass aClass, final ArrayList<PsiMethod> methods, final ArrayList<PsiField> fields, final String conflicts,
boolean generateGettersSetters) {
try {
ExtractClassProcessor processor = new ExtractClassProcessor(aClass, fields, methods, new ArrayList<PsiClass>(), "", "Extracted", null, generateGettersSetters);
ExtractClassProcessor processor = new ExtractClassProcessor(aClass, fields, methods, new ArrayList<PsiClass>(), "", "Extracted", null, generateGettersSetters, Collections.<MemberInfo>emptyList());
processor.run();
LocalFileSystem.getInstance().refresh(false);
FileDocumentManager.getInstance().saveAllDocuments();
@@ -253,7 +255,7 @@ public class ExtractClassTest extends MultiFileTestCase{
fields.add(aClass.findFieldByName("myT", false));
final ExtractClassProcessor processor =
new ExtractClassProcessor(aClass, fields, methods, new ArrayList<PsiClass>(), "", "Extracted", PsiModifier.PUBLIC, false);
new ExtractClassProcessor(aClass, fields, methods, new ArrayList<PsiClass>(), "", "Extracted", PsiModifier.PUBLIC, false, Collections.<MemberInfo>emptyList());
processor.run();
LocalFileSystem.getInstance().refresh(false);
FileDocumentManager.getInstance().saveAllDocuments();

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2000-2010 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-Jun-2010
*/
package com.intellij.refactoring;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.extractclass.ExtractClassProcessor;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import junit.framework.Assert;
import java.util.*;
public class ExtractEnumTest extends MultiFileTestCase {
@Override
protected String getTestRoot() {
return "/refactoring/extractEnum/";
}
public void testOneConstant() throws Exception {
doTest(new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, true));
}
public void testDependantConstants() throws Exception {
doTest(new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, true),
new RefactoringTestUtil.MemberDescriptor("BAR", PsiField.class, true));
}
public void testReferencesOnEnumConstantInEnum() throws Exception {
doTest(new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, true),
new RefactoringTestUtil.MemberDescriptor("foo", PsiMethod.class));
}
public void testReferencesOnEnumConstantInOriginal() throws Exception {
doTest(new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, true));
}
public void testForwardReferenceConflict() throws Exception {
doTest("Enum constant field <b><code>BAR</code></b> would forward reference on field field <b><code>FOO</code></b>", false,
new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, false),
new RefactoringTestUtil.MemberDescriptor("BAR", PsiField.class, true));
}
public void testValueNameConflict() throws Exception {
doTest(new RefactoringTestUtil.MemberDescriptor("FOO", PsiField.class, true),
new RefactoringTestUtil.MemberDescriptor("value", PsiField.class, false));
}
private void doTest(final RefactoringTestUtil.MemberDescriptor... memberDescriptors) throws Exception {
doTest(null, false, memberDescriptors);
}
private void doTest(final String conflicts,
final boolean generateAccessors,
final RefactoringTestUtil.MemberDescriptor... memberDescriptors) throws Exception {
doTest(new PerformAction() {
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
final PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(myProject));
assertNotNull("Class Test not found", aClass);
final ArrayList<PsiField> fields = new ArrayList<PsiField>();
final ArrayList<PsiMethod> methods = new ArrayList<PsiMethod>();
final List<MemberInfo> enumConstants = new ArrayList<MemberInfo>();
for (MemberInfo memberInfo : RefactoringTestUtil.findMembers(aClass, memberDescriptors)) {
final PsiMember member = memberInfo.getMember();
if (member instanceof PsiField) {
fields.add((PsiField)member);
if (member.hasModifierProperty(PsiModifier.STATIC) && member.hasModifierProperty(PsiModifier.FINAL) && ((PsiField)member).hasInitializer()) {
if (memberInfo.isToAbstract()) {
enumConstants.add(memberInfo);
}
}
}
else if (member instanceof PsiMethod) {
methods.add((PsiMethod)member);
}
}
try {
final ExtractClassProcessor processor =
new ExtractClassProcessor(aClass, fields, methods, new ArrayList<PsiClass>(), "", "EEnum",
null, generateAccessors, enumConstants);
processor.run();
LocalFileSystem.getInstance().refresh(false);
FileDocumentManager.getInstance().saveAllDocuments();
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
if (conflicts != null) {
TreeSet expectedConflictsSet = new TreeSet(Arrays.asList(conflicts.split("\n")));
TreeSet actualConflictsSet = new TreeSet(Arrays.asList(e.getMessage().split("\n")));
Assert.assertEquals(expectedConflictsSet, actualConflictsSet);
return;
}
else {
fail(e.getMessage());
}
}
if (conflicts != null) {
fail("Conflicts were not detected: " + conflicts);
}
}
});
}
}

View File

@@ -29,16 +29,16 @@ import java.io.File;
*/
public class ExtractSuperClassTest extends CodeInsightTestCase {
public void testFinalFieldInitialization() throws Exception { // IDEADEV-19704
doTest("Test", "TestSubclass", new PullUpTest.MemberDescriptor("X", PsiClass.class),
new PullUpTest.MemberDescriptor("x", PsiField.class));
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("X", PsiClass.class),
new RefactoringTestUtil.MemberDescriptor("x", PsiField.class));
}
public void testFieldInitializationWithCast() throws Exception {
doTest("Test", "TestSubclass", new PullUpTest.MemberDescriptor("x", PsiField.class));
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("x", PsiField.class));
}
public void testParameterNameEqualsFieldName() throws Exception { // IDEADEV-10629
doTest("Test", "TestSubclass", new PullUpTest.MemberDescriptor("a", PsiField.class));
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("a", PsiField.class));
}
public void testExtendsLibraryClass() throws Exception {
@@ -46,7 +46,7 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
}
public void testRequiredImportRemoved() throws Exception {
doTest("foo.impl.B", "BImpl", new PullUpTest.MemberDescriptor("getInstance", PsiMethod.class));
doTest("foo.impl.B", "BImpl", new RefactoringTestUtil.MemberDescriptor("getInstance", PsiMethod.class));
}
public void testSubstituteGenerics() throws Exception {
@@ -54,11 +54,11 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
}
public void testExtendsList() throws Exception {
doTest("Test", "TestSubclass", new PullUpTest.MemberDescriptor("List", PsiClass.class));
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("List", PsiClass.class));
}
public void testImportsCorruption() throws Exception {
doTest("p1.A", "AA", new PullUpTest.MemberDescriptor("m1", PsiMethod.class));
doTest("p1.A", "AA", new RefactoringTestUtil.MemberDescriptor("m1", PsiMethod.class));
}
@Override
@@ -78,13 +78,13 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
}
private void doTest(@NonNls final String className, @NonNls final String newClassName,
PullUpTest.MemberDescriptor... membersToFind) throws Exception {
RefactoringTestUtil.MemberDescriptor... membersToFind) throws Exception {
String rootBefore = getRoot() + "/before";
PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk("java 1.5"));
final VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete);
PsiClass psiClass = myJavaFacade.findClass(className, ProjectScope.getAllScope(myProject));
assertNotNull(psiClass);
final MemberInfo[] members = PullUpTest.findMembers(psiClass, membersToFind);
final MemberInfo[] members = RefactoringTestUtil.findMembers(psiClass, membersToFind);
ExtractSuperClassProcessor processor = new ExtractSuperClassProcessor(myProject,
psiClass.getContainingFile().getContainingDirectory(),
newClassName,

View File

@@ -23,75 +23,75 @@ public class PullUpTest extends LightCodeInsightTestCase {
public void testQualifiedThis() throws Exception {
doTest(new MemberDescriptor ("Inner", PsiClass.class));
doTest(new RefactoringTestUtil.MemberDescriptor("Inner", PsiClass.class));
}
public void testQualifiedSuper() throws Exception {
doTest(new MemberDescriptor ("Inner", PsiClass.class));
doTest(new RefactoringTestUtil.MemberDescriptor("Inner", PsiClass.class));
}
public void testQualifiedReference() throws Exception { // IDEADEV-25008
doTest(new MemberDescriptor ("x", PsiField.class),
new MemberDescriptor ("getX", PsiMethod.class),
new MemberDescriptor ("setX", PsiMethod.class));
doTest(new RefactoringTestUtil.MemberDescriptor("x", PsiField.class),
new RefactoringTestUtil.MemberDescriptor("getX", PsiMethod.class),
new RefactoringTestUtil.MemberDescriptor("setX", PsiMethod.class));
}
public void testPullUpAndAbstractize() throws Exception {
doTest(new MemberDescriptor("a", PsiMethod.class),
new MemberDescriptor("b", PsiMethod.class, true));
doTest(new RefactoringTestUtil.MemberDescriptor("a", PsiMethod.class),
new RefactoringTestUtil.MemberDescriptor("b", PsiMethod.class, true));
}
public void testTryCatchFieldInitializer() throws Exception {
doTest(new MemberDescriptor("field", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("field", PsiField.class));
}
public void testIfFieldInitializationWithNonMovedField() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testIfFieldMovedInitialization() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testMultipleConstructorsFieldInitialization() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testMultipleConstructorsFieldInitializationNoGood() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testRemoveOverride() throws Exception {
doTest(new MemberDescriptor ("get", PsiMethod.class));
doTest(new RefactoringTestUtil.MemberDescriptor("get", PsiMethod.class));
}
public void testTypeParamErasure() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testTypeParamSubst() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testTypeArgument() throws Exception {
doTest(new MemberDescriptor("f", PsiField.class));
doTest(new RefactoringTestUtil.MemberDescriptor("f", PsiField.class));
}
public void testGenericsInAbstractMethod() throws Exception {
doTest(new MemberDescriptor("method", PsiMethod.class, true));
doTest(new RefactoringTestUtil.MemberDescriptor("method", PsiMethod.class, true));
}
public void testGenericsInImplements() throws Exception {
doTest(false, new MemberDescriptor("I", PsiClass.class));
doTest(false, new RefactoringTestUtil.MemberDescriptor("I", PsiClass.class));
}
private void doTest(MemberDescriptor... membersToFind) throws Exception {
private void doTest(RefactoringTestUtil.MemberDescriptor... membersToFind) throws Exception {
doTest(true, membersToFind);
}
private void doTest(final boolean checkMemebersMovedCount, MemberDescriptor... membersToFind) throws Exception {
private void doTest(final boolean checkMemebersMovedCount, RefactoringTestUtil.MemberDescriptor... membersToFind) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
PsiElement elementAt = getFile().findElementAt(getEditor().getCaretModel().getOffset());
final PsiClass sourceClass = PsiTreeUtil.getParentOfType(elementAt, PsiClass.class);
@@ -104,7 +104,7 @@ public class PullUpTest extends LightCodeInsightTestCase {
assertTrue(interfaces[0].isWritable());
targetClass = interfaces[0];
}
MemberInfo[] infos = findMembers(sourceClass, membersToFind);
MemberInfo[] infos = RefactoringTestUtil.findMembers(sourceClass, membersToFind);
final int[] countMoved = new int[] {0};
final MoveMemberListener listener = new MoveMemberListener() {
@@ -123,43 +123,6 @@ public class PullUpTest extends LightCodeInsightTestCase {
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public static MemberInfo[] findMembers(final PsiClass sourceClass, final MemberDescriptor... membersToFind) {
MemberInfo[] infos = new MemberInfo[membersToFind.length];
for (int i = 0; i < membersToFind.length; i++) {
final Class<? extends PsiMember> clazz = membersToFind[i].myClass;
final String name = membersToFind[i].myName;
PsiMember member = null;
boolean overrides = false;
PsiReferenceList refList = null;
if (PsiClass.class.isAssignableFrom(clazz)) {
member = sourceClass.findInnerClassByName(name, false);
if (member == null) {
final PsiClass[] supers = sourceClass.getSupers();
for (PsiClass superTypeClass : supers) {
if (superTypeClass.getName().equals(name)) {
member = superTypeClass;
overrides = true;
refList = superTypeClass.isInterface() ? sourceClass.getImplementsList() : sourceClass.getExtendsList();
break;
}
}
}
} else if (PsiMethod.class.isAssignableFrom(clazz)) {
final PsiMethod[] methods = sourceClass.findMethodsByName(name, false);
assertEquals(1, methods.length);
member = methods[0];
} else if (PsiField.class.isAssignableFrom(clazz)) {
member = sourceClass.findFieldByName(name, false);
}
assertNotNull(member);
infos[i] = new MemberInfo(member, overrides, refList);
infos[i].setToAbstract(membersToFind[i].myAbstract);
}
return infos;
}
protected Sdk getProjectJDK() {
return JavaSdkImpl.getMockJdk15("50");
}
@@ -168,21 +131,5 @@ public class PullUpTest extends LightCodeInsightTestCase {
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath();
}
public static class MemberDescriptor {
private String myName;
private Class<? extends PsiMember> myClass;
private boolean myAbstract;
public MemberDescriptor(String name, Class<? extends PsiMember> aClass, boolean isAbstract) {
myName = name;
myClass = aClass;
myAbstract = isAbstract;
}
public MemberDescriptor(String name, Class<? extends PsiMember> aClass) {
this(name, aClass, false);
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2000-2010 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-Jun-2010
*/
package com.intellij.refactoring;
import com.intellij.psi.*;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import junit.framework.Assert;
public class RefactoringTestUtil {
public static MemberInfo[] findMembers(final PsiClass sourceClass, final MemberDescriptor... membersToFind) {
MemberInfo[] infos = new MemberInfo[membersToFind.length];
for (int i = 0; i < membersToFind.length; i++) {
final Class<? extends PsiMember> clazz = membersToFind[i].myClass;
final String name = membersToFind[i].myName;
PsiMember member = null;
boolean overrides = false;
PsiReferenceList refList = null;
if (PsiClass.class.isAssignableFrom(clazz)) {
member = sourceClass.findInnerClassByName(name, false);
if (member == null) {
final PsiClass[] supers = sourceClass.getSupers();
for (PsiClass superTypeClass : supers) {
if (superTypeClass.getName().equals(name)) {
member = superTypeClass;
overrides = true;
refList = superTypeClass.isInterface() ? sourceClass.getImplementsList() : sourceClass.getExtendsList();
break;
}
}
}
} else if (PsiMethod.class.isAssignableFrom(clazz)) {
final PsiMethod[] methods = sourceClass.findMethodsByName(name, false);
Assert.assertEquals(1, methods.length);
member = methods[0];
} else if (PsiField.class.isAssignableFrom(clazz)) {
member = sourceClass.findFieldByName(name, false);
}
Assert.assertNotNull(member);
infos[i] = new MemberInfo(member, overrides, refList);
infos[i].setToAbstract(membersToFind[i].myAbstract);
}
return infos;
}
public static class MemberDescriptor {
private String myName;
private Class<? extends PsiMember> myClass;
private boolean myAbstract;
public MemberDescriptor(String name, Class<? extends PsiMember> aClass, boolean isAbstract) {
myName = name;
myClass = aClass;
myAbstract = isAbstract;
}
public MemberDescriptor(String name, Class<? extends PsiMember> aClass) {
this(name, aClass, false);
}
}
}