inplace introduce field

This commit is contained in:
anna
2011-03-17 15:02:39 +01:00
parent a36e66ba11
commit f82cbec6d5
12 changed files with 1418 additions and 856 deletions
@@ -32,7 +32,9 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.ide.util.DirectoryChooserUtil;
import com.intellij.ide.util.PackageUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
@@ -70,7 +72,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase implements RefactoringActionHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler");
@@ -152,15 +153,6 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
final PsiType type = tempType;
final String fieldName = settings.getFieldName();
final PsiElement anchorElementIfOne = tempAnchorElement;
final boolean replaceAll = settings.isReplaceAll();
if (replaceAll) {
tempAnchorElement = anchorStatementIfAll;
}
final PsiElement anchorElement = tempAnchorElement;
if (editor != null) {
HighlightManager highlightManager = HighlightManager.getInstance(project);
for (RangeHighlighter highlighter : highlighters) {
@@ -168,194 +160,18 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
}
PsiElement anchor = getNormalizedAnchor(anchorElement);
final Boolean outOfCodeBlockExtraction = selectedExpr.getUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK);
boolean tempDeleteSelf = outOfCodeBlockExtraction != null;
if (element.getParent() instanceof PsiExpressionStatement && anchor.equals(anchorElement)) {
PsiStatement statement = (PsiStatement)element.getParent();
if (statement.getParent() instanceof PsiCodeBlock) {
tempDeleteSelf = true;
final Runnable runnable =
new ConvertToFieldRunnable(selectedExpr, settings, type, occurrences, occurenceManager,
anchorStatementIfAll, tempAnchorElement, editor,
myParentClass);
new WriteCommandAction(project, getRefactoringName()){
@Override
protected void run(Result result) throws Throwable {
runnable.run();
}
}
final boolean deleteSelf = tempDeleteSelf;
final Runnable runnable = new Runnable() {
public void run() {
try {
PsiExpression expr = selectedExpr;
InitializationPlace initializerPlace = settings.getInitializerPlace();
final PsiLocalVariable localVariable = settings.getLocalVariable();
final boolean deleteLocalVariable = settings.isDeleteLocalVariable();
@Nullable PsiExpression initializer;
if (localVariable != null) {
initializer = localVariable.getInitializer();
}
else {
initializer = expr;
}
final PsiMethod enclosingConstructor = getEnclosingConstructor(myParentClass, anchorElement);
final PsiClass destClass = settings.getDestinationClass() == null ? myParentClass : settings.getDestinationClass();
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, destClass.getContainingFile())) return;
if (initializer != null) {
ChangeContextUtil.encodeContextInfo(initializer, true);
}
PsiField field = settings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(destClass, fieldName, initializer) : createField(fieldName, type, initializer, initializerPlace == InitializationPlace.IN_FIELD_DECLARATION && initializer != null);
PsiElement finalAnchorElement = null;
if (destClass == myParentClass) {
for (finalAnchorElement = anchorElement;
finalAnchorElement != null && finalAnchorElement.getParent() != destClass;
finalAnchorElement = finalAnchorElement.getParent()) {
}
}
PsiMember anchorMember = finalAnchorElement instanceof PsiMember ? (PsiMember)finalAnchorElement : null;
setModifiers(field, settings, settings.isDeclareStatic());
if ((anchorMember instanceof PsiField) &&
anchorMember.hasModifierProperty(PsiModifier.STATIC) == field.hasModifierProperty(PsiModifier.STATIC)) {
field = (PsiField)destClass.addBefore(field, anchorMember);
}
else if (anchorMember instanceof PsiClassInitializer) {
field = (PsiField)destClass.addBefore(field, anchorMember);
destClass.addBefore(CodeEditUtil.createLineFeed(field.getManager()), anchorMember);
}
else {
final PsiField forwardReference = checkForwardRefs(initializer);
if (forwardReference != null) {
field = (PsiField)destClass.addAfter(field, forwardReference);
} else {
field = (PsiField)destClass.add(field);
}
}
if (!settings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(occurrences, field, settings.getFieldVisibility());
}
PsiStatement assignStatement = null;
PsiElement anchorElementHere = null;
if (initializerPlace == InitializationPlace.IN_CURRENT_METHOD && initializer != null ||
initializerPlace == InitializationPlace.IN_CONSTRUCTOR && enclosingConstructor != null && initializer != null) {
if (replaceAll) {
if (enclosingConstructor != null) {
final PsiElement anchorInConstructor = occurenceManager.getAnchorStatementForAllInScope(enclosingConstructor);
anchorElementHere = anchorInConstructor != null ? anchorInConstructor : anchorStatementIfAll;
}
else {
anchorElementHere = anchorStatementIfAll;
}
}
else {
anchorElementHere = anchorElementIfOne;
}
assignStatement = createAssignment(field, initializer, anchorElementHere);
if (!IntroduceVariableBase.isLoopOrIf(anchorElementHere.getParent())) {
anchorElementHere.getParent().addBefore(assignStatement, getNormalizedAnchor(anchorElementHere));
}
}
if (initializerPlace == InitializationPlace.IN_CONSTRUCTOR && initializer != null) {
addInitializationToConstructors(initializer, field, enclosingConstructor);
}
if (initializerPlace == InitializationPlace.IN_SETUP_METHOD && initializer != null) {
addInitializationToSetUp(initializer, field, occurenceManager, replaceAll);
}
if (expr.getParent() instanceof PsiParenthesizedExpression) {
expr = (PsiExpression)expr.getParent();
}
if (outOfCodeBlockExtraction != null) {
final int endOffset = selectedExpr.getUserData(ElementToWorkOn.TEXT_RANGE).getEndOffset();
PsiElement endElement = element.getContainingFile().findElementAt(endOffset);
while (true) {
final PsiElement parent = endElement.getParent();
if (parent instanceof PsiClass) break;
endElement = parent;
}
element.getParent().deleteChildRange(element, PsiTreeUtil.skipSiblingsBackward(endElement, PsiWhiteSpace.class));
} else if (deleteSelf) {
element.getParent().delete();
}
if (replaceAll) {
List<PsiElement> array = new ArrayList<PsiElement>();
for (PsiExpression occurrence : occurrences) {
if (occurrence instanceof PsiExpression) {
occurrence = RefactoringUtil.outermostParenthesizedExpression(occurrence);
}
if (deleteSelf && occurrence.equals(expr)) continue;
final PsiElement replaced = RefactoringUtil.replaceOccurenceWithFieldRef(occurrence, field, destClass);
if (replaced != null) {
array.add(replaced);
}
}
if (editor != null) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
PsiElement[] exprsToHighlight = PsiUtilBase.toPsiElementArray(array);
HighlightManager highlightManager = HighlightManager.getInstance(project);
highlightManager.addOccurrenceHighlights(editor, exprsToHighlight, highlightAttributes(), true, null);
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
}
}
else {
if (!deleteSelf) {
expr = RefactoringUtil.outermostParenthesizedExpression(expr);
RefactoringUtil.replaceOccurenceWithFieldRef(expr, field, destClass);
}
}
if (anchorElementHere != null && IntroduceVariableBase.isLoopOrIf(anchorElementHere.getParent())) {
IntroduceVariableBase.putStatementInLoopBody(assignStatement, anchorElementHere.getParent(), anchorElementHere);
}
if (localVariable != null) {
if (deleteLocalVariable) {
localVariable.normalizeDeclaration();
localVariable.getParent().delete();
}
}
if (initializer != null) {
ChangeContextUtil.clearContextInfo(initializer);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
private PsiField checkForwardRefs(PsiExpression initializer) {
final PsiField[] refConstantFields = new PsiField[1];
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiField &&
((PsiField)resolve).hasModifierProperty(PsiModifier.FINAL) &&
PsiTreeUtil.isAncestor(myParentClass, resolve, false) && ((PsiField)resolve).hasInitializer()) {
if (refConstantFields[0] == null || refConstantFields[0].getTextOffset() < resolve.getTextOffset()) {
refConstantFields[0] = (PsiField)resolve;
}
}
}
});
return refConstantFields[0];
}
};
CommandProcessor.getInstance().executeCommand(
project,
new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(runnable);
}
},
getRefactoringName(), null
);
}.execute();
return true;
}
@@ -452,10 +268,12 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
return null;
}
private void addInitializationToSetUp(final PsiExpression initializer,
final PsiField field,
final OccurenceManager occurenceManager, final boolean replaceAll) throws IncorrectOperationException {
final PsiMethod setupMethod = TestUtil.findOrCreateSetUpMethod(myParentClass);
private static void addInitializationToSetUp(final PsiExpression initializer,
final PsiField field,
final OccurenceManager occurenceManager,
final boolean replaceAll,
final PsiClass parentClass) throws IncorrectOperationException {
final PsiMethod setupMethod = TestUtil.findOrCreateSetUpMethod(parentClass);
assert setupMethod != null;
@@ -467,7 +285,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
final PsiExpressionStatement expressionStatement =
(PsiExpressionStatement)JavaPsiFacade.getInstance(myParentClass.getProject()).getElementFactory()
(PsiExpressionStatement)JavaPsiFacade.getInstance(parentClass.getProject()).getElementFactory()
.createStatementFromText(field.getName() + "= expr;", null);
PsiAssignmentExpression expr = (PsiAssignmentExpression)expressionStatement.getExpression();
final PsiExpression rExpression = expr.getRExpression();
@@ -479,7 +297,9 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
body.addBefore(expressionStatement, anchor);
}
private void addInitializationToConstructors(PsiExpression initializerExpression, PsiField field, PsiMethod enclosingConstructor) {
private static void addInitializationToConstructors(PsiExpression initializerExpression,
PsiField field,
PsiMethod enclosingConstructor, final PsiClass parentClass) {
try {
PsiClass aClass = field.getContainingClass();
PsiMethod[] constructors = aClass.getConstructors();
@@ -502,7 +322,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
}
}
PsiStatement assignment = createAssignment(field, initializerExpression, body.getLastChild());
PsiStatement assignment = createAssignment(field, initializerExpression, body.getLastChild(), parentClass);
assignment = (PsiStatement) body.add(assignment);
ChangeContextUtil.decodeContextInfo(assignment, field.getContainingClass(),
RefactoringUtil.createThisExpression(field.getManager(), null));
@@ -512,7 +332,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
PsiMethod constructor = (PsiMethod)aClass.add(factory.createConstructor());
final PsiCodeBlock body = constructor.getBody();
PsiStatement assignment = createAssignment(field, initializerExpression, body.getLastChild());
PsiStatement assignment = createAssignment(field, initializerExpression, body.getLastChild(), parentClass);
assignment = (PsiStatement) body.add(assignment);
ChangeContextUtil.decodeContextInfo(assignment, field.getContainingClass(),
RefactoringUtil.createThisExpression(field.getManager(), null));
@@ -523,7 +343,10 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
}
private PsiField createField(String fieldName, PsiType type, PsiExpression initializerExpr, boolean includeInitializer) {
private static PsiField createField(String fieldName,
PsiType type,
PsiExpression initializerExpr,
boolean includeInitializer, final PsiClass parentClass) {
@NonNls StringBuilder pattern = new StringBuilder();
pattern.append("private int ");
pattern.append(fieldName);
@@ -531,7 +354,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
pattern.append("=0");
}
pattern.append(";");
PsiManager psiManager = myParentClass.getManager();
PsiManager psiManager = parentClass.getManager();
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
try {
PsiField field = factory.createFieldFromText(pattern.toString(), null);
@@ -548,10 +371,13 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
}
}
private PsiStatement createAssignment(PsiField field, PsiExpression initializerExpr, PsiElement context) {
private static PsiStatement createAssignment(PsiField field,
PsiExpression initializerExpr,
PsiElement context,
final PsiClass parentClass) {
try {
@NonNls String pattern = "x=0;";
PsiManager psiManager = myParentClass.getManager();
PsiManager psiManager = parentClass.getManager();
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(pattern, null);
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(psiManager.getProject()).reformat(statement);
@@ -733,4 +559,230 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
return myTargetClass;
}
}
public static class ConvertToFieldRunnable implements Runnable {
private PsiExpression mySelectedExpr;
private final Settings mySettings;
private final PsiElement myAnchorElement;
private final Project myProject;
private final String myFieldName;
private final PsiType myType;
private final PsiExpression[] myOccurrences;
private final boolean myReplaceAll;
private final OccurenceManager myOccurenceManager;
private final PsiElement myAnchorStatementIfAll;
private final PsiElement myAnchorElementIfOne;
private final Boolean myOutOfCodeBlockExtraction;
private final PsiElement myElement;
private boolean myDeleteSelf;
private final Editor myEditor;
private final PsiClass myParentClass;
private PsiField myField;
public ConvertToFieldRunnable(PsiExpression selectedExpr,
Settings settings,
PsiType type,
PsiExpression[] occurrences,
OccurenceManager occurenceManager,
PsiElement anchorStatementIfAll,
PsiElement anchorElementIfOne,
Editor editor,
PsiClass parentClass) {
mySelectedExpr = selectedExpr;
mySettings = settings;
myAnchorElement = settings.isReplaceAll() ? anchorStatementIfAll : anchorElementIfOne;
myProject = selectedExpr.getProject();
myFieldName = settings.getFieldName();
myType = type;
myOccurrences = occurrences;
myReplaceAll = settings.isReplaceAll();
myOccurenceManager = occurenceManager;
myAnchorStatementIfAll = anchorStatementIfAll;
myAnchorElementIfOne = anchorElementIfOne;
myOutOfCodeBlockExtraction = selectedExpr.getUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK);
myDeleteSelf = myOutOfCodeBlockExtraction != null;
myElement = getPhysicalElement(selectedExpr);
if (myElement.getParent() instanceof PsiExpressionStatement && getNormalizedAnchor(myAnchorElement).equals(myAnchorElement)) {
PsiStatement statement = (PsiStatement)myElement.getParent();
if (statement.getParent() instanceof PsiCodeBlock) {
myDeleteSelf = true;
}
}
myEditor = editor;
myParentClass = parentClass;
}
public void run() {
try {
InitializationPlace initializerPlace = mySettings.getInitializerPlace();
final PsiLocalVariable localVariable = mySettings.getLocalVariable();
final boolean deleteLocalVariable = mySettings.isDeleteLocalVariable();
@Nullable PsiExpression initializer;
if (localVariable != null) {
initializer = localVariable.getInitializer();
}
else {
initializer = mySelectedExpr;
}
final PsiMethod enclosingConstructor = getEnclosingConstructor(myParentClass, myAnchorElement);
final PsiClass destClass = mySettings.getDestinationClass() == null ? myParentClass : mySettings.getDestinationClass();
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, destClass.getContainingFile())) return;
if (initializer != null) {
ChangeContextUtil.encodeContextInfo(initializer, true);
}
myField = mySettings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(destClass, myFieldName, initializer) :
createField(myFieldName, myType, initializer, initializerPlace == InitializationPlace.IN_FIELD_DECLARATION && initializer != null,
myParentClass);
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;
setModifiers(myField, mySettings, mySettings.isDeclareStatic());
if ((anchorMember instanceof PsiField) &&
anchorMember.hasModifierProperty(PsiModifier.STATIC) == myField.hasModifierProperty(PsiModifier.STATIC)) {
myField = (PsiField)destClass.addBefore(myField, anchorMember);
}
else if (anchorMember instanceof PsiClassInitializer) {
myField = (PsiField)destClass.addBefore(myField, anchorMember);
destClass.addBefore(CodeEditUtil.createLineFeed(myField.getManager()), anchorMember);
}
else {
final PsiField forwardReference = checkForwardRefs(initializer);
if (forwardReference != null) {
myField = (PsiField)destClass.addAfter(myField, forwardReference);
} else {
myField = (PsiField)destClass.add(myField);
}
}
if (!mySettings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(myOccurrences, myField, mySettings.getFieldVisibility());
}
PsiStatement assignStatement = null;
PsiElement anchorElementHere = null;
if (initializerPlace == InitializationPlace.IN_CURRENT_METHOD && initializer != null ||
initializerPlace == InitializationPlace.IN_CONSTRUCTOR && enclosingConstructor != null && initializer != null) {
if (myReplaceAll) {
if (enclosingConstructor != null) {
final PsiElement anchorInConstructor = myOccurenceManager.getAnchorStatementForAllInScope(enclosingConstructor);
anchorElementHere = anchorInConstructor != null ? anchorInConstructor : myAnchorStatementIfAll;
}
else {
anchorElementHere = myAnchorStatementIfAll;
}
}
else {
anchorElementHere = myAnchorElementIfOne;
}
assignStatement = createAssignment(myField, initializer, anchorElementHere, myParentClass);
if (!IntroduceVariableBase.isLoopOrIf(anchorElementHere.getParent())) {
anchorElementHere.getParent().addBefore(assignStatement, getNormalizedAnchor(anchorElementHere));
}
}
if (initializerPlace == InitializationPlace.IN_CONSTRUCTOR && initializer != null) {
addInitializationToConstructors(initializer, myField, enclosingConstructor, myParentClass);
}
if (initializerPlace == InitializationPlace.IN_SETUP_METHOD && initializer != null) {
addInitializationToSetUp(initializer, myField, myOccurenceManager, myReplaceAll, myParentClass);
}
if (mySelectedExpr.getParent() instanceof PsiParenthesizedExpression) {
mySelectedExpr = (PsiExpression)mySelectedExpr.getParent();
}
if (myOutOfCodeBlockExtraction != null) {
final int endOffset = mySelectedExpr.getUserData(ElementToWorkOn.TEXT_RANGE).getEndOffset();
PsiElement endElement = myElement.getContainingFile().findElementAt(endOffset);
while (true) {
final PsiElement parent = endElement.getParent();
if (parent instanceof PsiClass) break;
endElement = parent;
}
myElement.getParent().deleteChildRange(myElement, PsiTreeUtil.skipSiblingsBackward(endElement, PsiWhiteSpace.class));
} else if (myDeleteSelf) {
myElement.getParent().delete();
}
if (myReplaceAll) {
List<PsiElement> array = new ArrayList<PsiElement>();
for (PsiExpression occurrence : myOccurrences) {
if (occurrence instanceof PsiExpression) {
occurrence = RefactoringUtil.outermostParenthesizedExpression(occurrence);
}
if (myDeleteSelf && occurrence.equals(mySelectedExpr)) continue;
final PsiElement replaced = RefactoringUtil.replaceOccurenceWithFieldRef(occurrence, myField, destClass);
if (replaced != null) {
array.add(replaced);
}
}
if (myEditor != null) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
PsiElement[] exprsToHighlight = PsiUtilBase.toPsiElementArray(array);
HighlightManager highlightManager = HighlightManager.getInstance(myProject);
highlightManager.addOccurrenceHighlights(myEditor, exprsToHighlight, highlightAttributes(), true, null);
WindowManager
.getInstance().getStatusBar(myProject).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
}
}
else {
if (!myDeleteSelf) {
mySelectedExpr = RefactoringUtil.outermostParenthesizedExpression(mySelectedExpr);
RefactoringUtil.replaceOccurenceWithFieldRef(mySelectedExpr, myField, destClass);
}
}
if (anchorElementHere != null && IntroduceVariableBase.isLoopOrIf(anchorElementHere.getParent())) {
IntroduceVariableBase.putStatementInLoopBody(assignStatement, anchorElementHere.getParent(), anchorElementHere);
}
if (localVariable != null) {
if (deleteLocalVariable) {
localVariable.normalizeDeclaration();
localVariable.getParent().delete();
}
}
if (initializer != null) {
ChangeContextUtil.clearContextInfo(initializer);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
private PsiField checkForwardRefs(PsiExpression initializer) {
final PsiField[] refConstantFields = new PsiField[1];
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement resolve = expression.resolve();
if (resolve instanceof PsiField &&
((PsiField)resolve).hasModifierProperty(PsiModifier.FINAL) &&
PsiTreeUtil.isAncestor(myParentClass, resolve, false) && ((PsiField)resolve).hasInitializer()) {
if (refConstantFields[0] == null || refConstantFields[0].getTextOffset() < resolve.getTextOffset()) {
refConstantFields[0] = (PsiField)resolve;
}
}
}
});
return refConstantFields[0];
}
public PsiField getField() {
return myField;
}
}
}
@@ -1,210 +0,0 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.refactoring.introduceField;
import com.intellij.codeInsight.TestUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.ui.IdeBorderFactory;
import javax.swing.*;
import java.awt.event.ItemListener;
public class InitializerPlaceChooser {
private static final Logger LOG = Logger.getInstance("#" + InitializerPlaceChooser.class.getName());
static BaseExpressionToFieldHandler.InitializationPlace ourLastInitializerPlace;
PsiClass myParentClass;
PsiExpression myInitializerExpression;
boolean myAllowInitInMethod;
boolean myAllowInitInMethodIfAll;
JRadioButton myRbInConstructor;
JRadioButton myRbInCurrentMethod;
JRadioButton myRbInFieldDeclaration;
JRadioButton myRbInSetUp;
public InitializerPlaceChooser(PsiClass parentClass,
PsiExpression initializerExpression,
boolean allowInitInMethod, boolean allowInitInMethodIfAll) {
myParentClass = parentClass;
myInitializerExpression = initializerExpression;
myAllowInitInMethod = allowInitInMethod;
myAllowInitInMethodIfAll = allowInitInMethodIfAll;
}
void updateInitializerPlace(boolean replaceAll) {
if (myAllowInitInMethod) {
myRbInCurrentMethod.setEnabled(myAllowInitInMethodIfAll || !replaceAll);
if (!myRbInCurrentMethod.isEnabled() && myRbInCurrentMethod.isSelected()) {
myRbInCurrentMethod.setSelected(false);
myRbInFieldDeclaration.setSelected(true);
}
}
}
void initializeControls(PsiExpression initializerExpression) {
if (initializerExpression != null) {
if (!setEnabledInitializationPlaces(initializerExpression, initializerExpression)) {
myRbInFieldDeclaration.setEnabled(false);
myRbInConstructor.setEnabled(false);
if (myRbInSetUp != null) myRbInSetUp.setEnabled(false);
}
if (!myAllowInitInMethod) {
myRbInCurrentMethod.setEnabled(false);
}
}
else {
myRbInConstructor.setEnabled(false);
myRbInCurrentMethod.setEnabled(false);
myRbInFieldDeclaration.setEnabled(false);
if (myRbInSetUp != null) myRbInSetUp.setEnabled(false);
}
final PsiMethod setUpMethod = TestUtil.findSetUpMethod(myParentClass);
if (myInitializerExpression != null && PsiTreeUtil.isAncestor(setUpMethod, myInitializerExpression, false) && myRbInSetUp.isEnabled() ||
ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD &&
TestUtil.isTestClass(myParentClass) &&
myRbInSetUp.isEnabled()) {
myRbInSetUp.setSelected(true);
}
else if (ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR) {
if (myRbInConstructor.isEnabled()) {
myRbInConstructor.setSelected(true);
}
else {
selectInCurrentMethod();
}
}
else if (ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION) {
if (myRbInFieldDeclaration.isEnabled()) {
myRbInFieldDeclaration.setSelected(true);
}
else {
selectInCurrentMethod();
}
}
else {
selectInCurrentMethod();
}
}
void selectInCurrentMethod() {
if (myRbInCurrentMethod.isEnabled()) {
myRbInCurrentMethod.setSelected(true);
}
else if (myRbInFieldDeclaration.isEnabled()) {
myRbInFieldDeclaration.setSelected(true);
}
else {
myRbInCurrentMethod.setSelected(true);
}
}
public BaseExpressionToFieldHandler.InitializationPlace getInitializerPlace() {
if (myRbInConstructor.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR;
}
if (myRbInCurrentMethod.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_CURRENT_METHOD;
}
if (myRbInFieldDeclaration.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION;
}
if (myRbInSetUp != null && myRbInSetUp.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD;
}
LOG.assertTrue(false);
return BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION;
}
JComponent createInitializerPlacePanel() {
final JPanel initializationPanel = new JPanel();
initializationPanel.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("initialize.in.border.title")));
initializationPanel.setLayout(new BoxLayout(initializationPanel, BoxLayout.Y_AXIS));
myRbInCurrentMethod = new JRadioButton();
myRbInCurrentMethod.setFocusable(false);
myRbInCurrentMethod.setText(RefactoringBundle.message("current.method.radio"));
myRbInCurrentMethod.setEnabled(myAllowInitInMethod);
myRbInFieldDeclaration = new JRadioButton();
myRbInFieldDeclaration.setFocusable(false);
myRbInFieldDeclaration.setText(RefactoringBundle.message("field.declaration.radio"));
myRbInConstructor = new JRadioButton();
myRbInConstructor.setFocusable(false);
myRbInConstructor.setText(RefactoringBundle.message("class.constructors.radio"));
initializationPanel.add(myRbInCurrentMethod);
initializationPanel.add(myRbInFieldDeclaration);
initializationPanel.add(myRbInConstructor);
if (TestUtil.isTestClass(myParentClass)) {
myRbInSetUp = new JRadioButton();
myRbInSetUp.setFocusable(false);
myRbInSetUp.setText(RefactoringBundle.message("setup.method.radio"));
initializationPanel.add(myRbInSetUp);
}
ButtonGroup bg = new ButtonGroup();
bg.add(myRbInCurrentMethod);
bg.add(myRbInFieldDeclaration);
bg.add(myRbInConstructor);
if (myRbInSetUp != null) bg.add(myRbInSetUp);
return initializationPanel;
}
static boolean setEnabledInitializationPlaces(PsiElement initializerPart, PsiElement initializer) {
if (initializerPart instanceof PsiReferenceExpression) {
PsiReferenceExpression refExpr = (PsiReferenceExpression)initializerPart;
if (refExpr.getQualifierExpression() == null) {
PsiElement refElement = refExpr.resolve();
if (refElement == null ||
(refElement instanceof PsiLocalVariable || refElement instanceof PsiParameter) &&
!PsiTreeUtil.isAncestor(initializer, refElement, true)) {
return false;
}
}
}
PsiElement[] children = initializerPart.getChildren();
for (PsiElement child : children) {
if (!setEnabledInitializationPlaces(child, initializer)) return false;
}
return true;
}
boolean allowFinal(boolean willBeDeclaredStatic, boolean isCurrentMethodConstructor) {
boolean allowFinal = myRbInFieldDeclaration.isSelected() || (myRbInConstructor.isSelected() && !willBeDeclaredStatic);
if (myRbInCurrentMethod.isSelected() && isCurrentMethodConstructor) {
final PsiMethod[] constructors = myParentClass.getConstructors();
allowFinal = constructors.length <= 1;
}
return allowFinal;
}
void addItemListener(ItemListener listener) {
myRbInConstructor.addItemListener(listener);
myRbInCurrentMethod.addItemListener(listener);
myRbInFieldDeclaration.addItemListener(listener);
if (myRbInSetUp != null) myRbInSetUp.addItemListener(listener);
}
}
@@ -0,0 +1,381 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.refactoring.introduceField;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.introduceParameter.AbstractInplaceIntroducer;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.occurences.OccurenceManager;
import com.intellij.ui.TitlePanel;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
/**
* User: anna
* Date: 3/15/11
*/
public class InplaceIntroduceFieldPopup {
private PsiLocalVariable myLocalVariable;
private PsiClass myParentClass;
private boolean myStatic;
private PsiExpression[] myOccurrences;
private PsiExpression myInitializerExpression;
private final Editor myEditor;
private Project myProject;
private final TypeSelectorManagerImpl myTypeSelectorManager;
private final PsiElement myAnchorElement;
private final PsiElement myAnchorElementIfAll;
private final OccurenceManager myOccurenceManager;
private List<RangeMarker> myOccurrenceMarkers;
private final IntroduceFieldCentralPanel myIntroduceFieldPanel;
private JPanel myWholePanel;
private String myExprText;
private RangeMarker myExprMarker;
private String myFieldName;
private boolean myInitListeners = false;
public InplaceIntroduceFieldPopup(PsiLocalVariable localVariable,
PsiClass parentClass,
boolean aStatic,
boolean currentMethodConstructor, PsiExpression[] occurrences,
PsiExpression initializerExpression,
TypeSelectorManagerImpl typeSelectorManager,
Editor editor,
final boolean allowInitInMethod,
boolean allowInitInMethodIfAll, final PsiElement anchorElement,
final PsiElement anchorElementIfAll,
final OccurenceManager occurenceManager) {
myLocalVariable = localVariable;
myParentClass = parentClass;
myStatic = aStatic;
myOccurrences = occurrences;
myInitializerExpression = initializerExpression;
myExprText = myInitializerExpression != null ? myInitializerExpression.getText() : null;
myExprMarker = myInitializerExpression != null ? editor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null;
myTypeSelectorManager = typeSelectorManager;
myAnchorElement = anchorElement;
myAnchorElementIfAll = anchorElementIfAll;
myOccurenceManager = occurenceManager;
myProject = myLocalVariable != null ? myLocalVariable.getProject() : myInitializerExpression.getProject();
myEditor = editor;
myIntroduceFieldPanel =
new IntroduceFieldCentralPanel(parentClass, initializerExpression, localVariable, currentMethodConstructor, localVariable != null, aStatic,
myOccurrences.length, allowInitInMethod, allowInitInMethodIfAll, typeSelectorManager);
myWholePanel = new JPanel(new GridBagLayout());
myWholePanel.setBorder(null);
final TitlePanel titlePanel = new TitlePanel();
titlePanel.setBorder(null);
titlePanel.setText(IntroduceFieldHandler.REFACTORING_NAME);
GridBagConstraints gc =
new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
new Insets(0,0,0,0), 0, 0);
myWholePanel.add(titlePanel, gc);
gc.gridy++;
gc.insets.top = 5;
myWholePanel.add(myIntroduceFieldPanel.createCenterPanel(), gc);
myIntroduceFieldPanel.initializeControls(initializerExpression);
myIntroduceFieldPanel.addOccurrenceListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
if (templateState != null) {
templateState.gotoEnd(true);
startTemplate(myIntroduceFieldPanel.isReplaceAllOccurrences());
}
}
});
}
public List<RangeMarker> getOccurrenceMarkers() {
if (myOccurrenceMarkers == null) {
myOccurrenceMarkers = new ArrayList<RangeMarker>();
for (PsiExpression occurrence : myOccurrences) {
myOccurrenceMarkers.add(myEditor.getDocument().createRangeMarker(occurrence.getTextRange()));
}
}
return myOccurrenceMarkers;
}
public void startTemplate() {
startTemplate(false);
}
public void startTemplate(final boolean replaceAllOccurrences) {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
myTypeSelectorManager.setAllOccurences(replaceAllOccurrences);
final PsiType defaultType = myTypeSelectorManager.getTypeSelector().getSelectedType();
final SuggestedNameInfo suggestedNameInfo =
IntroduceFieldDialog.createGenerator(myStatic, myLocalVariable, myInitializerExpression, myLocalVariable != null)
.getSuggestedNameInfo(defaultType);
final PsiField field = createFieldToStartTemplateOn(suggestedNameInfo.names, defaultType, null);
if (field != null) {
myEditor.getCaretModel().moveToOffset(field.getTextOffset());
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<String>();
nameSuggestions.add(field.getName());
nameSuggestions.addAll(Arrays.asList(suggestedNameInfo.names));
final VariableInplaceRenamer renamer = new FieldInplaceIntroducer(field);
renamer.performInplaceRename(false, nameSuggestions);
}
}
}, IntroduceFieldHandler.REFACTORING_NAME, null);
}
private PsiField createFieldToStartTemplateOn(final String[] names,
final PsiType defaultType,
final PsiElement anchor) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
return ApplicationManager.getApplication().runWriteAction(new Computable<PsiField>() {
@Override
public PsiField compute() {
PsiField field = elementFactory.createField(myFieldName != null ? myFieldName : names[0], defaultType);
field = anchor != null ? (PsiField)myParentClass.addBefore(field, anchor) : (PsiField)myParentClass.add(field);
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, myIntroduceFieldPanel.isDeclareFinal());
return field;
}
});
}
class FieldInplaceIntroducer extends AbstractInplaceIntroducer {
private RangeMarker myFieldRangeStart;
private SmartTypePointer myDefaultParameterTypePointer;
private SmartTypePointer myFieldTypePointer;
public FieldInplaceIntroducer(PsiVariable psiVariable) {
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
myEditor, psiVariable, false,
myTypeSelectorManager.getTypesForAll().length > 1,
myInitializerExpression != null ? myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange()) : null, InplaceIntroduceFieldPopup.this.getOccurrenceMarkers());
myDefaultParameterTypePointer =
SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(myTypeSelectorManager.getDefaultType());
myFieldRangeStart = myEditor.getDocument().createRangeMarker(psiVariable.getTextRange());
}
@Override
protected boolean isReplaceAllOccurrences() {
return myIntroduceFieldPanel.isReplaceAllOccurrences();
}
@Override
protected PsiExpression getExpr() {
return myInitializerExpression;
}
@Override
protected PsiExpression[] getOccurrences() {
return myOccurrences;
}
@Override
protected List<RangeMarker> getOccurrenceMarkers() {
return InplaceIntroduceFieldPopup.this.getOccurrenceMarkers();
}
@Override
public RangeMarker getExprMarker() {
return myExprMarker;
}
@Override
protected void saveSettings(PsiVariable psiVariable) {
TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), myDefaultParameterTypePointer.getType());
JavaRefactoringSettings.getInstance().INTRODUCE_FIELD_VISIBILITY = myIntroduceFieldPanel.getFieldVisibility();
}
@Override
protected PsiElement checkLocalScope() {
return myParentClass;
}
@Override
protected JComponent getComponent() {
if (!myInitListeners) {
myInitListeners = true;
myIntroduceFieldPanel.addVisibilityListener(new VisibilityListener());
final FinalListener finalListener = new FinalListener(myProject);
myIntroduceFieldPanel.addFinalListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
finalListener.perform(myIntroduceFieldPanel.isDeclareFinal());
}
});
}
return myWholePanel;
}
@Override
protected PsiVariable getVariable() {
PsiElement element = myParentClass.getContainingFile().findElementAt(myFieldRangeStart.getStartOffset());
if (element instanceof PsiWhiteSpace) {
element = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class);
}
return PsiTreeUtil.getParentOfType(element, PsiField.class, false);
}
@Override
protected void moveOffsetAfter(boolean success) {
if (success) {
final BaseExpressionToFieldHandler.Settings settings =
new BaseExpressionToFieldHandler.Settings(myFieldName, myIntroduceFieldPanel.isReplaceAllOccurrences(), myStatic,
myIntroduceFieldPanel.isDeclareFinal(),
myIntroduceFieldPanel.getInitializerPlace(),
myIntroduceFieldPanel.getFieldVisibility(), myLocalVariable,
myFieldTypePointer.getType(),
myIntroduceFieldPanel.isDeleteVariable(),
myParentClass, false, false);
if (myLocalVariable != null) {
final LocalToFieldHandler.IntroduceFieldRunnable fieldRunnable =
new LocalToFieldHandler.IntroduceFieldRunnable(false, myLocalVariable, myParentClass, settings, myStatic, myOccurrences);
fieldRunnable.run();
}
else {
final BaseExpressionToFieldHandler.ConvertToFieldRunnable convertToFieldRunnable =
new BaseExpressionToFieldHandler.ConvertToFieldRunnable(myInitializerExpression, settings, settings.getForcedType(),
myOccurrences, myOccurenceManager,
myAnchorElementIfAll, myAnchorElement, myEditor,
myParentClass);
convertToFieldRunnable.run();
}
}
super.moveOffsetAfter(success);
}
@Override
public void finish() {
super.finish();
final PsiField psiField = (PsiField)getVariable();
LOG.assertTrue(psiField != null);
myFieldTypePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(psiField.getType());
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
myFieldName = psiField.getName();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final PsiFile containingFile = myParentClass.getContainingFile();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
myInitializerExpression = restoreExpression(containingFile, psiField, elementFactory, getExprMarker(), myExprText);
if (myInitializerExpression != null) {
myExprMarker = myEditor.getDocument().createRangeMarker(myInitializerExpression.getTextRange());
}
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
for (int i = 0, occurrenceMarkersSize = occurrenceMarkers.size(); i < occurrenceMarkersSize; i++) {
RangeMarker marker = occurrenceMarkers.get(i);
if (getExprMarker() != null && marker.getStartOffset() == getExprMarker().getStartOffset()) {
myOccurrences[i] = myInitializerExpression;
continue;
}
final PsiExpression psiExpression = restoreExpression(containingFile, psiField, elementFactory, marker, myExprText);
if (psiExpression != null) {
myOccurrences[i] = psiExpression;
}
}
myOccurrenceMarkers = null;
if (psiField.isValid()) {
psiField.delete();
}
}
});
}
private class VisibilityListener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
new WriteCommandAction(myProject) {
@Override
protected void run(Result result) throws Throwable {
final PsiVariable variable = getVariable();
LOG.assertTrue(variable != null);
final PsiModifierList modifierList = variable.getModifierList();
LOG.assertTrue(modifierList != null);
int textOffset = modifierList.getTextOffset();
final Document document = myEditor.getDocument();
String visibility = myIntroduceFieldPanel.getFieldVisibility();
if (visibility == PsiModifier.PACKAGE_LOCAL) {
visibility = "";
}
final String modifierListText = modifierList.getText();
int length = PsiModifier.PUBLIC.length();
int idx = modifierListText.indexOf(PsiModifier.PUBLIC);
if (idx == -1) {
idx = modifierListText.indexOf(PsiModifier.PROTECTED);
length = PsiModifier.PROTECTED.length();
}
if (idx == -1) {
idx = modifierListText.indexOf(PsiModifier.PRIVATE);
length = PsiModifier.PRIVATE.length();
}
final int startOffset = textOffset + Math.max(idx, 0);
final int endOffset = textOffset + (idx > -1 ? length : 0);
document.replaceString(startOffset, endOffset, visibility + (startOffset == endOffset ? " " : ""));
}
}.execute();
}
}
}
}
@@ -0,0 +1,394 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.refactoring.introduceField;
import com.intellij.codeInsight.TestUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.JavaVisibilityPanel;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.StateRestoringCheckBox;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* User: anna
* Date: 3/16/11
*/
public class IntroduceFieldCentralPanel {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceField.IntroduceFieldDialog");
private static boolean ourLastCbFinalState = false;
private static BaseExpressionToFieldHandler.InitializationPlace ourLastInitializerPlace;
private final PsiClass myParentClass;
private final PsiExpression myInitializerExpression;
private final PsiLocalVariable myLocalVariable;
private final boolean myIsCurrentMethodConstructor;
private final boolean myIsInvokedOnDeclaration;
private final boolean myWillBeDeclaredStatic;
private final int myOccurrencesCount;
private final boolean myAllowInitInMethod;
private final boolean myAllowInitInMethodIfAll;
private final TypeSelectorManager myTypeSelectorManager;
private JCheckBox myCbReplaceAll;
private StateRestoringCheckBox myCbDeleteVariable;
private StateRestoringCheckBox myCbFinal;
private JRadioButton myRbInConstructor;
private JRadioButton myRbInCurrentMethod;
private JRadioButton myRbInFieldDeclaration;
private JRadioButton myRbInSetUp;
private JavaVisibilityPanel myVisibilityPanel;
public IntroduceFieldCentralPanel(PsiClass parentClass,
PsiExpression initializerExpression,
PsiLocalVariable localVariable,
boolean isCurrentMethodConstructor, boolean isInvokedOnDeclaration, boolean willBeDeclaredStatic,
int occurrencesCount, boolean allowInitInMethod, boolean allowInitInMethodIfAll,
TypeSelectorManager typeSelectorManager) {
myParentClass = parentClass;
myInitializerExpression = initializerExpression;
myLocalVariable = localVariable;
myIsCurrentMethodConstructor = isCurrentMethodConstructor;
myIsInvokedOnDeclaration = isInvokedOnDeclaration;
myWillBeDeclaredStatic = willBeDeclaredStatic;
myOccurrencesCount = occurrencesCount;
myAllowInitInMethod = allowInitInMethod;
myAllowInitInMethodIfAll = allowInitInMethodIfAll;
myTypeSelectorManager = typeSelectorManager;
}
void initializeControls(PsiExpression initializerExpression) {
if (initializerExpression != null) {
setEnabledInitializationPlaces(initializerExpression, initializerExpression);
if (!myAllowInitInMethod) {
myRbInCurrentMethod.setEnabled(false);
}
} else {
myRbInConstructor.setEnabled(false);
myRbInCurrentMethod.setEnabled(false);
myRbInFieldDeclaration.setEnabled(false);
if (myRbInSetUp != null) myRbInSetUp.setEnabled(false);
}
final PsiMethod setUpMethod = TestUtil.findSetUpMethod(myParentClass);
if (myInitializerExpression != null && PsiTreeUtil.isAncestor(setUpMethod, myInitializerExpression, false) && myRbInSetUp.isEnabled() ||
ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD && TestUtil.isTestClass(myParentClass) && myRbInSetUp.isEnabled()) {
myRbInSetUp.setSelected(true);
}
else if (ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR) {
if (myRbInConstructor.isEnabled()) {
myRbInConstructor.setSelected(true);
} else {
selectInCurrentMethod();
}
} else if (ourLastInitializerPlace == BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION) {
if (myRbInFieldDeclaration.isEnabled()) {
myRbInFieldDeclaration.setSelected(true);
} else {
selectInCurrentMethod();
}
} else {
selectInCurrentMethod();
}
String ourLastVisibility = JavaRefactoringSettings.getInstance().INTRODUCE_FIELD_VISIBILITY;
myVisibilityPanel.setVisibility(ourLastVisibility);
myCbFinal.setSelected(myCbFinal.isEnabled() && ourLastCbFinalState);
}
private void selectInCurrentMethod() {
if (myRbInCurrentMethod.isEnabled()) {
myRbInCurrentMethod.setSelected(true);
}
else if (myRbInFieldDeclaration.isEnabled()) {
myRbInFieldDeclaration.setSelected(true);
}
else {
myRbInCurrentMethod.setSelected(true);
}
}
public BaseExpressionToFieldHandler.InitializationPlace getInitializerPlace() {
if (myRbInConstructor.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_CONSTRUCTOR;
}
if (myRbInCurrentMethod.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_CURRENT_METHOD;
}
if (myRbInFieldDeclaration.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION;
}
if (myRbInSetUp != null && myRbInSetUp.isSelected()) {
return BaseExpressionToFieldHandler.InitializationPlace.IN_SETUP_METHOD;
}
LOG.assertTrue(false);
return BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION;
}
public String getFieldVisibility() {
return myVisibilityPanel.getVisibility();
}
public boolean isReplaceAllOccurrences() {
if (myIsInvokedOnDeclaration) return true;
if (myOccurrencesCount <= 1) return false;
return myCbReplaceAll.isSelected();
}
public boolean isDeleteVariable() {
if (myIsInvokedOnDeclaration) return true;
if (myCbDeleteVariable == null) return false;
return myCbDeleteVariable.isSelected();
}
public boolean isDeclareFinal() {
return myCbFinal.isSelected();
}
protected JComponent createCenterPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbConstraints = new GridBagConstraints();
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
gbConstraints.weightx = 1;
gbConstraints.weighty = 0;
gbConstraints.gridwidth = 1;
gbConstraints.gridx = 0;
gbConstraints.gridy = 0;
final Insets standardInsets = new Insets(0, 0, 0, 0);
gbConstraints.insets = standardInsets;
panel.add(createInitializerPlacePanel(), gbConstraints);
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (myCbReplaceAll != null && myAllowInitInMethod) {
myRbInCurrentMethod.setEnabled(myAllowInitInMethodIfAll || !myCbReplaceAll.isSelected());
if (!myRbInCurrentMethod.isEnabled() && myRbInCurrentMethod.isSelected()) {
myRbInCurrentMethod.setSelected(false);
myRbInFieldDeclaration.setSelected(true);
}
}
updateTypeSelector();
}
};
ItemListener finalUpdater = new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateCbFinal();
}
};
myRbInConstructor.addItemListener(itemListener);
myRbInCurrentMethod.addItemListener(itemListener);
myRbInFieldDeclaration.addItemListener(itemListener);
myRbInConstructor.addItemListener(finalUpdater);
myRbInCurrentMethod.addItemListener(finalUpdater);
myRbInFieldDeclaration.addItemListener(finalUpdater);
if (myRbInSetUp != null) myRbInSetUp.addItemListener(finalUpdater);
if (myOccurrencesCount > 1) {
myCbReplaceAll = new NonFocusableCheckBox();
myCbReplaceAll.setText(RefactoringBundle.message("replace.all.occurrences.of.expression.0.occurrences", myOccurrencesCount));
gbConstraints.gridy++;
panel.add(myCbReplaceAll, gbConstraints);
myCbReplaceAll.addItemListener(itemListener);
if (myIsInvokedOnDeclaration) {
myCbReplaceAll.setEnabled(false);
myCbReplaceAll.setSelected(true);
}
}
if (myLocalVariable != null) {
gbConstraints.gridy++;
if (myCbReplaceAll != null) {
gbConstraints.insets = new Insets(0, 8, 0, 0);
}
myCbDeleteVariable = new StateRestoringCheckBox();
myCbDeleteVariable.setText(RefactoringBundle.message("delete.variable.declaration"));
panel.add(myCbDeleteVariable, gbConstraints);
if (myIsInvokedOnDeclaration) {
myCbDeleteVariable.setEnabled(false);
myCbDeleteVariable.setSelected(true);
} else if (myCbReplaceAll != null) {
updateCbDeleteVariable();
myCbReplaceAll.addItemListener(
new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateCbDeleteVariable();
}
}
);
}
gbConstraints.insets = standardInsets;
}
myCbFinal.addItemListener(itemListener);
// myCbStatic.addItemListener(itemListener);
// myCbStatic.addItemListener(finalUpdater);
// myCbStatic.addItemListener(
// new ItemListener() {
// public void itemStateChanged(ItemEvent e) {
// updateNameList();
// }
// }
// );
updateTypeSelector();
return panel;
}
private void updateTypeSelector() {
if (myCbReplaceAll != null) {
myTypeSelectorManager.setAllOccurences(myCbReplaceAll.isSelected());
} else {
myTypeSelectorManager.setAllOccurences(false);
}
}
private void updateCbDeleteVariable() {
if (!myCbReplaceAll.isSelected()) {
myCbDeleteVariable.makeUnselectable(false);
} else {
myCbDeleteVariable.makeSelectable();
}
}
private JComponent createInitializerPlacePanel() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JPanel initializationPanel = new JPanel();
initializationPanel.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("initialize.in.border.title")));
initializationPanel.setLayout(new BoxLayout(initializationPanel, BoxLayout.Y_AXIS));
myRbInCurrentMethod = new JRadioButton();
myRbInCurrentMethod.setFocusable(false);
myRbInCurrentMethod.setText(RefactoringBundle.message("current.method.radio"));
myRbInCurrentMethod.setEnabled(myAllowInitInMethod);
myRbInFieldDeclaration = new JRadioButton();
myRbInFieldDeclaration.setFocusable(false);
myRbInFieldDeclaration.setText(RefactoringBundle.message("field.declaration.radio"));
myRbInConstructor = new JRadioButton();
myRbInConstructor.setFocusable(false);
myRbInConstructor.setText(RefactoringBundle.message("class.constructors.radio"));
myVisibilityPanel = new JavaVisibilityPanel(false, false);
myCbFinal = new StateRestoringCheckBox();
myCbFinal.setFocusable(false);
myCbFinal.setText(RefactoringBundle.message("declare.final"));
initializationPanel.add(myRbInCurrentMethod);
initializationPanel.add(myRbInFieldDeclaration);
initializationPanel.add(myRbInConstructor);
if (TestUtil.isTestClass(myParentClass)) {
myRbInSetUp = new JRadioButton();
myRbInSetUp.setFocusable(false);
myRbInSetUp.setText(RefactoringBundle.message("setup.method.radio"));
initializationPanel.add(myRbInSetUp);
}
ButtonGroup bg = new ButtonGroup();
bg.add(myRbInCurrentMethod);
bg.add(myRbInFieldDeclaration);
bg.add(myRbInConstructor);
if (myRbInSetUp != null) bg.add(myRbInSetUp);
// modifiersPanel.add(myCbFinal);
// modifiersPanel.add(myCbStatic);
JPanel groupPanel = new JPanel(new GridLayout(1, 2));
groupPanel.add(initializationPanel);
groupPanel.add(myVisibilityPanel);
mainPanel.add(groupPanel, BorderLayout.CENTER);
mainPanel.add(myCbFinal, BorderLayout.SOUTH);
return mainPanel;
}
private void updateCbFinal() {
boolean allowFinal = myRbInFieldDeclaration.isSelected() || (myRbInConstructor.isSelected() && !myWillBeDeclaredStatic);
if (myRbInCurrentMethod.isSelected() && myIsCurrentMethodConstructor) {
final PsiMethod[] constructors = myParentClass.getConstructors();
allowFinal = constructors.length <= 1;
}
if (!allowFinal) {
myCbFinal.makeUnselectable(false);
} else {
myCbFinal.makeSelectable();
}
}
private boolean setEnabledInitializationPlaces(PsiElement initializerPart, PsiElement initializer) {
if (initializerPart instanceof PsiReferenceExpression) {
PsiReferenceExpression refExpr = (PsiReferenceExpression) initializerPart;
if (refExpr.getQualifierExpression() == null) {
PsiElement refElement = refExpr.resolve();
if (refElement == null ||
(refElement instanceof PsiLocalVariable || refElement instanceof PsiParameter) &&
!PsiTreeUtil.isAncestor(initializer, refElement, true)) {
myRbInFieldDeclaration.setEnabled(false);
myRbInConstructor.setEnabled(false);
if (myRbInSetUp != null) myRbInSetUp.setEnabled(false);
myCbFinal.setEnabled(false);
return false;
}
}
}
PsiElement[] children = initializerPart.getChildren();
for (PsiElement child : children) {
if (!setEnabledInitializationPlaces(child, initializer)) return false;
}
return true;
}
public void addOccurrenceListener(ItemListener itemListener) {
if (myCbReplaceAll != null) {
myCbReplaceAll.addItemListener(itemListener);
}
}
public void addVisibilityListener(ChangeListener changeListener) {
myVisibilityPanel.addListener(changeListener);
}
public void addFinalListener(ItemListener itemListener) {
myCbFinal.addItemListener(itemListener);
}
}
@@ -33,30 +33,28 @@ import com.intellij.refactoring.util.RefactoringMessageUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
class IntroduceFieldDialog extends DialogWrapper {
static BaseExpressionToFieldHandler.InitializationPlace ourLastInitializerPlace;
static boolean ourLastCbFinalState = false;
private final Project myProject;
private final PsiClass myParentClass;
private final PsiExpression myInitializerExpression;
private final PsiLocalVariable myLocalVariable;
private final boolean myIsCurrentMethodConstructor;
private final boolean myIsInvokedOnDeclaration;
private final boolean myWillBeDeclaredStatic;
private final TypeSelectorManager myTypeSelectorManager;
private NameSuggestionsField myNameField;
private IntroduceFieldCentralPanel myCentralPanel;
private TypeSelector myTypeSelector;
private NameSuggestionsManager myNameSuggestionsManager;
private static final String REFACTORING_NAME = RefactoringBundle.message("introduce.field.title");
private final InitializerPlaceChooser myInitializerPlaceChooser;
private JavaVisibilityPanel myVisibilityPanel;
private IntroduceFieldPanel myIntroduceFieldPanel;
public IntroduceFieldDialog(Project project,
PsiClass parentClass,
@@ -69,10 +67,11 @@ class IntroduceFieldDialog extends DialogWrapper {
myProject = project;
myParentClass = parentClass;
myInitializerExpression = initializerExpression;
myInitializerPlaceChooser = new InitializerPlaceChooser(parentClass, initializerExpression, allowInitInMethod, allowInitInMethodIfAll);
myIntroduceFieldPanel = new IntroduceFieldPanel(isInvokedOnDeclaration, occurrencesCount, localVariable);
myCentralPanel =
new IntroduceFieldCentralPanel(parentClass, initializerExpression, localVariable, isCurrentMethodConstructor, isInvokedOnDeclaration,
willBeDeclaredStatic, occurrencesCount, allowInitInMethod, allowInitInMethodIfAll,
typeSelectorManager);
myLocalVariable = localVariable;
myIsCurrentMethodConstructor = isCurrentMethodConstructor;
myIsInvokedOnDeclaration = isInvokedOnDeclaration;
myWillBeDeclaredStatic = willBeDeclaredStatic;
@@ -81,44 +80,36 @@ class IntroduceFieldDialog extends DialogWrapper {
setTitle(REFACTORING_NAME);
init();
initializeControls(initializerExpression);
myCentralPanel.initializeControls(initializerExpression);
updateButtons();
}
private void initializeControls(PsiExpression initializerExpression) {
myInitializerPlaceChooser.initializeControls(initializerExpression);
myIntroduceFieldPanel.initializeControls(initializerExpression);
String ourLastVisibility = JavaRefactoringSettings.getInstance().INTRODUCE_FIELD_VISIBILITY;
myVisibilityPanel.setVisibility(ourLastVisibility);
}
public String getEnteredName() {
return myNameField.getEnteredName();
}
public BaseExpressionToFieldHandler.InitializationPlace getInitializerPlace() {
return myInitializerPlaceChooser.getInitializerPlace();
return myCentralPanel.getInitializerPlace();
}
@Modifier
public String getFieldVisibility() {
return myVisibilityPanel.getVisibility();
return myCentralPanel.getFieldVisibility();
}
public boolean isReplaceAllOccurrences() {
return myIntroduceFieldPanel.isReplaceAllOccurrences();
return myCentralPanel.isReplaceAllOccurrences();
}
public boolean isDeleteVariable() {
return myIntroduceFieldPanel.isDeleteVariable();
return myCentralPanel.isDeleteVariable();
}
public boolean isDeclareFinal() {
return myIntroduceFieldPanel.isDeclareFinal();
return myCentralPanel.isDeclareFinal();
}
public PsiType getFieldType() {
@@ -179,7 +170,8 @@ class IntroduceFieldDialog extends DialogWrapper {
});
namePrompt.setLabelFor(myNameField.getFocusableComponent());
myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, createGenerator());
myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField,
createGenerator(myWillBeDeclaredStatic, myLocalVariable, myInitializerExpression, myIsInvokedOnDeclaration));
myNameSuggestionsManager.setLabelsFor(type, namePrompt);
return panel;
@@ -196,66 +188,27 @@ class IntroduceFieldDialog extends DialogWrapper {
}
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints gbConstraints = new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0);
final JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JPanel groupPanel = new JPanel(new GridLayout(1, 2));
final JComponent initializerPlacePanel = myInitializerPlaceChooser.createInitializerPlacePanel();
myInitializerPlaceChooser.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
myIntroduceFieldPanel.updateTypeSelector(myTypeSelectorManager);
myIntroduceFieldPanel.updateCbFinal(myInitializerPlaceChooser.allowFinal(myWillBeDeclaredStatic, myIsCurrentMethodConstructor));
}
});
groupPanel.add(initializerPlacePanel);
myVisibilityPanel = new JavaVisibilityPanel(false, false);
groupPanel.add(myVisibilityPanel);
mainPanel.add(groupPanel, BorderLayout.CENTER);
final ItemListener itemListener = new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (myIntroduceFieldPanel.hasOccurrences()) {
myInitializerPlaceChooser.updateInitializerPlace(myIntroduceFieldPanel.isReplaceAllOccurrences());
}
myIntroduceFieldPanel.updateTypeSelector(myTypeSelectorManager);
myNameField.requestFocusInWindow();
}
};
panel.add(mainPanel, gbConstraints);
myIntroduceFieldPanel.appendFinalCb(panel, gbConstraints, itemListener);
myIntroduceFieldPanel.appendOccurrencesCb(panel, gbConstraints, itemListener);
myIntroduceFieldPanel.appendDeleteVariableDeclarationCb(panel, gbConstraints);
myIntroduceFieldPanel.updateTypeSelector(myTypeSelectorManager);
return panel;
return myCentralPanel.createCenterPanel();
}
private NameSuggestionsGenerator createGenerator() {
static NameSuggestionsGenerator createGenerator(final boolean willBeDeclaredStatic,
final PsiLocalVariable localVariable,
final PsiExpression initializerExpression,
final boolean isInvokedOnDeclaration) {
return new NameSuggestionsGenerator() {
private final JavaCodeStyleManager myCodeStyleManager = JavaCodeStyleManager.getInstance(myProject);
private final JavaCodeStyleManager myCodeStyleManager = JavaCodeStyleManager.getInstance(localVariable != null ? localVariable.getProject()
: initializerExpression.getProject());
public SuggestedNameInfo getSuggestedNameInfo(PsiType type) {
VariableKind variableKind = myWillBeDeclaredStatic ? VariableKind.STATIC_FIELD : VariableKind.FIELD;
VariableKind variableKind = willBeDeclaredStatic ? VariableKind.STATIC_FIELD : VariableKind.FIELD;
String propertyName = null;
if (myIsInvokedOnDeclaration) {
propertyName = myCodeStyleManager.variableNameToPropertyName(myLocalVariable.getName(),
VariableKind.LOCAL_VARIABLE
);
if (isInvokedOnDeclaration) {
propertyName = myCodeStyleManager.variableNameToPropertyName(localVariable.getName(), VariableKind.LOCAL_VARIABLE);
}
final SuggestedNameInfo nameInfo = myCodeStyleManager.suggestVariableName(variableKind, propertyName, myInitializerExpression, type);
final SuggestedNameInfo nameInfo = myCodeStyleManager.suggestVariableName(variableKind, propertyName, initializerExpression, type);
final String[] strings = JavaCompletionUtil.completeVariableNameForRefactoring(myCodeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo);
return new SuggestedNameInfo.Delegate(strings, nameInfo);
return new SuggestedNameInfo.Delegate(strings, nameInfo);
}
};
}
@@ -293,8 +246,8 @@ class IntroduceFieldDialog extends DialogWrapper {
}
}
IntroduceFieldPanel.ourLastCbFinalState = myIntroduceFieldPanel.isFinal();
InitializerPlaceChooser.ourLastInitializerPlace = myInitializerPlaceChooser.getInitializerPlace();
ourLastCbFinalState = myCentralPanel.isDeclareFinal();
ourLastInitializerPlace = myCentralPanel.getInitializerPlace();
JavaRefactoringSettings.getInstance().INTRODUCE_FIELD_VISIBILITY = getFieldVisibility();
myNameSuggestionsManager.nameSelected();
@@ -16,6 +16,8 @@
package com.intellij.refactoring.introduceField;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.WindowManager;
@@ -96,12 +98,21 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
final boolean currentMethodConstructor = containingMethod != null && containingMethod.isConstructor();
final boolean allowInitInMethod = (!currentMethodConstructor || !isInSuperOrThis) && (anchorElement instanceof PsiLocalVariable || anchorElement instanceof PsiStatement);
final boolean allowInitInMethodIfAll = (!currentMethodConstructor || !isInSuperOrThis) && anchorElementIfAll instanceof PsiStatement;
final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences);
if (editor != null && editor.getSettings().isVariableInplaceRenameEnabled() && ApplicationManagerEx.getApplicationEx().isInternal()) {
new InplaceIntroduceFieldPopup(localVariable, parentClass, declareStatic, currentMethodConstructor, occurences, expr, typeSelectorManager, editor,
allowInitInMethod, allowInitInMethodIfAll, anchorElement, anchorElementIfAll, createOccurenceManager(expr, parentClass))
.startTemplate();
return null;
}
IntroduceFieldDialog dialog = new IntroduceFieldDialog(
project, parentClass, expr, localVariable,
currentMethodConstructor,
localVariable != null, declareStatic, occurencesNumber,
allowInitInMethod, allowInitInMethodIfAll,
new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences)
typeSelectorManager
);
dialog.show();
@@ -1,152 +0,0 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.refactoring.introduceField;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.StateRestoringCheckBox;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* User: anna
* Date: 3/15/11
*/
public class IntroduceFieldPanel {
static boolean ourLastCbFinalState = false;
private JCheckBox myCbReplaceAll;
private StateRestoringCheckBox myCbDeleteVariable;
private StateRestoringCheckBox myCbFinal;
private boolean myIsInvokedOnDeclaration;
private int myOccurrencesCount;
private PsiLocalVariable myLocalVariable;
public IntroduceFieldPanel(boolean isInvokedOnDeclaration, int occurrencesCount, PsiLocalVariable localVariable) {
myIsInvokedOnDeclaration = isInvokedOnDeclaration;
myOccurrencesCount = occurrencesCount;
myLocalVariable = localVariable;
}
public void initializeControls(PsiExpression initializerExpression) {
if (initializerExpression != null && !InitializerPlaceChooser.setEnabledInitializationPlaces(initializerExpression, initializerExpression)) {
myCbFinal.setEnabled(false);
}
myCbFinal.setSelected(myCbFinal.isEnabled() && ourLastCbFinalState);
}
public boolean isReplaceAllOccurrences() {
if (myIsInvokedOnDeclaration) return true;
if (myOccurrencesCount <= 1) return false;
return myCbReplaceAll.isSelected();
}
public boolean isDeclareFinal() {
return myCbFinal.isSelected();
}
public boolean isDeleteVariable() {
if (myIsInvokedOnDeclaration) return true;
if (myCbDeleteVariable == null) return false;
return myCbDeleteVariable.isSelected();
}
void appendFinalCb(JPanel mainPanel, GridBagConstraints gbConstraints, ItemListener itemListener) {
myCbFinal = new StateRestoringCheckBox();
myCbFinal.setText(RefactoringBundle.message("declare.final"));
myCbFinal.addItemListener(itemListener);
gbConstraints.gridy++;
mainPanel.add(myCbFinal, gbConstraints);
}
void appendOccurrencesCb(JPanel panel, GridBagConstraints gbConstraints, ItemListener itemListener) {
if (myOccurrencesCount > 1) {
myCbReplaceAll = new NonFocusableCheckBox();
myCbReplaceAll.setText(RefactoringBundle.message("replace.all.occurrences.of.expression.0.occurrences", myOccurrencesCount));
gbConstraints.gridy++;
panel.add(myCbReplaceAll, gbConstraints);
myCbReplaceAll.addItemListener(itemListener);
if (myIsInvokedOnDeclaration) {
myCbReplaceAll.setEnabled(false);
myCbReplaceAll.setSelected(true);
}
}
}
void appendDeleteVariableDeclarationCb(JPanel panel, GridBagConstraints gbConstraints) {
if (myLocalVariable != null) {
gbConstraints.gridy++;
if (myCbReplaceAll != null) {
gbConstraints.insets = new Insets(0, 8, 0, 0);
}
myCbDeleteVariable = new StateRestoringCheckBox();
myCbDeleteVariable.setText(RefactoringBundle.message("delete.variable.declaration"));
panel.add(myCbDeleteVariable, gbConstraints);
if (myIsInvokedOnDeclaration) {
myCbDeleteVariable.setEnabled(false);
myCbDeleteVariable.setSelected(true);
} else if (myCbReplaceAll != null) {
updateCbDeleteVariable();
myCbReplaceAll.addItemListener(
new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateCbDeleteVariable();
}
}
);
}
gbConstraints.insets = new Insets(0, 0, 0, 0);
}
}
private void updateCbDeleteVariable() {
if (!myCbReplaceAll.isSelected()) {
myCbDeleteVariable.makeUnselectable(false);
} else {
myCbDeleteVariable.makeSelectable();
}
}
void updateCbFinal(boolean allowFinal) {
if (!allowFinal) {
myCbFinal.makeUnselectable(false);
} else {
myCbFinal.makeSelectable();
}
}
public boolean isFinal() {
return myCbFinal.isSelected();
}
void updateTypeSelector(TypeSelectorManager typeSelectorManager) {
if (myCbReplaceAll != null) {
typeSelectorManager.setAllOccurences(myCbReplaceAll.isSelected());
} else {
typeSelectorManager.setAllOccurences(false);
}
}
public boolean hasOccurrences() {
return myCbReplaceAll != null;
}
}
@@ -45,11 +45,9 @@ public abstract class LocalToFieldHandler {
private static final String REFACTORING_NAME = RefactoringBundle.message("convert.local.to.field.title");
private final Project myProject;
private final boolean myIsConstant;
private final PsiManager myManager;
public LocalToFieldHandler(Project project, boolean isConstant) {
myProject = project;
myManager = PsiManager.getInstance(myProject);
myIsConstant = isConstant;
}
@@ -86,9 +84,6 @@ public abstract class LocalToFieldHandler {
final BaseExpressionToFieldHandler.Settings settings = showRefactoringDialog(aClass, local, occurences, isStatic);
if (settings == null) return false;
//LocalToFieldDialog dialog = new LocalToFieldDialog(project, aClass, local, isStatic);
final String variableName = local.getName();
final String fieldName = settings.getFieldName();
final BaseExpressionToFieldHandler.InitializationPlace initializerPlace = settings.getInitializerPlace();
final PsiClass destinationClass = settings.getDestinationClass();
boolean rebindNeeded = false;
if (destinationClass != null) {
@@ -98,76 +93,8 @@ public abstract class LocalToFieldHandler {
final PsiClass aaClass = aClass;
final boolean rebindNeeded1 = rebindNeeded;
final Runnable runnable = new Runnable() {
public void run() {
try {
final boolean rebindNeeded2 = !variableName.equals(fieldName) || rebindNeeded1;
final PsiReference[] refs;
if (rebindNeeded2) {
refs = ReferencesSearch.search(local, GlobalSearchScope.projectScope(myProject), false).toArray(new PsiReference[0]);
}
else {
refs = null;
}
final PsiMethod enclosingConstructor = BaseExpressionToFieldHandler.getEnclosingConstructor(aaClass, local);
PsiField field = settings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(aaClass, local, fieldName)
: createField(local, settings.getForcedType(), fieldName, initializerPlace == IN_FIELD_DECLARATION);
field = (PsiField)aaClass.add(field);
BaseExpressionToFieldHandler.setModifiers(field, settings, isStatic);
if (!settings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(occurences, field, settings.getFieldVisibility());
}
local.normalizeDeclaration();
PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)local.getParent();
final BaseExpressionToFieldHandler.InitializationPlace finalInitializerPlace;
if (local.getInitializer() == null) {
finalInitializerPlace = IN_FIELD_DECLARATION;
}
else {
finalInitializerPlace = initializerPlace;
}
final PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
switch (finalInitializerPlace) {
case IN_FIELD_DECLARATION:
declarationStatement.delete();
break;
case IN_CURRENT_METHOD:
PsiStatement statement = createAssignment(local, fieldName, factory);
declarationStatement.replace(statement);
break;
case IN_CONSTRUCTOR:
addInitializationToConstructors(local, field, enclosingConstructor, factory);
break;
case IN_SETUP_METHOD:
addInitializationToSetUp(local, field, factory);
}
if (enclosingConstructor != null && initializerPlace == IN_CONSTRUCTOR) {
PsiStatement statement = createAssignment(local, fieldName, factory);
declarationStatement.replace(statement);
}
if (rebindNeeded2) {
for (final PsiReference reference : refs) {
if (reference != null) {
//expr = RefactoringUtil.outermostParenthesizedExpression(expr);
RefactoringUtil.replaceOccurenceWithFieldRef((PsiExpression)reference, field, aaClass);
//replaceOccurenceWithFieldRef((PsiExpression)reference, field, aaClass);
}
}
//RefactoringUtil.renameVariableReferences(local, pPrefix + fieldName, GlobalSearchScope.projectScope(myProject));
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
};
final Runnable runnable =
new IntroduceFieldRunnable(rebindNeeded1, local, aaClass, settings, isStatic, occurences);
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(runnable);
@@ -176,7 +103,7 @@ public abstract class LocalToFieldHandler {
return true;
}
private PsiField createField(PsiLocalVariable local, PsiType forcedType, String fieldName, boolean includeInitializer) {
private static PsiField createField(PsiLocalVariable local, PsiType forcedType, String fieldName, boolean includeInitializer) {
@NonNls StringBuilder pattern = new StringBuilder();
pattern.append("private int ");
pattern.append(fieldName);
@@ -187,10 +114,11 @@ public abstract class LocalToFieldHandler {
pattern.append("=0");
}
pattern.append(";");
PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
final Project project = local.getProject();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
try {
PsiField field = factory.createFieldFromText(pattern.toString(), null);
field = (PsiField)CodeStyleManager.getInstance(myProject).reformat(field);
field = (PsiField)CodeStyleManager.getInstance(project).reformat(field);
field.getTypeElement().replace(factory.createTypeElement(forcedType));
if (includeInitializer) {
@@ -207,11 +135,11 @@ public abstract class LocalToFieldHandler {
}
}
private PsiStatement createAssignment(PsiLocalVariable local, String fieldname, PsiElementFactory factory) {
private static PsiStatement createAssignment(PsiLocalVariable local, String fieldname, PsiElementFactory factory) {
try {
String pattern = fieldname + "=0;";
PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(pattern, null);
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(myProject).reformat(statement);
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(local.getProject()).reformat(statement);
PsiAssignmentExpression expr = (PsiAssignmentExpression)statement.getExpression();
final PsiExpression initializer = RefactoringUtil.convertInitializerToNormalExpression(local.getInitializer(), local.getType());
@@ -225,7 +153,7 @@ public abstract class LocalToFieldHandler {
}
}
private void addInitializationToSetUp(final PsiLocalVariable local, final PsiField field, final PsiElementFactory factory)
private static PsiStatement addInitializationToSetUp(final PsiLocalVariable local, final PsiField field, final PsiElementFactory factory)
throws IncorrectOperationException {
PsiMethod inClass = TestUtil.findOrCreateSetUpMethod(field.getContainingClass());
assert inClass != null;
@@ -233,15 +161,16 @@ public abstract class LocalToFieldHandler {
final PsiCodeBlock body = inClass.getBody();
assert body != null;
if (PsiTreeUtil.isAncestor(body, local, false)) {
body.addBefore(assignment, PsiTreeUtil.getParentOfType(local, PsiStatement.class));
assignment = (PsiStatement)body.addBefore(assignment, PsiTreeUtil.getParentOfType(local, PsiStatement.class));
} else {
body.add(assignment);
assignment = (PsiStatement)body.add(assignment);
}
local.delete();
return assignment;
}
private void addInitializationToConstructors(PsiLocalVariable local, PsiField field, PsiMethod enclosingConstructor,
PsiElementFactory factory) throws IncorrectOperationException {
private static PsiStatement addInitializationToConstructors(PsiLocalVariable local, PsiField field, PsiMethod enclosingConstructor,
PsiElementFactory factory) throws IncorrectOperationException {
PsiClass aClass = field.getContainingClass();
PsiMethod[] constructors = aClass.getConstructors();
PsiStatement assignment = createAssignment(local, field.getName(), factory);
@@ -263,15 +192,125 @@ public abstract class LocalToFieldHandler {
}
}
}
body.add(assignment);
assignment = (PsiStatement)body.add(assignment);
added = true;
}
if (!added && enclosingConstructor == null) {
PsiMethod constructor = factory.createConstructor();
constructor.getBody().add(assignment);
aClass.add(constructor);
PsiMethod constructor = (PsiMethod)aClass.add(factory.createConstructor());
assignment = (PsiStatement)constructor.getBody().add(assignment);
}
if (enclosingConstructor == null) local.delete();
return assignment;
}
static class IntroduceFieldRunnable implements Runnable {
private final String myVariableName;
private final String myFieldName;
private final boolean myRebindNeeded;
private final PsiLocalVariable myLocal;
private final Project myProject;
private final PsiClass myDestinationClass;
private final BaseExpressionToFieldHandler.Settings mySettings;
private final BaseExpressionToFieldHandler.InitializationPlace myInitializerPlace;
private final boolean myStatic;
private final PsiExpression[] myOccurences;
private PsiField myField;
private PsiStatement myAssignmentStatement;
public IntroduceFieldRunnable(boolean rebindNeeded,
PsiLocalVariable local,
PsiClass aClass,
BaseExpressionToFieldHandler.Settings settings,
boolean isStatic,
PsiExpression[] occurrences) {
myVariableName = local.getName();
myFieldName = settings.getFieldName();
myRebindNeeded = rebindNeeded;
myLocal = local;
myProject = local.getProject();
myDestinationClass = aClass;
mySettings = settings;
myInitializerPlace = settings.getInitializerPlace();
myStatic = isStatic;
myOccurences = occurrences;
}
public void run() {
try {
final boolean rebindNeeded2 = !myVariableName.equals(myFieldName) || myRebindNeeded;
final PsiReference[] refs;
if (rebindNeeded2) {
refs = ReferencesSearch.search(myLocal, GlobalSearchScope.projectScope(myProject), false).toArray(new PsiReference[0]);
}
else {
refs = null;
}
final PsiMethod enclosingConstructor = BaseExpressionToFieldHandler.getEnclosingConstructor(myDestinationClass, myLocal);
myField = mySettings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(myDestinationClass, myLocal, myFieldName)
: createField(myLocal, mySettings.getForcedType(), myFieldName, myInitializerPlace == IN_FIELD_DECLARATION);
myField = (PsiField)myDestinationClass.add(myField);
BaseExpressionToFieldHandler.setModifiers(myField, mySettings, myStatic);
if (!mySettings.isIntroduceEnumConstant()) {
VisibilityUtil.fixVisibility(myOccurences, myField, mySettings.getFieldVisibility());
}
myLocal.normalizeDeclaration();
PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)myLocal.getParent();
final BaseExpressionToFieldHandler.InitializationPlace finalInitializerPlace;
if (myLocal.getInitializer() == null) {
finalInitializerPlace = IN_FIELD_DECLARATION;
}
else {
finalInitializerPlace = myInitializerPlace;
}
final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
switch (finalInitializerPlace) {
case IN_FIELD_DECLARATION:
declarationStatement.delete();
break;
case IN_CURRENT_METHOD:
PsiStatement statement = createAssignment(myLocal, myFieldName, factory);
myAssignmentStatement = (PsiStatement)declarationStatement.replace(statement);
break;
case IN_CONSTRUCTOR:
myAssignmentStatement = addInitializationToConstructors(myLocal, myField, enclosingConstructor, factory);
break;
case IN_SETUP_METHOD:
myAssignmentStatement = addInitializationToSetUp(myLocal, myField, factory);
}
if (enclosingConstructor != null && myInitializerPlace == IN_CONSTRUCTOR) {
PsiStatement statement = createAssignment(myLocal, myFieldName, factory);
myAssignmentStatement = (PsiStatement)declarationStatement.replace(statement);
}
if (rebindNeeded2) {
for (final PsiReference reference : refs) {
if (reference != null) {
//expr = RefactoringUtil.outermostParenthesizedExpression(expr);
RefactoringUtil.replaceOccurenceWithFieldRef((PsiExpression)reference, myField, myDestinationClass);
//replaceOccurenceWithFieldRef((PsiExpression)reference, field, aaClass);
}
}
//RefactoringUtil.renameVariableReferences(local, pPrefix + fieldName, GlobalSearchScope.projectScope(myProject));
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
public PsiField getField() {
return myField;
}
public PsiStatement getAssignmentStatement() {
return myAssignmentStatement;
}
}
}
@@ -0,0 +1,134 @@
/*
* Copyright 2000-2011 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.
*/
package com.intellij.refactoring.introduceParameter;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.introduceVariable.VariableInplaceIntroducer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* User: anna
* Date: 3/15/11
*/
public abstract class AbstractInplaceIntroducer extends VariableInplaceIntroducer {
public AbstractInplaceIntroducer(Project project,
TypeExpression expression,
Editor editor,
PsiVariable elementToRename,
boolean cantChangeFinalModifier,
boolean hasTypeSuggestion,
RangeMarker exprMarker,
List<RangeMarker> occurrenceMarkers) {
super(project, expression, editor, elementToRename, cantChangeFinalModifier, hasTypeSuggestion, exprMarker, occurrenceMarkers);
}
protected abstract boolean isReplaceAllOccurrences();
protected abstract PsiExpression getExpr();
protected abstract PsiExpression[] getOccurrences();
protected abstract List<RangeMarker> getOccurrenceMarkers();
@Override
protected void addReferenceAtCaret(Collection<PsiReference> refs) {
final PsiVariable variable = getVariable();
if (variable != null) {
for (PsiReference reference : ReferencesSearch.search(variable)) {
refs.remove(reference);
}
}
}
@Override
protected boolean appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages) {
return true;
}
@Override
protected void collectAdditionalElementsToRename(boolean processTextOccurrences, List<Pair<PsiElement, TextRange>> stringUsages) {
if (isReplaceAllOccurrences()) {
for (PsiExpression expression : getOccurrences()) {
stringUsages.add(Pair.<PsiElement, TextRange>create(expression, new TextRange(0, expression.getTextLength())));
}
}
else if (getExpr() != null) {
stringUsages.add(Pair.<PsiElement, TextRange>create(getExpr(), new TextRange(0, getExpr().getTextLength())));
}
}
@Override
protected void collectAdditionalRangesToHighlight(Map<TextRange, TextAttributes> rangesToHighlight,
Collection<Pair<PsiElement, TextRange>> stringUsages,
EditorColorsManager colorsManager) {
}
@Override
protected void addHighlights(@NotNull Map<TextRange, TextAttributes> ranges,
@NotNull Editor editor,
@NotNull Collection<RangeHighlighter> highlighters,
@NotNull HighlightManager highlightManager) {
final TextAttributes attributes =
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
final int variableNameLength = getVariable().getName().length();
if (isReplaceAllOccurrences()) {
for (RangeMarker marker : getOccurrenceMarkers()) {
final int startOffset = marker.getStartOffset();
highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null);
}
}
else if (getExpr() != null) {
final int startOffset = getExprMarker().getStartOffset();
highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null);
}
super.addHighlights(ranges, editor, highlighters, highlightManager);
}
@Nullable
protected static PsiExpression restoreExpression(PsiFile containingFile,
PsiVariable psiVariable,
PsiElementFactory elementFactory,
RangeMarker marker, String exprText) {
if (exprText == null) return null;
if (psiVariable == null || !psiVariable.isValid()) return null;
final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset());
final PsiExpression expression = PsiTreeUtil.getParentOfType(refVariableElement, PsiReferenceExpression.class);
if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() == psiVariable) {
return (PsiExpression)expression.replace(elementFactory.createExpressionFromText(exprText, psiVariable));
}
return null;
}
}
@@ -15,43 +15,28 @@
*/
package com.intellij.refactoring.introduceParameter;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.*;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.introduceVariable.VariableInplaceIntroducer;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.TitlePanel;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.usageView.UsageInfo;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -64,7 +49,6 @@ import java.util.List;
*/
class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
private Balloon myBalloon;
private final Project myProject;
private final Editor myEditor;
private final TypeSelectorManagerImpl myTypeSelectorManager;
@@ -104,7 +88,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
myMethodToSearchFor = methodToSearchFor;
myOccurrences = occurrences;
myMustBeFinal = mustBeFinal;
myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(myExpr.getTextRange()) : null;
myExprMarker = expr != null ? myEditor.getDocument().createRangeMarker(expr.getTextRange()) : null;
myExprText = myExpr != null ? myExpr.getText() : null;
myWholePanel = new JPanel(new GridBagLayout());
@@ -180,7 +164,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
return myOccurrenceMarkers;
}
private class ParameterInplaceIntroducer extends VariableInplaceIntroducer {
private class ParameterInplaceIntroducer extends AbstractInplaceIntroducer {
private SmartTypePointer myParameterTypePointer;
private SmartTypePointer myDefaultParameterTypePointer;
@@ -190,7 +174,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
public ParameterInplaceIntroducer(PsiParameter parameter) {
super(myProject, new TypeExpression(myProject, myTypeSelectorManager.getTypesForAll()),
myEditor, parameter, myMustBeFinal,
myTypeSelectorManager.getTypesForAll().length > 1, myExprMarker, getOccurrenceMarkers());
myTypeSelectorManager.getTypesForAll().length > 1, myExprMarker, InplaceIntroduceParameterPopup.this.getOccurrenceMarkers());
myDefaultParameterTypePointer = SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(parameter.getType());
}
@@ -207,64 +191,31 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
return panel;
}
@Override
protected boolean isReplaceAllOccurrences() {
return InplaceIntroduceParameterPopup.this.isReplaceAllOccurences();
}
@Override
protected PsiExpression getExpr() {
return myExpr;
}
@Override
protected PsiExpression[] getOccurrences() {
return myOccurrences;
}
@Override
protected List<RangeMarker> getOccurrenceMarkers() {
return InplaceIntroduceParameterPopup.this.getOccurrenceMarkers();
}
@Override
protected PsiVariable getVariable() {
return getParameter();
}
@Override
protected void addReferenceAtCaret(Collection<PsiReference> refs) {
final PsiVariable variable = getVariable();
if (variable != null) {
for (PsiReference reference : ReferencesSearch.search(variable)) {
refs.remove(reference);
}
}
}
@Override
protected boolean appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages) {
return true;
}
@Override
protected void collectAdditionalElementsToRename(boolean processTextOccurrences, List<Pair<PsiElement, TextRange>> stringUsages) {
if (isReplaceAllOccurences()) {
for (PsiExpression expression : myOccurrences) {
stringUsages.add(Pair.<PsiElement, TextRange>create(expression, new TextRange(0, expression.getTextLength())));
}
}
else if (myExpr != null) {
stringUsages.add(Pair.<PsiElement, TextRange>create(myExpr, new TextRange(0, myExpr.getTextLength())));
}
}
@Override
protected void collectAdditionalRangesToHighlight(Map<TextRange, TextAttributes> rangesToHighlight,
Collection<Pair<PsiElement, TextRange>> stringUsages,
EditorColorsManager colorsManager) {
}
@Override
protected void addHighlights(@NotNull Map<TextRange, TextAttributes> ranges,
@NotNull Editor editor,
@NotNull Collection<RangeHighlighter> highlighters,
@NotNull HighlightManager highlightManager) {
final TextAttributes attributes =
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
final int variableNameLength = getVariable().getName().length();
if (isReplaceAllOccurences()) {
for (RangeMarker marker : getOccurrenceMarkers()) {
final int startOffset = marker.getStartOffset();
highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null);
}
}
else if (myExpr != null) {
final int startOffset = myExprMarker.getStartOffset();
highlightManager.addOccurrenceHighlight(editor, startOffset, startOffset + variableNameLength, attributes, 0, highlighters, null);
}
super.addHighlights(ranges, editor, highlighters, highlightManager);
}
@Override
protected void saveSettings(PsiVariable psiVariable) {
@@ -336,7 +287,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
public void run() {
final PsiFile containingFile = myMethod.getContainingFile();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
myExpr = restoreExpression(containingFile, psiParameter, elementFactory, myExprMarker);
myExpr = restoreExpression(containingFile, psiParameter, elementFactory, myExprMarker, myExprText);
if (myExpr != null) {
myExprMarker = myEditor.getDocument().createRangeMarker(myExpr.getTextRange());
}
@@ -347,7 +298,7 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
myOccurrences[i] = myExpr;
continue;
}
final PsiExpression psiExpression = restoreExpression(containingFile, psiParameter, elementFactory, marker);
final PsiExpression psiExpression = restoreExpression(containingFile, psiParameter, elementFactory, marker, myExprText);
if (psiExpression != null) {
myOccurrences[i] = psiExpression;
}
@@ -360,21 +311,6 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI {
});
}
@Nullable
private PsiExpression restoreExpression(PsiFile containingFile,
PsiParameter psiParameter,
PsiElementFactory elementFactory,
RangeMarker marker) {
if (myExprText == null) return null;
if (psiParameter == null || !psiParameter.isValid()) return null;
final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset());
final PsiExpression expression = PsiTreeUtil.getParentOfType(refVariableElement, PsiReferenceExpression.class);
if (expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).resolve() == psiParameter) {
return (PsiExpression)expression.replace(elementFactory.createExpressionFromText(myExprText, myMethod));
}
return null;
}
public boolean createFinals() {
return hasFinalModifier();
@@ -109,30 +109,7 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
myCanBeFinal = new NonFocusableCheckBox("Declare final");
myCanBeFinal.setSelected(createFinals());
myCanBeFinal.setMnemonic('f');
myCanBeFinal.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new WriteCommandAction(project){
@Override
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
final PsiModifierList modifierList = getVariable().getModifierList();
LOG.assertTrue(modifierList != null);
final Document document = myEditor.getDocument();
final int textOffset = modifierList.getTextOffset();
if (myCanBeFinal.isSelected()) {
if (StringUtil.isEmptyOrSpaces(document.getText(new TextRange(textOffset - 1, textOffset)))) {
document.insertString(textOffset - 1, "final");
} else {
document.insertString(textOffset, "final ");
}
}
else {
document.deleteString(textOffset, textOffset + modifierList.getTextLength());
}
}
}.execute();
}
});
myCanBeFinal.addActionListener(new FinalListener(project));
}
}
@@ -186,6 +163,10 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
return super.performInplaceRename(processTextOccurrences, nameSuggestions);
}
public RangeMarker getExprMarker() {
return myExprMarker;
}
@Override
protected void moveOffsetAfter(boolean success) {
try {
@@ -382,4 +363,41 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer {
myBalloon
.show(new RelativePoint(new Point(screenPoint.x, screenPoint.y - myEditor.getLineHeight())), Balloon.Position.above);
}
public class FinalListener implements ActionListener {
private final Project myProject;
public FinalListener(Project project) {
myProject = project;
}
@Override
public void actionPerformed(ActionEvent e) {
perform(myCanBeFinal.isSelected());
}
public void perform(final boolean generateFinal) {
new WriteCommandAction(myProject){
@Override
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
final PsiVariable variable = getVariable();
LOG.assertTrue(variable != null);
final PsiModifierList modifierList = variable.getModifierList();
LOG.assertTrue(modifierList != null);
final int textOffset = modifierList.getTextOffset();
final Document document = myEditor.getDocument();
if (generateFinal) {
final PsiTypeElement typeElement = variable.getTypeElement();
final int typeOffset = typeElement != null ? typeElement.getTextOffset() : textOffset;
document.insertString(typeOffset, PsiModifier.FINAL + " ");
}
else {
final int idx = modifierList.getText().indexOf(PsiModifier.FINAL);
document.deleteString(textOffset + idx, textOffset + idx + PsiModifier.FINAL.length() + 1);
}
}
}.execute();
}
}
}
@@ -144,12 +144,7 @@ public class VariableInplaceRenamer {
ourRenamersStack.push(this);
PsiElement scope = null;
final SearchScope searchScope = myElementToRename.getManager().getSearchHelper().getUseScope(myElementToRename);
if (searchScope instanceof LocalSearchScope) {
final PsiElement[] elements = ((LocalSearchScope)searchScope).getScope();
scope = PsiTreeUtil.findCommonParent(elements);
}
PsiElement scope = checkLocalScope();
if (scope == null) {
return false; // Should have valid local search scope for inplace rename
@@ -173,6 +168,17 @@ public class VariableInplaceRenamer {
return true;
}
@Nullable
protected PsiElement checkLocalScope() {
final SearchScope searchScope = myElementToRename.getManager().getSearchHelper().getUseScope(myElementToRename);
if (searchScope instanceof LocalSearchScope) {
final PsiElement[] elements = ((LocalSearchScope)searchScope).getScope();
return PsiTreeUtil.findCommonParent(elements);
}
return null;
}
protected boolean appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages) {
return stringUsages.isEmpty();
}