From 828bdcac9b6e786a79af8bb3c4ee3fa1fa81416d Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 16 Mar 2011 19:34:03 +0100 Subject: [PATCH] choose class to introduce field/constant to --- .../BaseExpressionToFieldHandler.java | 87 +++++++++++++------ .../IntroduceConstantHandler.java | 4 + .../introduceField/IntroduceFieldHandler.java | 4 + .../introduceField/LocalToFieldHandler.java | 40 +++++++-- 4 files changed, 100 insertions(+), 35 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java index c8367bb08d6c..895d766927df 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java @@ -29,8 +29,10 @@ import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.codeInsight.TestUtil; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.navigation.NavigationUtil; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.ide.util.PackageUtil; +import com.intellij.ide.util.PsiClassListCellRenderer; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.CommandProcessor; @@ -51,6 +53,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilBase; @@ -83,8 +86,13 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase IN_SETUP_METHOD } + private boolean myIsConstant; private PsiClass myParentClass; + protected BaseExpressionToFieldHandler(boolean isConstant) { + myIsConstant = isConstant; + } + protected boolean invokeImpl(final Project project, @NotNull final PsiExpression selectedExpr, final Editor editor) { final PsiElement element = getPhysicalElement(selectedExpr); @@ -95,24 +103,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase LOG.debug("expression:" + selectedExpr); } - myParentClass = getParentClass(selectedExpr); - if (myParentClass == null) { - if (JspPsiUtil.isInJspFile(file)) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.message("error.not.supported.for.jsp", getRefactoringName()), - getRefactoringName(), getHelpID()); - return false; - } - else { - LOG.assertTrue(false); - return false; - } - } - - if (!validClass(myParentClass, editor)) { - return false; - } - - PsiType tempType = getTypeByExpression(selectedExpr); + final PsiType tempType = getTypeByExpression(selectedExpr); if (tempType == null) { String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("unknown.expression.type")); CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), getHelpID()); @@ -125,11 +116,55 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase return false; } + myParentClass = getParentClass(selectedExpr); + final List classes = new ArrayList(); + PsiClass aClass = myParentClass; + while (aClass != null) { + classes.add(aClass); + aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true); + } + if (classes.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { + return !convertExpressionToField(selectedExpr, editor, file, project, tempType); + } + else { + NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), + "Choose class to introduce " + (myIsConstant ? "constant" : "field"), + new PsiElementProcessor() { + @Override + public boolean execute(PsiClass aClass) { + myParentClass = aClass; + convertExpressionToField(selectedExpr, editor, file, project, tempType); + return false; + } + }).showInBestPositionFor(editor); + } + return true; + } - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return false; + private boolean convertExpressionToField(PsiExpression selectedExpr, + Editor editor, + PsiFile file, + final Project project, + PsiType tempType) { + if (myParentClass == null) { + if (JspPsiUtil.isInJspFile(file)) { + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.message("error.not.supported.for.jsp", getRefactoringName()), + getRefactoringName(), getHelpID()); + return true; + } + else { + LOG.assertTrue(false); + return true; + } + } - final PsiClass parentClass = myParentClass; - final OccurenceManager occurenceManager = createOccurenceManager(selectedExpr, parentClass); + if (!validClass(myParentClass, editor)) { + return true; + } + + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return true; + + final OccurenceManager occurenceManager = createOccurenceManager(selectedExpr, myParentClass); final PsiExpression[] occurrences = occurenceManager.getOccurences(); final PsiElement anchorStatementIfAll = occurenceManager.getAnchorStatementForAll(); @@ -140,13 +175,14 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase PsiElement tempAnchorElement = RefactoringUtil.getParentExpressionAnchorElement(selectedExpr); if (!Comparing.strEqual(IntroduceConstantHandler.REFACTORING_NAME, getRefactoringName()) && - IntroduceVariableBase.checkAnchorBeforeThisOrSuper(project, editor, tempAnchorElement, getRefactoringName(), getHelpID())) return false; + IntroduceVariableBase.checkAnchorBeforeThisOrSuper(project, editor, tempAnchorElement, getRefactoringName(), getHelpID())) + return true; final Settings settings = showRefactoringDialog(project, editor, myParentClass, selectedExpr, tempType, occurrences, tempAnchorElement, anchorStatementIfAll); - if (settings == null) return false; + if (settings == null) return true; if (settings.getForcedType() != null) { tempType = settings.getForcedType(); @@ -172,8 +208,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase runnable.run(); } }.execute(); - - return true; + return false; } public static void setModifiers(PsiField field, Settings settings, final boolean declareStatic) { @@ -251,7 +286,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase if (element == null) element = initializerExpression.getParent(); PsiElement parent = element; while (parent != null) { - if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) { + if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass && myIsConstant)) { return (PsiClass)parent; } parent = parent.getParent(); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java index ce76aa6d6c23..b34ac13ee7f1 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java @@ -44,6 +44,10 @@ import java.util.ArrayList; public class IntroduceConstantHandler extends BaseExpressionToFieldHandler { public static final String REFACTORING_NAME = RefactoringBundle.message("introduce.constant.title"); + public IntroduceConstantHandler() { + super(true); + } + protected String getHelpID() { return HelpID.INTRODUCE_CONSTANT; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java index 65cee01e33c3..08cc4d68bfd0 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java @@ -36,6 +36,10 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler { public static final String REFACTORING_NAME = RefactoringBundle.message("introduce.field.title"); private static final MyOccurenceFilter MY_OCCURENCE_FILTER = new MyOccurenceFilter(); + public IntroduceFieldHandler() { + super(false); + } + protected String getRefactoringName() { return REFACTORING_NAME; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java index bdb26a8e9b45..7e5c5b47d83d 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java @@ -17,6 +17,8 @@ package com.intellij.refactoring.introduceField; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.TestUtil; +import com.intellij.codeInsight.navigation.NavigationUtil; +import com.intellij.ide.util.PsiClassListCellRenderer; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -25,17 +27,23 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.ui.ClassCellRenderer; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.EnumConstantsUtil; import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.ui.components.panels.OpaquePanel; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NonNls; +import java.util.ArrayList; +import java.util.List; + import static com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR; import static com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION; @@ -54,14 +62,12 @@ public abstract class LocalToFieldHandler { protected abstract BaseExpressionToFieldHandler.Settings showRefactoringDialog(PsiClass aClass, PsiLocalVariable local, PsiExpression[] occurences, boolean isStatic); public boolean convertLocalToField(final PsiLocalVariable local, final Editor editor) { - PsiClass aClass; boolean tempIsStatic = myIsConstant; PsiElement parent = local.getParent(); - - while (true) { - if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) { - aClass = (PsiClass)parent; - break; + List classes = new ArrayList(); + while (parent != null && parent.getContainingFile() != null) { + if (parent instanceof PsiClass && !(myIsConstant && parent instanceof PsiAnonymousClass)) { + classes.add((PsiClass)parent); } if (parent instanceof PsiFile && JspPsiUtil.isInJspFile(parent)) { String message = RefactoringBundle.message("error.not.supported.for.jsp", REFACTORING_NAME); @@ -74,15 +80,31 @@ public abstract class LocalToFieldHandler { parent = parent.getParent(); } - final boolean isStatic = tempIsStatic; + if (classes.isEmpty()) return false; + if (classes.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { + if (convertLocalToField(local, classes.get(0), editor, tempIsStatic)) return false; + } else { + final boolean isStatic = tempIsStatic; + NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor() { + @Override + public boolean execute(PsiClass aClass) { + convertLocalToField(local, aClass, editor, isStatic); + return false; + } + }).showInBestPositionFor(editor); + } + return true; + } + + private boolean convertLocalToField(PsiLocalVariable local, PsiClass aClass, Editor editor, boolean isStatic) { final PsiExpression[] occurences = CodeInsightUtil.findReferenceExpressions(RefactoringUtil.getVariableScope(local), local); if (editor != null) { RefactoringUtil.highlightAllOccurences(myProject, occurences, editor); } final BaseExpressionToFieldHandler.Settings settings = showRefactoringDialog(aClass, local, occurences, isStatic); - if (settings == null) return false; + if (settings == null) return true; //LocalToFieldDialog dialog = new LocalToFieldDialog(project, aClass, local, isStatic); final PsiClass destinationClass = settings.getDestinationClass(); boolean rebindNeeded = false; @@ -100,7 +122,7 @@ public abstract class LocalToFieldHandler { ApplicationManager.getApplication().runWriteAction(runnable); } }, REFACTORING_NAME, null); - return true; + return false; } private static PsiField createField(PsiLocalVariable local, PsiType forcedType, String fieldName, boolean includeInitializer) {