introduce constant: create subclass when it is not possible to place the constant inside the class (IDEA-86965)

This commit is contained in:
Anna Kozlova
2012-06-04 18:14:44 +04:00
parent 6bbbb5031f
commit 201978075d
6 changed files with 70 additions and 21 deletions
@@ -704,7 +704,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
initializer = IntroduceVariableBase.replaceExplicitWithDiamondWhenApplicable(initializer, myType);
final PsiMethod enclosingConstructor = getEnclosingConstructor(myParentClass, myAnchorElement);
final PsiClass destClass = mySettings.getDestinationClass() == null ? myParentClass : mySettings.getDestinationClass();
PsiClass destClass = mySettings.getDestinationClass() == null ? myParentClass : mySettings.getDestinationClass();
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, destClass.getContainingFile())) return;
@@ -716,7 +716,29 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
myParentClass);
setModifiers(myField, mySettings);
myField = appendField(initializer, initializerPlace, destClass, myParentClass, myAnchorElement, myField);
PsiElement finalAnchorElement = null;
if (destClass == myParentClass) {
for (finalAnchorElement = myAnchorElement;
finalAnchorElement != null && finalAnchorElement.getParent() != destClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
if (anchorMember instanceof PsiEnumConstant && destClass == anchorMember.getContainingClass()) {
String constantsClassName = "Constants";
int i = 1;
while (destClass.findInnerClassByName(constantsClassName, true) != null) {
constantsClassName += constantsClassName + i++;
}
PsiClass psiClass = JavaPsiFacade.getElementFactory(myProject).createClass(constantsClassName);
PsiUtil.setModifierProperty(psiClass, PsiModifier.PRIVATE, true);
destClass = (PsiClass)destClass.add(psiClass);
anchorMember = null;
}
myField = appendField(initializer, initializerPlace, destClass, myParentClass, myField, anchorMember);
if (!mySettings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(myOccurrences, myField, mySettings.getFieldVisibility());
}
@@ -823,18 +845,9 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
static PsiField appendField(final PsiExpression initializer,
InitializationPlace initializerPlace, final PsiClass destClass,
final PsiClass parentClass,
final PsiElement anchorElement,
final PsiField psiField) {
PsiElement finalAnchorElement = null;
if (destClass == parentClass) {
for (finalAnchorElement = anchorElement;
finalAnchorElement != null && finalAnchorElement.getParent() != destClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
final PsiField psiField,
final PsiMember anchorMember) {
if ((anchorMember instanceof PsiField) &&
anchorMember.hasModifierProperty(PsiModifier.STATIC) == psiField.hasModifierProperty(PsiModifier.STATIC)) {
return (PsiField)destClass.addBefore(psiField, anchorMember);
@@ -72,7 +72,6 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
gc.gridy = 2;
myWholePanel.add(createLeftPanel(), gc);
}
@Nullable
@@ -103,7 +102,8 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
private JPanel createLeftPanel() {
final JPanel left = new JPanel(new GridBagLayout());
myMoveToAnotherClassCb = new JCheckBox("Move to another class", JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS);
myMoveToAnotherClassCb =
new JCheckBox("Move to another class", JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS);
myMoveToAnotherClassCb.setMnemonic('m');
myMoveToAnotherClassCb.setFocusable(false);
left.add(myMoveToAnotherClassCb,
@@ -141,9 +141,15 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
if (visibility != null) {
PsiUtil.setModifierProperty(field, visibility, true);
}
final PsiElement anchorElementIfAll = getAnchorElementIfAll();
PsiElement finalAnchorElement;
for (finalAnchorElement = anchorElementIfAll;
finalAnchorElement != null && finalAnchorElement.getParent() != myParentClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
field = BaseExpressionToFieldHandler.ConvertToFieldRunnable
.appendField(myExpr, BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, myParentClass, myParentClass,
getAnchorElementIfAll(), field);
.appendField(myExpr, BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, myParentClass, myParentClass, field, anchorMember);
myFieldRangeStart = myEditor.getDocument().createRangeMarker(field.getTextRange());
return field;
}
@@ -228,7 +234,8 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
protected void run(Result result) throws Throwable {
if (getLocalVariable() != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable)getLocalVariable(), myParentClass, settings, true, myOccurrences);
new LocalToFieldHandler.IntroduceFieldRunnable(false, (PsiLocalVariable)getLocalVariable(), myParentClass, settings, true,
myOccurrences);
fieldRunnable.run();
}
else {
@@ -37,6 +37,7 @@ import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
@@ -129,7 +130,7 @@ class IntroduceConstantDialog extends DialogWrapper {
init();
myVPanel.setVisibility(JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY);
myIntroduceEnumConstantCb.setEnabled(EnumConstantsUtil.isSuitableForEnumConstant(getSelectedType(), myTargetClass));
myIntroduceEnumConstantCb.setEnabled(isSuitableForEnumConstant());
updateVisibilityPanel();
updateButtons();
}
@@ -324,7 +325,13 @@ class IntroduceConstantDialog extends DialogWrapper {
final String targetClassName = getTargetClassName();
myTargetClass = JavaPsiFacade.getInstance(myProject).findClass(targetClassName, GlobalSearchScope.projectScope(myProject));
updateVisibilityPanel();
myIntroduceEnumConstantCb.setEnabled(EnumConstantsUtil.isSuitableForEnumConstant(getSelectedType(), myTargetClass));
myIntroduceEnumConstantCb.setEnabled(isSuitableForEnumConstant());
}
private boolean isSuitableForEnumConstant() {
return EnumConstantsUtil.isSuitableForEnumConstant(getSelectedType(), myTargetClass) && PsiTreeUtil
.getParentOfType(myInitializerExpression,
PsiEnumConstant.class) == null;
}
private void enableEnumDependant(boolean enable) {
@@ -0,0 +1,6 @@
enum TestEnum {
ONE("te<caret>stString");
TestEnum(String str) {
}
}
@@ -0,0 +1,10 @@
enum TestEnum {
ONE(Constants.xxx);
TestEnum(String str) {
}
private class Constants {
public static final String xxx = "testString";
}
}
@@ -34,6 +34,12 @@ public class IntroduceConstantTest extends LightCodeInsightTestCase {
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testFromEnumConstantInitializer() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null).invoke(getProject(), getEditor(), getFile(), null);
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testEnumConstant() throws Exception {
doTest(true);
}