mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inplace introduce variable
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+152
-66
@@ -24,29 +24,35 @@
|
||||
package com.intellij.refactoring.introduceVariable;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtil;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.highlighting.HighlightManager;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
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.codeStyle.*;
|
||||
import com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.IntroduceHandlerBase;
|
||||
import com.intellij.refactoring.IntroduceTargetChooser;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.*;
|
||||
import com.intellij.refactoring.introduceField.ElementToWorkOn;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
|
||||
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.FieldConflictsResolver;
|
||||
@@ -55,13 +61,12 @@ import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.occurences.ExpressionOccurenceManager;
|
||||
import com.intellij.refactoring.util.occurences.NotInSuperCallOccurenceFilter;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.containers.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class IntroduceVariableBase extends IntroduceHandlerBase implements RefactoringActionHandler {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceVariable.IntroduceVariableBase");
|
||||
@@ -69,6 +74,15 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
|
||||
protected static String REFACTORING_NAME = RefactoringBundle.message("introduce.variable.title");
|
||||
|
||||
public static SuggestedNameInfo getSuggestedName(PsiType type, final PsiExpression expression) {
|
||||
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject());
|
||||
final SuggestedNameInfo nameInfo = codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, expression, type);
|
||||
final String[] strings = JavaCompletionUtil
|
||||
.completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo);
|
||||
final SuggestedNameInfo.Delegate delegate = new SuggestedNameInfo.Delegate(strings, nameInfo);
|
||||
return codeStyleManager.suggestUniqueVariableName(delegate, expression, true);
|
||||
}
|
||||
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, DataContext dataContext) {
|
||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||
if (!selectionModel.hasSelection()) {
|
||||
@@ -351,10 +365,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
|
||||
|
||||
PsiType originalType = RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
|
||||
final PsiType originalType = RefactoringUtil.getTypeByExpressionWithExpectedType(expr);
|
||||
if (originalType == null) {
|
||||
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("unknown.expression.type"));
|
||||
showErrorMessage(project, editor, message);
|
||||
@@ -370,7 +382,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
|
||||
final PsiElement physicalElement = expr.getUserData(ElementToWorkOn.PARENT);
|
||||
|
||||
PsiElement anchorStatement = RefactoringUtil.getParentStatement(physicalElement != null ? physicalElement : expr, false);
|
||||
final PsiElement anchorStatement = RefactoringUtil.getParentStatement(physicalElement != null ? physicalElement : expr, false);
|
||||
|
||||
if (anchorStatement == null) {
|
||||
return parentStatementNotFound(project, editor);
|
||||
@@ -388,7 +400,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
}
|
||||
}
|
||||
|
||||
PsiElement tempContainer = anchorStatement.getParent();
|
||||
final PsiElement tempContainer = anchorStatement.getParent();
|
||||
|
||||
if (!(tempContainer instanceof PsiCodeBlock) && !isLoopOrIf(tempContainer)) {
|
||||
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
|
||||
@@ -418,38 +430,66 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionOccurenceManager occurenceManager = new ExpressionOccurenceManager(expr, lastScope,
|
||||
final ExpressionOccurenceManager occurenceManager = new ExpressionOccurenceManager(expr, lastScope,
|
||||
NotInSuperCallOccurenceFilter.INSTANCE);
|
||||
final PsiExpression[] occurrences = occurenceManager.getOccurences();
|
||||
final PsiElement anchorStatementIfAll = occurenceManager.getAnchorStatementForAll();
|
||||
boolean declareFinalIfAll = occurenceManager.isInFinalContext();
|
||||
|
||||
final LinkedHashMap<OccurrencesChooser.ReplaceChoice, PsiExpression[]> occurrencesMap =
|
||||
new LinkedHashMap<OccurrencesChooser.ReplaceChoice, PsiExpression[]>();
|
||||
|
||||
boolean anyAssignmentLHS = false;
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
if (RefactoringUtil.isAssignmentLHS(occurrence)) {
|
||||
anyAssignmentLHS = true;
|
||||
break;
|
||||
final boolean hasWriteAccess = OccurrencesChooser.fillChoices(expr, occurrences, occurrencesMap);
|
||||
|
||||
final boolean isInplaceAvailableOnDataContext =
|
||||
new VariableInplaceRenameHandler().isAvailableOnDataContext(DataManager.getInstance().getDataContext()) &&
|
||||
!ApplicationManager.getApplication().isUnitTestMode();
|
||||
final boolean inFinalContext = occurenceManager.isInFinalContext();
|
||||
final InputValidator validator = new InputValidator(this, project, anchorStatementIfAll, anchorStatement, occurenceManager);
|
||||
final TypeSelectorManagerImpl typeSelectorManager = new TypeSelectorManagerImpl(project, originalType, expr, occurrences);
|
||||
|
||||
final Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||
@Override
|
||||
public void pass(OccurrencesChooser.ReplaceChoice choice) {
|
||||
final Ref<SmartPsiElementPointer<PsiVariable>> variable = new Ref<SmartPsiElementPointer<PsiVariable>>();
|
||||
final IntroduceVariableSettings settings =
|
||||
getSettings(project, editor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, choice);
|
||||
final Runnable runnable =
|
||||
introduce(project, expr, editor, anchorStatement, tempContainer, occurrences, anchorStatementIfAll, settings, variable);
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
project,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
if (isInplaceAvailableOnDataContext) {
|
||||
PsiVariable elementToRename = variable.get().getElement();
|
||||
if (elementToRename != null) {
|
||||
new VariableInplaceRenamer(elementToRename, editor).performInplaceRename(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, REFACTORING_NAME, null);
|
||||
}
|
||||
};
|
||||
|
||||
if (!isInplaceAvailableOnDataContext) {
|
||||
callback.pass(null);
|
||||
}
|
||||
|
||||
|
||||
IntroduceVariableSettings settings = getSettings(project, editor, expr, occurrences, anyAssignmentLHS, declareFinalIfAll,
|
||||
originalType,
|
||||
new TypeSelectorManagerImpl(project, originalType, expr, occurrences),
|
||||
new InputValidator(this, project, anchorStatementIfAll, anchorStatement, occurenceManager));
|
||||
|
||||
if (!settings.isOK()) {
|
||||
return false;
|
||||
else {
|
||||
new OccurrencesChooser(editor).showChooser(callback, occurrencesMap);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final String variableName = settings.getEnteredName();
|
||||
|
||||
final PsiType type = settings.getSelectedType();
|
||||
final boolean replaceAll = settings.isReplaceAllOccurrences();
|
||||
final boolean replaceWrite = settings.isReplaceLValues();
|
||||
final boolean declareFinal = replaceAll && declareFinalIfAll || settings.isDeclareFinal();
|
||||
if (replaceAll) {
|
||||
private static Runnable introduce(final Project project,
|
||||
final PsiExpression expr,
|
||||
final Editor editor,
|
||||
PsiElement anchorStatement,
|
||||
PsiElement tempContainer,
|
||||
final PsiExpression[] occurrences,
|
||||
PsiElement anchorStatementIfAll,
|
||||
final IntroduceVariableSettings settings,
|
||||
final Ref<SmartPsiElementPointer<PsiVariable>> variable) {
|
||||
if (settings.isReplaceAllOccurrences()) {
|
||||
anchorStatement = anchorStatementIfAll;
|
||||
tempContainer = anchorStatement.getParent();
|
||||
}
|
||||
@@ -463,7 +503,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
final PsiElement anchor = child == null ? anchorStatement : child;
|
||||
|
||||
boolean tempDeleteSelf = false;
|
||||
final boolean replaceSelf = replaceWrite || !RefactoringUtil.isAssignmentLHS(expr);
|
||||
final boolean replaceSelf = settings.isReplaceLValues() || !RefactoringUtil.isAssignmentLHS(expr);
|
||||
if (!isLoopOrIf(container)) {
|
||||
if (expr.getParent() instanceof PsiExpressionStatement && anchor.equals(anchorStatement)) {
|
||||
PsiStatement statement = (PsiStatement) expr.getParent();
|
||||
@@ -489,10 +529,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
}
|
||||
|
||||
final PsiCodeBlock newDeclarationScope = PsiTreeUtil.getParentOfType(container, PsiCodeBlock.class, false);
|
||||
final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(variableName, newDeclarationScope);
|
||||
|
||||
final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(settings.getEnteredName(), newDeclarationScope);
|
||||
final PsiElement finalAnchorStatement = anchorStatement;
|
||||
final Runnable runnable = new Runnable() {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
PsiStatement statement = null;
|
||||
@@ -500,6 +539,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
if (!isInsideLoop && deleteSelf) {
|
||||
statement = (PsiStatement) expr.getParent();
|
||||
}
|
||||
|
||||
final PsiExpression expr1 = fieldConflictsResolver.fixInitializer(expr);
|
||||
PsiExpression initializer = RefactoringUtil.unparenthesizeExpression(expr1);
|
||||
if (expr1 instanceof PsiNewExpression) {
|
||||
@@ -508,7 +548,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
initializer = newExpression.getArrayInitializer();
|
||||
}
|
||||
}
|
||||
PsiDeclarationStatement declaration = factory.createVariableDeclarationStatement(variableName, type, initializer);
|
||||
PsiDeclarationStatement declaration = JavaPsiFacade.getInstance(project).getElementFactory()
|
||||
.createVariableDeclarationStatement(settings.getEnteredName(), settings.getSelectedType(), initializer);
|
||||
if (!isInsideLoop) {
|
||||
declaration = (PsiDeclarationStatement) container.addBefore(declaration, anchor);
|
||||
LOG.assertTrue(expr1.isValid());
|
||||
@@ -528,8 +569,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
}
|
||||
}
|
||||
|
||||
PsiExpression ref = factory.createExpressionFromText(variableName, null);
|
||||
if (replaceAll) {
|
||||
PsiExpression ref = JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(settings.getEnteredName(), null);
|
||||
if (settings.isReplaceAllOccurrences()) {
|
||||
ArrayList<PsiElement> array = new ArrayList<PsiElement>();
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
if (deleteSelf && occurrence.equals(expr)) continue;
|
||||
@@ -539,7 +580,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
if (occurrence != null) {
|
||||
occurrence = RefactoringUtil.outermostParenthesizedExpression(occurrence);
|
||||
}
|
||||
if (replaceWrite || !RefactoringUtil.isAssignmentLHS(occurrence)) {
|
||||
if (settings.isReplaceLValues() || !RefactoringUtil.isAssignmentLHS(occurrence)) {
|
||||
array.add(replace(occurrence, ref, project));
|
||||
}
|
||||
}
|
||||
@@ -557,23 +598,14 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
declaration = (PsiDeclarationStatement) putStatementInLoopBody(declaration, container, finalAnchorStatement);
|
||||
declaration = (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(declaration);
|
||||
PsiVariable var = (PsiVariable) declaration.getDeclaredElements()[0];
|
||||
PsiUtil.setModifierProperty(var, PsiModifier.FINAL, declareFinal);
|
||||
|
||||
PsiUtil.setModifierProperty(var, PsiModifier.FINAL, settings.isDeclareFinal());
|
||||
variable.set(SmartPointerManager.getInstance(project).createLazyPointer(var));
|
||||
fieldConflictsResolver.fix();
|
||||
} catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
project,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
}
|
||||
}, REFACTORING_NAME, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static PsiElement replace(final PsiExpression expr1, final PsiExpression ref, final Project project)
|
||||
@@ -662,11 +694,15 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
return child;
|
||||
}
|
||||
|
||||
protected abstract void highlightReplacedOccurences(Project project, Editor editor, PsiElement[] replacedOccurences);
|
||||
|
||||
protected abstract IntroduceVariableSettings getSettings(Project project, Editor editor, PsiExpression expr, final PsiElement[] occurrences,
|
||||
boolean anyAssignmentLHS, final boolean declareFinalIfAll, final PsiType type,
|
||||
TypeSelectorManagerImpl typeSelectorManager, InputValidator validator);
|
||||
protected static void highlightReplacedOccurences(Project project, Editor editor, PsiElement[] replacedOccurences){
|
||||
if (editor == null) return;
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
HighlightManager highlightManager = HighlightManager.getInstance(project);
|
||||
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
|
||||
TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
|
||||
highlightManager.addOccurrenceHighlights(editor, replacedOccurences, attributes, true, null);
|
||||
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
|
||||
}
|
||||
|
||||
protected abstract void showErrorMessage(Project project, Editor editor, String message);
|
||||
|
||||
@@ -695,13 +731,65 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
return element instanceof PsiLoopStatement || element instanceof PsiIfStatement;
|
||||
}
|
||||
|
||||
protected boolean reportConflicts(MultiMap<PsiElement,String> conflicts, Project project, IntroduceVariableSettings settings){
|
||||
return false;
|
||||
}
|
||||
|
||||
public IntroduceVariableSettings getSettings(Project project, Editor editor,
|
||||
PsiExpression expr, PsiExpression[] occurrences,
|
||||
final TypeSelectorManagerImpl typeSelectorManager,
|
||||
boolean declareFinalIfAll,
|
||||
boolean anyAssignmentLHS,
|
||||
final InputValidator validator,
|
||||
final OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||
final SuggestedNameInfo suggestedName = getSuggestedName(typeSelectorManager.getDefaultType(), expr);
|
||||
final String variableName = suggestedName.names[0];
|
||||
final Boolean generateFinals = JavaRefactoringSettings.getInstance().INTRODUCE_LOCAL_CREATE_FINALS;
|
||||
final boolean replaceAll =
|
||||
replaceChoice == OccurrencesChooser.ReplaceChoice.ALL || replaceChoice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
|
||||
final boolean declareFinal =
|
||||
!anyAssignmentLHS && (replaceAll &&
|
||||
declareFinalIfAll || generateFinals == null ?
|
||||
CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS :
|
||||
generateFinals.booleanValue());
|
||||
final boolean replaceWrite = anyAssignmentLHS && replaceChoice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
return new IntroduceVariableSettings() {
|
||||
@Override
|
||||
public String getEnteredName() {
|
||||
return variableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceAllOccurrences() {
|
||||
return replaceAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeclareFinal() {
|
||||
return declareFinal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceLValues() {
|
||||
return replaceWrite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getSelectedType() {
|
||||
return typeSelectorManager.getDefaultType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface Validator {
|
||||
boolean isOK(IntroduceVariableSettings dialog);
|
||||
}
|
||||
|
||||
protected abstract boolean reportConflicts(MultiMap<PsiElement,String> conflicts, final Project project, IntroduceVariableSettings dialog);
|
||||
|
||||
|
||||
public static void checkInLoopCondition(PsiExpression occurence, MultiMap<PsiElement, String> conflicts) {
|
||||
final PsiElement loopForLoopCondition = RefactoringUtil.getLoopForLoopCondition(occurence);
|
||||
if (loopForLoopCondition == null) return;
|
||||
@@ -721,6 +809,4 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
conflicts.putValue(occurence, RefactoringBundle.message("introducing.variable.may.break.code.logic"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+14
-16
@@ -22,11 +22,10 @@ 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.wm.WindowManager;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.ui.ConflictsDialog;
|
||||
@@ -38,11 +37,19 @@ import java.util.ArrayList;
|
||||
|
||||
public class IntroduceVariableHandler extends IntroduceVariableBase {
|
||||
|
||||
protected IntroduceVariableSettings getSettings(final Project project, Editor editor, PsiExpression expr,
|
||||
PsiElement[] occurrences, boolean anyAssignmentLHS,
|
||||
boolean declareFinalIfAll, PsiType type,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
InputValidator validator) {
|
||||
|
||||
@Override
|
||||
public IntroduceVariableSettings getSettings(Project project, Editor editor,
|
||||
PsiExpression expr, PsiExpression[] occurrences,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
boolean declareFinalIfAll,
|
||||
boolean anyAssignmentLHS,
|
||||
final InputValidator validator,
|
||||
final OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||
if (replaceChoice != null) {
|
||||
return super.getSettings(project, editor, expr, occurrences, typeSelectorManager, declareFinalIfAll, anyAssignmentLHS, validator,
|
||||
replaceChoice);
|
||||
}
|
||||
ArrayList<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
|
||||
HighlightManager highlightManager = null;
|
||||
if (editor != null) {
|
||||
@@ -78,15 +85,6 @@ public class IntroduceVariableHandler extends IntroduceVariableBase {
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE);
|
||||
}
|
||||
|
||||
protected void highlightReplacedOccurences(final Project project, Editor editor, final PsiElement[] replacedOccurences) {
|
||||
if (editor == null) return;
|
||||
HighlightManager highlightManager = HighlightManager.getInstance(project);
|
||||
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
|
||||
TextAttributes attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
|
||||
highlightManager.addOccurrenceHighlights(editor, replacedOccurences, attributes, true, null);
|
||||
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
|
||||
}
|
||||
|
||||
protected boolean reportConflicts(final MultiMap<PsiElement,String> conflicts, final Project project, IntroduceVariableSettings dialog) {
|
||||
ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts);
|
||||
conflictsDialog.show();
|
||||
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.refactoring.introduceVariable;
|
||||
|
||||
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.*;
|
||||
import com.intellij.openapi.ui.popup.JBPopupAdapter;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.ui.components.JBList;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 10/14/10
|
||||
*/
|
||||
public class OccurrencesChooser {
|
||||
public static enum ReplaceChoice {
|
||||
NO("Do not replace"), NO_WRITE("Replace all but write"), ALL("Replace all occurrences");
|
||||
|
||||
private String myDescription;
|
||||
|
||||
ReplaceChoice(String description) {
|
||||
myDescription = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Set<RangeHighlighter> myRangeHighlighters = new HashSet<RangeHighlighter>();
|
||||
private final Editor myEditor;
|
||||
private final TextAttributes myAttributes;
|
||||
|
||||
public OccurrencesChooser(Editor editor) {
|
||||
myEditor = editor;
|
||||
myAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
|
||||
}
|
||||
|
||||
public void showChooser(final Pass<ReplaceChoice> callback,
|
||||
final Map<ReplaceChoice, PsiExpression[]> occurrencesMap) {
|
||||
if (occurrencesMap.size() == 1) {
|
||||
callback.pass(occurrencesMap.keySet().iterator().next());
|
||||
return;
|
||||
}
|
||||
final DefaultListModel model = new DefaultListModel();
|
||||
for (ReplaceChoice choice : occurrencesMap.keySet()) {
|
||||
model.addElement(choice);
|
||||
}
|
||||
final JList list = new JBList(model);
|
||||
list.setCellRenderer(new DefaultListCellRenderer() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(final JList list,
|
||||
final Object value,
|
||||
final int index,
|
||||
final boolean isSelected,
|
||||
final boolean cellHasFocus) {
|
||||
final Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
final ReplaceChoice choices = (ReplaceChoice)value;
|
||||
if (choices != null) {
|
||||
setText(choices.getDescription());
|
||||
}
|
||||
return rendererComponent;
|
||||
}
|
||||
});
|
||||
list.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(final ListSelectionEvent e) {
|
||||
final ReplaceChoice value = (ReplaceChoice)list.getSelectedValue();
|
||||
if (value == null) return;
|
||||
dropHighlighters();
|
||||
final MarkupModel markupModel = myEditor.getMarkupModel();
|
||||
final PsiExpression[] psiExpressions = occurrencesMap.get(value);
|
||||
for (PsiExpression psiExpression : psiExpressions) {
|
||||
final TextRange textRange = psiExpression.getTextRange();
|
||||
final RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter(
|
||||
textRange.getStartOffset(), textRange.getEndOffset(), HighlighterLayer.SELECTION - 1, myAttributes,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
myRangeHighlighters.add(rangeHighlighter);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JBPopupFactory.getInstance().createListPopupBuilder(list)
|
||||
.setTitle("Multiple occurrences found")
|
||||
.setMovable(false)
|
||||
.setResizable(false)
|
||||
.setRequestFocus(true)
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
callback.pass((ReplaceChoice)list.getSelectedValue());
|
||||
}
|
||||
})
|
||||
.addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
dropHighlighters();
|
||||
}
|
||||
})
|
||||
.createPopup().showInBestPositionFor(myEditor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if write usages found
|
||||
*/
|
||||
static boolean fillChoices(final PsiExpression expr,
|
||||
final PsiExpression[] occurrences,
|
||||
final LinkedHashMap<ReplaceChoice, PsiExpression[]> occurrencesMap) {
|
||||
occurrencesMap.put(ReplaceChoice.NO, new PsiExpression[]{expr});
|
||||
|
||||
final List<PsiExpression> nonWrite = new ArrayList<PsiExpression>();
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
if (!RefactoringUtil.isAssignmentLHS(occurrence)) {
|
||||
nonWrite.add(occurrence);
|
||||
}
|
||||
}
|
||||
final boolean hasWriteAccess = occurrences.length > nonWrite.size() && occurrences.length > 1;
|
||||
if (hasWriteAccess) {
|
||||
occurrencesMap.put(ReplaceChoice.NO_WRITE, nonWrite.toArray(new PsiExpression[nonWrite.size()]));
|
||||
}
|
||||
|
||||
if (occurrences.length > 1) {
|
||||
occurrencesMap.put(ReplaceChoice.ALL, occurrences);
|
||||
}
|
||||
return hasWriteAccess;
|
||||
}
|
||||
|
||||
private void dropHighlighters() {
|
||||
final MarkupModel markupModel = myEditor.getMarkupModel();
|
||||
for (RangeHighlighter highlight : myRangeHighlighters) {
|
||||
markupModel.removeHighlighter(highlight);
|
||||
}
|
||||
myRangeHighlighters.clear();
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,8 @@ class JavaResolveSnapshot extends ResolveSnapshotProvider.ResolveSnapshot {
|
||||
if (referent instanceof PsiReferenceExpression && referee instanceof PsiField) {
|
||||
PsiReferenceExpression ref = ((PsiReferenceExpression) referent);
|
||||
if (!ref.isQualified() && hidingLocalName.equals(ref.getReferenceName())) {
|
||||
final PsiElement newlyResolved = ref.resolve();
|
||||
if (referee.getManager().areElementsEquivalent(newlyResolved, referee)) return;
|
||||
PsiClass refereeClass = ((PsiField) referee).getContainingClass();
|
||||
PsiClass referentClass = PsiTreeUtil.getParentOfType(referent, PsiClass.class);
|
||||
if (refereeClass != null && referentClass != null &&
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
class Test {
|
||||
int myI;
|
||||
void foo(int i){
|
||||
this.myI = i;
|
||||
myI = i;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiType;
|
||||
import com.intellij.refactoring.introduceVariable.InputValidator;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings;
|
||||
import com.intellij.refactoring.introduceVariable.OccurrencesChooser;
|
||||
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -225,17 +226,17 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
public void testSiblingInnerClassType() throws Exception {
|
||||
doTest(new MockIntroduceVariableHandler("vari", true, false, false, "A.B"){
|
||||
@Override
|
||||
protected IntroduceVariableSettings getSettings(Project project,
|
||||
Editor editor,
|
||||
PsiExpression expr,
|
||||
PsiElement[] occurrences,
|
||||
boolean anyAssignmentLHS,
|
||||
boolean declareFinalIfAll,
|
||||
PsiType type,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
InputValidator validator) {
|
||||
public IntroduceVariableSettings getSettings(Project project, Editor editor,
|
||||
PsiExpression expr, PsiExpression[] occurrences,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
boolean declareFinalIfAll,
|
||||
boolean anyAssignmentLHS,
|
||||
InputValidator validator,
|
||||
final OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||
final PsiType type = typeSelectorManager.getDefaultType();
|
||||
Assert.assertTrue(type.getPresentableText(), type.getPresentableText().equals("B"));
|
||||
return super.getSettings(project, editor, expr, occurrences, anyAssignmentLHS, declareFinalIfAll, type, typeSelectorManager, validator);
|
||||
return super.getSettings(project, editor, expr, occurrences, typeSelectorManager, declareFinalIfAll, anyAssignmentLHS,
|
||||
validator, replaceChoice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+10
-11
@@ -2,12 +2,11 @@ package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.introduceVariable.InputValidator;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings;
|
||||
import com.intellij.refactoring.introduceVariable.OccurrencesChooser;
|
||||
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import junit.framework.Assert;
|
||||
@@ -36,9 +35,14 @@ class MockIntroduceVariableHandler extends IntroduceVariableBase {
|
||||
|
||||
|
||||
@Override
|
||||
protected IntroduceVariableSettings getSettings(Project project, Editor editor, PsiExpression expr, final PsiElement[] occurrences,
|
||||
boolean anyAssignmentLHS, final boolean declareFinalIfAll, final PsiType type,
|
||||
TypeSelectorManagerImpl typeSelectorManager, InputValidator validator) {
|
||||
public IntroduceVariableSettings getSettings(Project project, Editor editor,
|
||||
PsiExpression expr, final PsiExpression[] occurrences,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
final boolean declareFinalIfAll,
|
||||
boolean anyAssignmentLHS,
|
||||
InputValidator validator,
|
||||
final OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||
final PsiType type = typeSelectorManager.getDefaultType();
|
||||
Assert.assertTrue(type.getCanonicalText(), type.equalsToText(myExpectedTypeCanonicalName));
|
||||
IntroduceVariableSettings introduceVariableSettings = new IntroduceVariableSettings() {
|
||||
@Override
|
||||
@@ -85,11 +89,6 @@ class MockIntroduceVariableHandler extends IntroduceVariableBase {
|
||||
throw new RuntimeException("Error message:" + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void highlightReplacedOccurences(final Project project, Editor editor, final PsiElement[] replacedOccurences) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean reportConflicts(final MultiMap<PsiElement,String> conflicts, final Project project, IntroduceVariableSettings dialog) {
|
||||
return false;
|
||||
|
||||
@@ -73,7 +73,7 @@ public class RenameLocalTest extends LightCodeInsightTestCase {
|
||||
|
||||
ResolveSnapshotProvider resolveSnapshotProvider = VariableInplaceRenamer.INSTANCE.forLanguage(getFile().getLanguage());
|
||||
assertNotNull(resolveSnapshotProvider);
|
||||
final ResolveSnapshotProvider.ResolveSnapshot snapshot = resolveSnapshotProvider.createSnapshot(methodScope);
|
||||
final ResolveSnapshotProvider.ResolveSnapshot snapshot = resolveSnapshotProvider.createSnapshot(methodScope.getBody());
|
||||
assertNotNull(snapshot);
|
||||
|
||||
final int offset = element.getTextOffset();
|
||||
|
||||
+9
-1
@@ -97,9 +97,17 @@ public class VariableInplaceRenameHandler implements RenameHandler {
|
||||
|
||||
@Nullable
|
||||
public VariableInplaceRenamer doRename(final PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
|
||||
return doRename(elementToRename, editor, dataContext, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VariableInplaceRenamer doRename(final PsiElement elementToRename,
|
||||
final Editor editor,
|
||||
final DataContext dataContext,
|
||||
boolean processTextOccurrences) {
|
||||
|
||||
VariableInplaceRenamer renamer = createRenamer(elementToRename, editor);
|
||||
boolean startedRename = renamer == null ? false : renamer.performInplaceRename();
|
||||
boolean startedRename = renamer == null ? false : renamer.performInplaceRename(processTextOccurrences);
|
||||
|
||||
if (!startedRename) {
|
||||
try {
|
||||
|
||||
+6
-1
@@ -94,6 +94,10 @@ public class VariableInplaceRenamer {
|
||||
}
|
||||
|
||||
public boolean performInplaceRename() {
|
||||
return performInplaceRename(true);
|
||||
}
|
||||
|
||||
public boolean performInplaceRename(boolean processTextOccurrences) {
|
||||
if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(myElementToRename)) {
|
||||
return false;
|
||||
}
|
||||
@@ -146,7 +150,8 @@ public class VariableInplaceRenamer {
|
||||
}
|
||||
|
||||
String stringToSearch = myElementToRename.getName();
|
||||
if (stringToSearch != null &&
|
||||
if (processTextOccurrences &&
|
||||
stringToSearch != null &&
|
||||
!TextOccurrencesUtil.processUsagesInStringsAndComments(myElementToRename, stringToSearch, true, new PairProcessor<PsiElement, TextRange>() {
|
||||
public boolean process(PsiElement psiElement, TextRange textRange) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user