mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
705 lines
29 KiB
Java
705 lines
29 KiB
Java
/*
|
|
* Copyright 2000-2009 JetBrains s.r.o.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* Created by IntelliJ IDEA.
|
|
* User: dsl
|
|
* Date: 29.05.2002
|
|
* Time: 13:05:34
|
|
* To change template for new class use
|
|
* Code Style | Class Templates options (Tools | IDE Options).
|
|
*/
|
|
package com.intellij.refactoring.introduceField;
|
|
|
|
import com.intellij.codeInsight.AnnotationUtil;
|
|
import com.intellij.codeInsight.ChangeContextUtil;
|
|
import com.intellij.codeInsight.TestUtil;
|
|
import com.intellij.codeInsight.highlighting.HighlightManager;
|
|
import com.intellij.ide.util.DirectoryChooserUtil;
|
|
import com.intellij.ide.util.PackageUtil;
|
|
import com.intellij.openapi.application.ApplicationManager;
|
|
import com.intellij.openapi.command.CommandProcessor;
|
|
import com.intellij.openapi.diagnostic.Logger;
|
|
import com.intellij.openapi.editor.Editor;
|
|
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.Pass;
|
|
import com.intellij.openapi.util.text.StringUtil;
|
|
import com.intellij.openapi.wm.WindowManager;
|
|
import com.intellij.psi.*;
|
|
import com.intellij.psi.codeStyle.CodeStyleManager;
|
|
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
|
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
|
import com.intellij.psi.search.GlobalSearchScope;
|
|
import com.intellij.psi.util.PsiTreeUtil;
|
|
import com.intellij.psi.util.PsiUtil;
|
|
import com.intellij.refactoring.IntroduceHandlerBase;
|
|
import com.intellij.refactoring.RefactoringActionHandler;
|
|
import com.intellij.refactoring.RefactoringBundle;
|
|
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
|
import com.intellij.refactoring.rename.RenameJavaVariableProcessor;
|
|
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
|
import com.intellij.refactoring.util.EnumConstantsUtil;
|
|
import com.intellij.refactoring.util.RefactoringUtil;
|
|
import com.intellij.refactoring.util.occurences.OccurenceManager;
|
|
import com.intellij.util.IncorrectOperationException;
|
|
import com.intellij.util.VisibilityUtil;
|
|
import org.jetbrains.annotations.NonNls;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase implements RefactoringActionHandler {
|
|
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler");
|
|
|
|
public enum InitializationPlace {
|
|
IN_CURRENT_METHOD,
|
|
IN_FIELD_DECLARATION,
|
|
IN_CONSTRUCTOR,
|
|
IN_SETUP_METHOD
|
|
}
|
|
|
|
private PsiClass myParentClass;
|
|
|
|
protected boolean invokeImpl(final Project project, @NotNull final PsiExpression selectedExpr, final Editor editor) {
|
|
final PsiElement element = getPhysicalElement(selectedExpr);
|
|
|
|
final PsiFile file = element.getContainingFile();
|
|
LOG.assertTrue(file != null, "expr.getContainingFile() == null");
|
|
|
|
if (LOG.isDebugEnabled()) {
|
|
LOG.debug("expression:" + selectedExpr);
|
|
}
|
|
|
|
myParentClass = getParentClass(selectedExpr);
|
|
if (myParentClass == null) {
|
|
if (JspPsiUtil.isInJspFile(file)) {
|
|
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.message("error.not.supported.for.jsp", getRefactoringName()),
|
|
getRefactoringName(), getHelpID());
|
|
return false;
|
|
}
|
|
else {
|
|
LOG.assertTrue(false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!validClass(myParentClass, editor)) {
|
|
return false;
|
|
}
|
|
|
|
PsiType tempType = getTypeByExpression(selectedExpr);
|
|
if (tempType == null) {
|
|
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("unknown.expression.type"));
|
|
CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), getHelpID());
|
|
return false;
|
|
}
|
|
|
|
if (PsiType.VOID.equals(tempType)) {
|
|
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("selected.expression.has.void.type"));
|
|
CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), getHelpID());
|
|
return false;
|
|
}
|
|
|
|
|
|
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return false;
|
|
|
|
final PsiClass parentClass = myParentClass;
|
|
final OccurenceManager occurenceManager = createOccurenceManager(selectedExpr, parentClass);
|
|
final PsiExpression[] occurrences = occurenceManager.getOccurences();
|
|
final PsiElement anchorStatementIfAll = occurenceManager.getAnchorStatementForAll();
|
|
|
|
List<RangeHighlighter> highlighters = null;
|
|
if (editor != null) {
|
|
highlighters = RefactoringUtil.highlightAllOccurences(project, occurrences, editor);
|
|
}
|
|
|
|
PsiElement tempAnchorElement = RefactoringUtil.getParentExpressionAnchorElement(selectedExpr);
|
|
if (IntroduceVariableBase.checkAnchorBeforeThisOrSuper(project, editor, tempAnchorElement, getRefactoringName(), getHelpID())) return false;
|
|
|
|
final Settings settings =
|
|
showRefactoringDialog(project, editor, myParentClass, selectedExpr, tempType,
|
|
occurrences, tempAnchorElement, anchorStatementIfAll);
|
|
|
|
if (settings == null) return false;
|
|
|
|
if (settings.getForcedType() != null) {
|
|
tempType = settings.getForcedType();
|
|
}
|
|
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) {
|
|
highlightManager.removeSegmentHighlighter(editor, highlighter);
|
|
}
|
|
}
|
|
|
|
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 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 {
|
|
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 = array.toArray(new PsiElement[array.size()]);
|
|
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);
|
|
}
|
|
}
|
|
};
|
|
|
|
CommandProcessor.getInstance().executeCommand(
|
|
project,
|
|
new Runnable() {
|
|
public void run() {
|
|
ApplicationManager.getApplication().runWriteAction(runnable);
|
|
}
|
|
},
|
|
getRefactoringName(), null
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
public static void setModifiers(PsiField field, Settings settings, final boolean declareStatic) {
|
|
if (!settings.isIntroduceEnumConstant()) {
|
|
if (declareStatic) {
|
|
PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true);
|
|
}
|
|
if (settings.isDeclareFinal()) {
|
|
PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true);
|
|
}
|
|
if (settings.isAnnotateAsNonNls()) {
|
|
PsiAnnotation annotation = JavaPsiFacade.getInstance(field.getProject()).getElementFactory()
|
|
.createAnnotationFromText("@" + AnnotationUtil.NON_NLS, field);
|
|
final PsiModifierList modifierList = field.getModifierList();
|
|
LOG.assertTrue(modifierList != null);
|
|
modifierList.addAfter(annotation, null);
|
|
}
|
|
}
|
|
JavaCodeStyleManager.getInstance(field.getProject()).shortenClassReferences(field);
|
|
}
|
|
|
|
private static PsiElement getPhysicalElement(final PsiExpression selectedExpr) {
|
|
PsiElement element = selectedExpr.getUserData(ElementToWorkOn.PARENT);
|
|
if (element == null) element = selectedExpr;
|
|
return element;
|
|
}
|
|
|
|
private static TextAttributes highlightAttributes() {
|
|
return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(
|
|
EditorColors.SEARCH_RESULT_ATTRIBUTES
|
|
);
|
|
}
|
|
|
|
protected abstract OccurenceManager createOccurenceManager(PsiExpression selectedExpr, PsiClass parentClass);
|
|
|
|
protected final PsiClass getParentClass() {
|
|
return myParentClass;
|
|
}
|
|
|
|
protected abstract boolean validClass(PsiClass parentClass, Editor editor);
|
|
|
|
private static PsiElement getNormalizedAnchor(PsiElement anchorElement) {
|
|
PsiElement child = anchorElement;
|
|
while (child != null) {
|
|
PsiElement prev = child.getPrevSibling();
|
|
if (RefactoringUtil.isExpressionAnchorElement(prev)) break;
|
|
if (prev instanceof PsiJavaToken && ((PsiJavaToken)prev).getTokenType() == JavaTokenType.LBRACE) break;
|
|
child = prev;
|
|
}
|
|
|
|
child = PsiTreeUtil.skipSiblingsForward(child, PsiWhiteSpace.class, PsiComment.class);
|
|
PsiElement anchor;
|
|
if (child != null) {
|
|
anchor = child;
|
|
}
|
|
else {
|
|
anchor = anchorElement;
|
|
}
|
|
return anchor;
|
|
}
|
|
|
|
protected abstract String getHelpID();
|
|
|
|
protected abstract Settings showRefactoringDialog(Project project, Editor editor, PsiClass parentClass, PsiExpression expr,
|
|
PsiType type, PsiExpression[] occurences, PsiElement anchorElement,
|
|
PsiElement anchorElementIfAll);
|
|
|
|
|
|
private static PsiType getTypeByExpression(PsiExpression expr) {
|
|
return RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
|
|
}
|
|
|
|
public PsiClass getParentClass(@NotNull PsiExpression initializerExpression) {
|
|
PsiElement element = initializerExpression.getUserData(ElementToWorkOn.PARENT);
|
|
if (element == null) element = initializerExpression.getParent();
|
|
PsiElement parent = element;
|
|
while (parent != null) {
|
|
if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) {
|
|
return (PsiClass)parent;
|
|
}
|
|
parent = parent.getParent();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static PsiMethod getEnclosingConstructor(PsiClass parentClass, PsiElement element) {
|
|
if (element == null) return null;
|
|
final PsiMethod[] constructors = parentClass.getConstructors();
|
|
for (PsiMethod constructor : constructors) {
|
|
if (PsiTreeUtil.isAncestor(constructor, element, false)) return constructor;
|
|
}
|
|
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);
|
|
|
|
assert setupMethod != null;
|
|
|
|
PsiElement anchor = null;
|
|
if (PsiTreeUtil.isAncestor(setupMethod, initializer, true)) {
|
|
anchor = replaceAll
|
|
? occurenceManager.getAnchorStatementForAllInScope(setupMethod)
|
|
: PsiTreeUtil.getParentOfType(initializer, PsiStatement.class);
|
|
}
|
|
|
|
final PsiExpressionStatement expressionStatement =
|
|
(PsiExpressionStatement)JavaPsiFacade.getInstance(myParentClass.getProject()).getElementFactory()
|
|
.createStatementFromText(field.getName() + "= expr;", null);
|
|
PsiAssignmentExpression expr = (PsiAssignmentExpression)expressionStatement.getExpression();
|
|
final PsiExpression rExpression = expr.getRExpression();
|
|
LOG.assertTrue(rExpression != null);
|
|
rExpression.replace(initializer);
|
|
|
|
final PsiCodeBlock body = setupMethod.getBody();
|
|
assert body != null;
|
|
body.addBefore(expressionStatement, anchor);
|
|
}
|
|
|
|
private void addInitializationToConstructors(PsiExpression initializerExpression, PsiField field, PsiMethod enclosingConstructor) {
|
|
try {
|
|
PsiClass aClass = field.getContainingClass();
|
|
PsiMethod[] constructors = aClass.getConstructors();
|
|
|
|
boolean added = false;
|
|
for (PsiMethod constructor : constructors) {
|
|
if (constructor == enclosingConstructor) continue;
|
|
PsiCodeBlock body = constructor.getBody();
|
|
if (body == null) continue;
|
|
PsiStatement[] statements = body.getStatements();
|
|
if (statements.length > 0) {
|
|
PsiStatement first = statements[0];
|
|
if (first instanceof PsiExpressionStatement) {
|
|
PsiExpression expression = ((PsiExpressionStatement)first).getExpression();
|
|
if (expression instanceof PsiMethodCallExpression) {
|
|
@NonNls String text = ((PsiMethodCallExpression)expression).getMethodExpression().getText();
|
|
if ("this".equals(text)) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
PsiStatement assignment = createAssignment(field, initializerExpression, body.getLastChild());
|
|
assignment = (PsiStatement) body.add(assignment);
|
|
ChangeContextUtil.decodeContextInfo(assignment, field.getContainingClass(),
|
|
RefactoringUtil.createThisExpression(field.getManager(), null));
|
|
added = true;
|
|
}
|
|
if (!added && enclosingConstructor == null) {
|
|
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());
|
|
assignment = (PsiStatement) body.add(assignment);
|
|
ChangeContextUtil.decodeContextInfo(assignment, field.getContainingClass(),
|
|
RefactoringUtil.createThisExpression(field.getManager(), null));
|
|
}
|
|
}
|
|
catch (IncorrectOperationException e) {
|
|
LOG.error(e);
|
|
}
|
|
}
|
|
|
|
private PsiField createField(String fieldName, PsiType type, PsiExpression initializerExpr, boolean includeInitializer) {
|
|
@NonNls StringBuilder pattern = new StringBuilder();
|
|
pattern.append("private int ");
|
|
pattern.append(fieldName);
|
|
if (includeInitializer) {
|
|
pattern.append("=0");
|
|
}
|
|
pattern.append(";");
|
|
PsiManager psiManager = myParentClass.getManager();
|
|
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
|
|
try {
|
|
PsiField field = factory.createFieldFromText(pattern.toString(), null);
|
|
field = (PsiField)CodeStyleManager.getInstance(psiManager.getProject()).reformat(field);
|
|
field.getTypeElement().replace(factory.createTypeElement(type));
|
|
if (includeInitializer) {
|
|
field.getInitializer().replace(initializerExpr);
|
|
}
|
|
return field;
|
|
}
|
|
catch (IncorrectOperationException e) {
|
|
LOG.error(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private PsiStatement createAssignment(PsiField field, PsiExpression initializerExpr, PsiElement context) {
|
|
try {
|
|
@NonNls String pattern = "x=0;";
|
|
PsiManager psiManager = myParentClass.getManager();
|
|
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
|
|
PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(pattern, null);
|
|
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(psiManager.getProject()).reformat(statement);
|
|
|
|
PsiAssignmentExpression expr = (PsiAssignmentExpression)statement.getExpression();
|
|
final PsiExpression rExpression = expr.getRExpression();
|
|
LOG.assertTrue(rExpression != null);
|
|
rExpression.replace(initializerExpr);
|
|
final PsiReferenceExpression fieldReference = RenameJavaVariableProcessor.createMemberReference(field, context);
|
|
expr.getLExpression().replace(fieldReference);
|
|
|
|
return statement;
|
|
}
|
|
catch (IncorrectOperationException e) {
|
|
LOG.error(e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
protected Pass<ElementToWorkOn> getElementProcessor(final Project project, final Editor editor) {
|
|
return new Pass<ElementToWorkOn>() {
|
|
@Override
|
|
public void pass(final ElementToWorkOn elementToWorkOn) {
|
|
if (elementToWorkOn == null) return;
|
|
|
|
if (elementToWorkOn.getExpression() == null) {
|
|
final PsiLocalVariable localVariable = elementToWorkOn.getLocalVariable();
|
|
final boolean result = invokeImpl(project, localVariable, editor);
|
|
if (result) {
|
|
editor.getSelectionModel().removeSelection();
|
|
}
|
|
}
|
|
else if (invokeImpl(project, elementToWorkOn.getExpression(), editor)) {
|
|
editor.getSelectionModel().removeSelection();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
protected abstract String getRefactoringName();
|
|
|
|
public static class Settings {
|
|
private final String myFieldName;
|
|
private final PsiType myForcedType;
|
|
|
|
private final boolean myReplaceAll;
|
|
private final boolean myDeclareStatic;
|
|
private final boolean myDeclareFinal;
|
|
private final InitializationPlace myInitializerPlace;
|
|
private final String myVisibility;
|
|
private final boolean myDeleteLocalVariable;
|
|
private final TargetDestination myTargetClass;
|
|
private final boolean myAnnotateAsNonNls;
|
|
private final boolean myIntroduceEnumConstant;
|
|
|
|
public PsiLocalVariable getLocalVariable() {
|
|
return myLocalVariable;
|
|
}
|
|
|
|
public boolean isDeleteLocalVariable() {
|
|
return myDeleteLocalVariable;
|
|
}
|
|
|
|
private final PsiLocalVariable myLocalVariable;
|
|
|
|
public String getFieldName() {
|
|
return myFieldName;
|
|
}
|
|
|
|
public boolean isDeclareStatic() {
|
|
return myDeclareStatic;
|
|
}
|
|
|
|
public boolean isDeclareFinal() {
|
|
return myDeclareFinal;
|
|
}
|
|
|
|
public InitializationPlace getInitializerPlace() {
|
|
return myInitializerPlace;
|
|
}
|
|
|
|
public String getFieldVisibility() {
|
|
return myVisibility;
|
|
}
|
|
|
|
@Nullable
|
|
public PsiClass getDestinationClass() {
|
|
return myTargetClass != null ? myTargetClass.getTargetClass() : null;
|
|
}
|
|
|
|
public PsiType getForcedType() {
|
|
return myForcedType;
|
|
}
|
|
|
|
public boolean isReplaceAll() {
|
|
return myReplaceAll;
|
|
}
|
|
|
|
public boolean isAnnotateAsNonNls() {
|
|
return myAnnotateAsNonNls;
|
|
}
|
|
|
|
public boolean isIntroduceEnumConstant() {
|
|
return myIntroduceEnumConstant;
|
|
}
|
|
|
|
public Settings(String fieldName, boolean replaceAll,
|
|
boolean declareStatic, boolean declareFinal,
|
|
InitializationPlace initializerPlace, String visibility, PsiLocalVariable localVariableToRemove, PsiType forcedType,
|
|
boolean deleteLocalVariable,
|
|
TargetDestination targetDestination,
|
|
final boolean annotateAsNonNls,
|
|
final boolean introduceEnumConstant) {
|
|
|
|
myFieldName = fieldName;
|
|
myReplaceAll = replaceAll;
|
|
myDeclareStatic = declareStatic;
|
|
myDeclareFinal = declareFinal;
|
|
myInitializerPlace = initializerPlace;
|
|
myVisibility = visibility;
|
|
myLocalVariable = localVariableToRemove;
|
|
myDeleteLocalVariable = deleteLocalVariable;
|
|
myForcedType = forcedType;
|
|
myTargetClass = targetDestination;
|
|
myAnnotateAsNonNls = annotateAsNonNls;
|
|
myIntroduceEnumConstant = introduceEnumConstant;
|
|
}
|
|
|
|
public Settings(String fieldName, boolean replaceAll,
|
|
boolean declareStatic, boolean declareFinal,
|
|
InitializationPlace initializerPlace, String visibility, PsiLocalVariable localVariableToRemove, PsiType forcedType,
|
|
boolean deleteLocalVariable,
|
|
PsiClass targetClass,
|
|
final boolean annotateAsNonNls,
|
|
final boolean introduceEnumConstant) {
|
|
|
|
this(fieldName, replaceAll, declareStatic, declareFinal, initializerPlace, visibility, localVariableToRemove, forcedType, deleteLocalVariable, new TargetDestination(targetClass), annotateAsNonNls, introduceEnumConstant);
|
|
}
|
|
|
|
}
|
|
|
|
public static class TargetDestination {
|
|
private final String myQualifiedName;
|
|
private final Project myProject;
|
|
|
|
private PsiClass myParentClass;
|
|
private PsiClass myTargetClass;
|
|
|
|
public TargetDestination(String qualifiedName, PsiClass parentClass) {
|
|
myQualifiedName = qualifiedName;
|
|
myParentClass = parentClass;
|
|
myProject = parentClass.getProject();
|
|
}
|
|
|
|
public TargetDestination(@NotNull PsiClass targetClass) {
|
|
myTargetClass = targetClass;
|
|
myQualifiedName = targetClass.getQualifiedName();
|
|
myProject = targetClass.getProject();
|
|
}
|
|
|
|
@Nullable
|
|
public PsiClass getTargetClass() {
|
|
if (myTargetClass != null) return myTargetClass;
|
|
final String packageName = StringUtil.getPackageName(myQualifiedName);
|
|
PsiPackage psiPackage = JavaPsiFacade.getInstance(myProject).findPackage(packageName);
|
|
final PsiDirectory psiDirectory;
|
|
if (psiPackage != null) {
|
|
final PsiDirectory[] directories = psiPackage.getDirectories(GlobalSearchScope.allScope(myProject));
|
|
psiDirectory = directories.length > 1 ? DirectoryChooserUtil.chooseDirectory(directories, null, myProject, new HashMap<PsiDirectory, String>()) : directories[0];
|
|
} else {
|
|
psiDirectory = PackageUtil.findOrCreateDirectoryForPackage(myProject, packageName, myParentClass.getContainingFile().getContainingDirectory(), false);
|
|
}
|
|
final String shortName = StringUtil.getShortName(myQualifiedName);
|
|
myTargetClass = psiDirectory != null ? JavaDirectoryService.getInstance().createClass(psiDirectory, shortName) : null;
|
|
return myTargetClass;
|
|
}
|
|
}
|
|
}
|