mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
introduce variable: common api (IDEA-94609; IDEA-125286; IDEA-131965; IDEA-131930)
This commit is contained in:
+1
-1
@@ -230,7 +230,7 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
|
||||
|
||||
@Override
|
||||
protected boolean startsOnTheSameElement(RefactoringActionHandler handler, PsiElement element) {
|
||||
return super.startsOnTheSameElement(handler, element) && handler instanceof IntroduceConstantHandler;
|
||||
return handler instanceof IntroduceConstantHandler && super.startsOnTheSameElement(handler, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -172,7 +172,7 @@ public class InplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPop
|
||||
|
||||
@Override
|
||||
protected boolean startsOnTheSameElement(RefactoringActionHandler handler, PsiElement element) {
|
||||
return super.startsOnTheSameElement(handler, element) && handler instanceof IntroduceFieldHandler;
|
||||
return handler instanceof IntroduceFieldHandler && super.startsOnTheSameElement(handler, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ public class InplaceIntroduceParameterPopup extends AbstractJavaInplaceIntroduce
|
||||
|
||||
@Override
|
||||
protected boolean startsOnTheSameElement(RefactoringActionHandler handler, PsiElement element) {
|
||||
return super.startsOnTheSameElement(handler, element) && handler instanceof IntroduceParameterHandler;
|
||||
return handler instanceof IntroduceParameterHandler && super.startsOnTheSameElement(handler, element);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+85
-79
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -18,7 +18,6 @@ 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.codeInsight.intention.impl.TypeExpression;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeInsight.unwrap.ScopeHighlighter;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
@@ -37,10 +36,7 @@ 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.Key;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
@@ -77,6 +73,7 @@ import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -91,6 +88,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
|
||||
protected static final String REFACTORING_NAME = RefactoringBundle.message("introduce.variable.title");
|
||||
public static final Key<Boolean> NEED_PARENTHESIS = Key.create("NEED_PARENTHESIS");
|
||||
private JavaVariableInplaceIntroducer myInplaceIntroducer;
|
||||
|
||||
public static SuggestedNameInfo getSuggestedName(@Nullable PsiType type, @NotNull final PsiExpression expression) {
|
||||
return getSuggestedName(type, expression, expression);
|
||||
@@ -645,76 +643,74 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
final Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||
@Override
|
||||
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
|
||||
final boolean allOccurences = choice == OccurrencesChooser.ReplaceChoice.ALL || choice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
|
||||
final Ref<SmartPsiElementPointer<PsiVariable>> variable = new Ref<SmartPsiElementPointer<PsiVariable>>();
|
||||
|
||||
final Editor topLevelEditor;
|
||||
if (!InjectedLanguageManager.getInstance(project).isInjectedFragment(anchorStatement.getContainingFile())) {
|
||||
topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
|
||||
} else {
|
||||
topLevelEditor = editor;
|
||||
}
|
||||
|
||||
final IntroduceVariableSettings settings;
|
||||
final PsiElement chosenAnchor;
|
||||
if (choice != null) {
|
||||
chosenAnchor = chooseAnchor(allOccurences, choice == OccurrencesChooser.ReplaceChoice.NO_WRITE, nonWrite, anchorStatementIfAll, anchorStatement);
|
||||
settings = getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor, choice);
|
||||
}
|
||||
else {
|
||||
settings = getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, anchorStatement, choice);
|
||||
chosenAnchor = chooseAnchor(settings.isReplaceAllOccurrences(), hasWriteAccess, nonWrite, anchorStatementIfAll, anchorStatement);
|
||||
}
|
||||
if (!settings.isOK()) {
|
||||
wasSucceed[0] = false;
|
||||
return;
|
||||
}
|
||||
typeSelectorManager.setAllOccurrences(allOccurences);
|
||||
final TypeExpression expression = new TypeExpression(project, allOccurences ? typeSelectorManager.getTypesForAll() : typeSelectorManager.getTypesForOne());
|
||||
final RangeMarker exprMarker = topLevelEditor.getDocument().createRangeMarker(expr.getTextRange());
|
||||
final SuggestedNameInfo suggestedName = getSuggestedName(settings.getSelectedType(), expr, chosenAnchor);
|
||||
final List<RangeMarker> occurrenceMarkers = new ArrayList<RangeMarker>();
|
||||
final boolean noWrite = choice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
if (allOccurences || (noWrite && !PsiUtil.isAccessedForWriting(occurrence))) {
|
||||
occurrenceMarkers.add(topLevelEditor.getDocument().createRangeMarker(occurrence.getTextRange()));
|
||||
final boolean replaceAll = choice == OccurrencesChooser.ReplaceChoice.ALL || choice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
|
||||
typeSelectorManager.setAllOccurrences(replaceAll);
|
||||
|
||||
final PsiElement chosenAnchor =
|
||||
chooseAnchor(replaceAll, choice == OccurrencesChooser.ReplaceChoice.NO_WRITE, nonWrite, anchorStatementIfAll, anchorStatement);
|
||||
final IntroduceVariableSettings settings =
|
||||
getSettings(project, editor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor, choice);
|
||||
|
||||
final boolean cantChangeFinalModifier = (hasWriteAccess || inFinalContext) && choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
|
||||
final boolean noWrite = choice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
|
||||
final List<PsiExpression> allOccurrences = new ArrayList<PsiExpression>();
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
if (expr.equals(occurrence) && expr.getParent() instanceof PsiExpressionStatement) continue;
|
||||
if (choice == OccurrencesChooser.ReplaceChoice.ALL || (noWrite && !PsiUtil.isAccessedForWriting(occurrence)) || expr.equals(occurrence)) {
|
||||
allOccurrences.add(occurrence);
|
||||
}
|
||||
}
|
||||
myInplaceIntroducer = new JavaVariableInplaceIntroducer(project,
|
||||
settings,
|
||||
chosenAnchor,
|
||||
editor, expr, cantChangeFinalModifier,
|
||||
allOccurrences.toArray(new PsiExpression[allOccurrences.size()]),
|
||||
typeSelectorManager,
|
||||
REFACTORING_NAME);
|
||||
if (myInplaceIntroducer.startInplaceIntroduceTemplate()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final RefactoringEventData beforeData = new RefactoringEventData();
|
||||
beforeData.addElement(expr);
|
||||
project.getMessageBus()
|
||||
.syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, beforeData);
|
||||
final String expressionText = expr.getText();
|
||||
final Runnable runnable = introduce(project, expr, topLevelEditor, chosenAnchor, occurrences, settings, variable);
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
project,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
final Editor topLevelEditor ;
|
||||
if (!InjectedLanguageManager.getInstance(project).isInjectedFragment(anchorStatement.getContainingFile())) {
|
||||
topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
|
||||
} else {
|
||||
topLevelEditor = editor;
|
||||
}
|
||||
|
||||
PsiVariable variable = null;
|
||||
try {
|
||||
ApplicationManager.getApplication().runWriteAction(runnable);
|
||||
final IntroduceVariableSettings settings =
|
||||
getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, anchorStatement, choice);
|
||||
if (!settings.isOK()) {
|
||||
wasSucceed[0] = false;
|
||||
return;
|
||||
}
|
||||
|
||||
final RefactoringEventData beforeData = new RefactoringEventData();
|
||||
beforeData.addElement(expr);
|
||||
project.getMessageBus()
|
||||
.syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, beforeData);
|
||||
|
||||
final PsiElement chosenAnchor =
|
||||
chooseAnchor(settings.isReplaceAllOccurrences(), hasWriteAccess, nonWrite, anchorStatementIfAll, anchorStatement);
|
||||
|
||||
variable = ApplicationManager.getApplication().runWriteAction(
|
||||
introduce(project, expr, topLevelEditor, chosenAnchor, occurrences, settings));
|
||||
}
|
||||
finally {
|
||||
final RefactoringEventData afterData = new RefactoringEventData();
|
||||
final SmartPsiElementPointer<PsiVariable> pointer = variable.get();
|
||||
afterData.addElement(pointer != null ? pointer.getElement() : null);
|
||||
afterData.addElement(variable);
|
||||
project.getMessageBus()
|
||||
.syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, afterData);
|
||||
}
|
||||
|
||||
if (isInplaceAvailableOnDataContext) {
|
||||
final PsiVariable elementToRename = variable.get().getElement();
|
||||
if (elementToRename != null) {
|
||||
topLevelEditor.getCaretModel().moveToOffset(elementToRename.getTextOffset());
|
||||
final boolean cantChangeFinalModifier = (hasWriteAccess || inFinalContext) && choice == OccurrencesChooser.ReplaceChoice.ALL;
|
||||
final JavaVariableInplaceIntroducer renamer =
|
||||
new JavaVariableInplaceIntroducer(project, expression, topLevelEditor, elementToRename, cantChangeFinalModifier,
|
||||
typeSelectorManager.getTypesForAll().length > 1, exprMarker, occurrenceMarkers,
|
||||
REFACTORING_NAME);
|
||||
renamer.initInitialText(expressionText);
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(topLevelEditor.getDocument());
|
||||
renamer.performInplaceRefactoring(new LinkedHashSet<String>(Arrays.asList(suggestedName.names)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, REFACTORING_NAME, null);
|
||||
}
|
||||
@@ -724,16 +720,25 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
callback.pass(null);
|
||||
}
|
||||
else {
|
||||
OccurrencesChooser.<PsiExpression>simpleChooser(editor).showChooser(callback, occurrencesMap);
|
||||
OccurrencesChooser.ReplaceChoice choice = getOccurrencesChoice();
|
||||
if (choice != null) {
|
||||
callback.pass(choice);
|
||||
} else {
|
||||
OccurrencesChooser.<PsiExpression>simpleChooser(editor).showChooser(callback, occurrencesMap);
|
||||
}
|
||||
}
|
||||
return wasSucceed[0];
|
||||
}
|
||||
|
||||
protected OccurrencesChooser.ReplaceChoice getOccurrencesChoice() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PsiElement chooseAnchor(boolean allOccurences,
|
||||
boolean hasWriteAccess,
|
||||
List<PsiExpression> nonWrite,
|
||||
PsiElement anchorStatementIfAll,
|
||||
PsiElement anchorStatement) {
|
||||
protected static PsiElement chooseAnchor(boolean allOccurences,
|
||||
boolean hasWriteAccess,
|
||||
List<PsiExpression> nonWrite,
|
||||
PsiElement anchorStatementIfAll,
|
||||
PsiElement anchorStatement) {
|
||||
if (allOccurences) {
|
||||
if (hasWriteAccess) {
|
||||
return RefactoringUtil.getAnchorElementForMultipleExpressions(nonWrite.toArray(new PsiExpression[nonWrite.size()]), null);
|
||||
@@ -792,13 +797,12 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
return parent3 instanceof JspHolderMethod;
|
||||
}
|
||||
|
||||
private static Runnable introduce(final Project project,
|
||||
final PsiExpression expr,
|
||||
final Editor editor,
|
||||
final PsiElement anchorStatement,
|
||||
final PsiExpression[] occurrences,
|
||||
final IntroduceVariableSettings settings,
|
||||
final Ref<SmartPsiElementPointer<PsiVariable>> variable) {
|
||||
public static Computable<PsiVariable> introduce(final Project project,
|
||||
final PsiExpression expr,
|
||||
final Editor editor,
|
||||
final PsiElement anchorStatement,
|
||||
final PsiExpression[] occurrences,
|
||||
final IntroduceVariableSettings settings) {
|
||||
final PsiElement container = anchorStatement.getParent();
|
||||
PsiElement child = anchorStatement;
|
||||
if (!RefactoringUtil.isLoopOrIf(container)) {
|
||||
@@ -837,8 +841,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
|
||||
final PsiCodeBlock newDeclarationScope = PsiTreeUtil.getParentOfType(container, PsiCodeBlock.class, false);
|
||||
final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(settings.getEnteredName(), newDeclarationScope);
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
return new Computable<PsiVariable>() {
|
||||
@Override
|
||||
public PsiVariable compute() {
|
||||
try {
|
||||
PsiStatement statement = null;
|
||||
final boolean isInsideLoop = RefactoringUtil.isLoopOrIf(container);
|
||||
@@ -913,11 +918,12 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
declaration = (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(declaration);
|
||||
PsiVariable var = (PsiVariable) declaration.getDeclaredElements()[0];
|
||||
PsiUtil.setModifierProperty(var, PsiModifier.FINAL, settings.isDeclareFinal());
|
||||
variable.set(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(var));
|
||||
fieldConflictsResolver.fix();
|
||||
return var;
|
||||
} catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private PsiDeclarationStatement addDeclaration(PsiDeclarationStatement declaration, PsiExpression initializer) {
|
||||
@@ -1165,6 +1171,6 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
|
||||
@Override
|
||||
public AbstractInplaceIntroducer getInplaceIntroducer() {
|
||||
return null;
|
||||
return myInplaceIntroducer;
|
||||
}
|
||||
}
|
||||
|
||||
+176
-154
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -21,7 +21,6 @@ import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.impl.StartMarkAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
@@ -30,87 +29,70 @@ import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.scope.processor.VariablesProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer;
|
||||
import com.intellij.refactoring.rename.ResolveSnapshotProvider;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
|
||||
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.ui.NonFocusableCheckBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 12/8/10
|
||||
*/
|
||||
public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<PsiExpression> {
|
||||
protected final Project myProject;
|
||||
private final SmartPsiElementPointer<PsiDeclarationStatement> myPointer;
|
||||
public class JavaVariableInplaceIntroducer extends AbstractJavaInplaceIntroducer {
|
||||
|
||||
private SmartPsiElementPointer<PsiDeclarationStatement> myPointer;
|
||||
|
||||
private JCheckBox myCanBeFinalCb;
|
||||
|
||||
private IntroduceVariableSettings mySettings;
|
||||
private SmartPsiElementPointer<PsiElement> myChosenAnchor;
|
||||
private final boolean myCantChangeFinalModifier;
|
||||
private final String myTitle;
|
||||
private String myExpressionText;
|
||||
protected final SmartTypePointer myDefaultType;
|
||||
protected final TypeExpression myExpression;
|
||||
|
||||
private boolean myHasTypeSuggestion;
|
||||
private ResolveSnapshotProvider.ResolveSnapshot myConflictResolver;
|
||||
private TypeExpression myExpression;
|
||||
private boolean myReplaceSelf;
|
||||
private boolean myDeleteSelf = true;
|
||||
|
||||
public JavaVariableInplaceIntroducer(final Project project,
|
||||
final TypeExpression expression,
|
||||
final Editor editor,
|
||||
@NotNull final PsiVariable elementToRename,
|
||||
IntroduceVariableSettings settings, PsiElement chosenAnchor, final Editor editor,
|
||||
final PsiExpression expr,
|
||||
final boolean cantChangeFinalModifier,
|
||||
final boolean hasTypeSuggestion,
|
||||
final RangeMarker exprMarker,
|
||||
final List<RangeMarker> occurrenceMarkers,
|
||||
final PsiExpression[] occurrences,
|
||||
final TypeSelectorManagerImpl selectorManager,
|
||||
final String title) {
|
||||
super(elementToRename, editor, project, title, new PsiExpression[0], null);
|
||||
myProject = project;
|
||||
super(project, editor, RefactoringUtil.outermostParenthesizedExpression(expr), null, occurrences, selectorManager, title);
|
||||
mySettings = settings;
|
||||
myChosenAnchor = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(chosenAnchor);
|
||||
myCantChangeFinalModifier = cantChangeFinalModifier;
|
||||
myHasTypeSuggestion = selectorManager.getTypesForAll().length > 1;
|
||||
myTitle = title;
|
||||
setExprMarker(exprMarker);
|
||||
setOccurrenceMarkers(occurrenceMarkers);
|
||||
final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(elementToRename, PsiDeclarationStatement.class);
|
||||
myPointer = declarationStatement != null ? SmartPointerManager.getInstance(project).createSmartPsiElementPointer(declarationStatement) : null;
|
||||
editor.putUserData(ReassignVariableUtil.DECLARATION_KEY, myPointer);
|
||||
if (occurrenceMarkers != null) {
|
||||
final ArrayList<RangeMarker> rangeMarkers = new ArrayList<RangeMarker>(occurrenceMarkers);
|
||||
rangeMarkers.add(exprMarker);
|
||||
editor.putUserData(ReassignVariableUtil.OCCURRENCES_KEY,
|
||||
rangeMarkers.toArray(new RangeMarker[rangeMarkers.size()]));
|
||||
}
|
||||
myExpression = expression;
|
||||
final PsiType defaultType = elementToRename.getType();
|
||||
myDefaultType = SmartTypePointerManager.getInstance(project).createSmartTypePointer(defaultType);
|
||||
setAdvertisementText(getAdvertisementText(declarationStatement, defaultType, hasTypeSuggestion));
|
||||
}
|
||||
myExpression = new TypeExpression(myProject, isReplaceAllOccurrences()
|
||||
? myTypeSelectorManager.getTypesForAll()
|
||||
: myTypeSelectorManager.getTypesForOne());
|
||||
|
||||
public void initInitialText(String text) {
|
||||
myExpressionText = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StartMarkAction startRename() throws StartMarkAction.AlreadyStartedException {
|
||||
return StartMarkAction.start(myEditor, myProject, getCommandName());
|
||||
final List<RangeMarker> rangeMarkers = getOccurrenceMarkers();
|
||||
editor.putUserData(ReassignVariableUtil.OCCURRENCES_KEY,
|
||||
rangeMarkers.toArray(new RangeMarker[rangeMarkers.size()]));
|
||||
myReplaceSelf = myExpr.getParent() instanceof PsiExpressionStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +104,7 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<Psi
|
||||
|
||||
@Nullable
|
||||
protected PsiVariable getVariable() {
|
||||
final PsiDeclarationStatement declarationStatement = myPointer.getElement();
|
||||
final PsiDeclarationStatement declarationStatement = myPointer != null ? myPointer.getElement() : null;
|
||||
if (declarationStatement != null) {
|
||||
PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
|
||||
return declaredElements.length == 0 ? null : (PsiVariable)declaredElements[0];
|
||||
@@ -131,101 +113,94 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<Psi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
try {
|
||||
if (success) {
|
||||
final Document document = myEditor.getDocument();
|
||||
@Nullable final PsiVariable psiVariable = getVariable();
|
||||
if (psiVariable == null) {
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(psiVariable.isValid());
|
||||
TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), myDefaultType.getType());
|
||||
if (myCanBeFinalCb != null) {
|
||||
JavaRefactoringSettings.getInstance().INTRODUCE_LOCAL_CREATE_FINALS = psiVariable.hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
adjustLine(psiVariable, document);
|
||||
protected String getActionName() {
|
||||
return "IntroduceVariable";
|
||||
}
|
||||
|
||||
int startOffset = getExprMarker() != null && getExprMarker().isValid() ? getExprMarker().getStartOffset() : psiVariable.getTextOffset();
|
||||
final PsiFile file = psiVariable.getContainingFile();
|
||||
final PsiReference referenceAt = file.findReferenceAt(startOffset);
|
||||
if (referenceAt != null && referenceAt.resolve() instanceof PsiVariable) {
|
||||
startOffset = referenceAt.getElement().getTextRange().getEndOffset();
|
||||
}
|
||||
else {
|
||||
final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(psiVariable, PsiDeclarationStatement.class);
|
||||
if (declarationStatement != null) {
|
||||
startOffset = declarationStatement.getTextRange().getEndOffset();
|
||||
}
|
||||
}
|
||||
myEditor.getCaretModel().moveToOffset(startOffset);
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
if (psiVariable.getInitializer() != null) {
|
||||
appendTypeCasts(getOccurrenceMarkers(), file, myProject, psiVariable);
|
||||
}
|
||||
if (myConflictResolver != null && myInsertedName != null && isIdentifier(myInsertedName, psiVariable.getLanguage())) {
|
||||
myConflictResolver.apply(psiVariable.getName());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
RangeMarker exprMarker = getExprMarker();
|
||||
if (exprMarker != null && exprMarker.isValid()) {
|
||||
myEditor.getCaretModel().moveToOffset(exprMarker.getStartOffset());
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
}
|
||||
if (myExpressionText != null) {
|
||||
if (!ReadonlyStatusHandler.ensureDocumentWritable(myProject, InjectedLanguageUtil.getTopLevelEditor(myEditor).getDocument())) return;
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
final PsiDeclarationStatement element = myPointer.getElement();
|
||||
if (element != null) {
|
||||
final PsiElement[] vars = element.getDeclaredElements();
|
||||
if (vars.length > 0 && vars[0] instanceof PsiVariable) {
|
||||
final PsiFile containingFile = element.getContainingFile();
|
||||
//todo pull up method restore state
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
|
||||
final RangeMarker exprMarker = getExprMarker();
|
||||
if (exprMarker != null) {
|
||||
myExpr = AbstractJavaInplaceIntroducer.restoreExpression(containingFile, (PsiVariable)vars[0], elementFactory, exprMarker, myExpressionText);
|
||||
if (myExpr != null && myExpr.isPhysical()) {
|
||||
myExprMarker = createMarker(myExpr);
|
||||
}
|
||||
}
|
||||
List<RangeMarker> markers = getOccurrenceMarkers();
|
||||
for (RangeMarker occurrenceMarker : markers) {
|
||||
if (getExprMarker() != null && occurrenceMarker.getStartOffset() == getExprMarker().getStartOffset() && myExpr != null) {
|
||||
continue;
|
||||
}
|
||||
AbstractJavaInplaceIntroducer
|
||||
.restoreExpression(containingFile, (PsiVariable)vars[0], elementFactory, occurrenceMarker, myExpressionText);
|
||||
}
|
||||
final PsiExpression initializer = ((PsiVariable)vars[0]).getInitializer();
|
||||
if (initializer != null && Comparing.strEqual(initializer.getText(), myExpressionText) && myExpr == null) {
|
||||
element.replace(JavaPsiFacade.getInstance(myProject).getElementFactory().createStatementFromText(myExpressionText, element));
|
||||
} else {
|
||||
element.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myEditor.putUserData(ReassignVariableUtil.DECLARATION_KEY, null);
|
||||
for (RangeMarker occurrenceMarker : getOccurrenceMarkers()) {
|
||||
occurrenceMarker.dispose();
|
||||
}
|
||||
myEditor.putUserData(ReassignVariableUtil.OCCURRENCES_KEY, null);
|
||||
if (getExprMarker() != null) getExprMarker().dispose();
|
||||
@Override
|
||||
protected void restoreState(PsiVariable psiField) {
|
||||
if (myDeleteSelf) return;
|
||||
super.restoreState(psiField);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean ensureValid() {
|
||||
final PsiVariable variable = getVariable();
|
||||
return variable != null && isIdentifier(getInputName(), variable.getLanguage());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCleanup() {
|
||||
super.performCleanup();
|
||||
super.restoreState(getVariable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteTemplateField(PsiVariable variable) {
|
||||
if (!myDeleteSelf) return;
|
||||
if (myReplaceSelf) {
|
||||
variable.replace(variable.getInitializer());
|
||||
} else {
|
||||
super.deleteTemplateField(variable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performIntroduce() {
|
||||
final PsiVariable psiVariable = getVariable();
|
||||
if (psiVariable == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), myTypeSelectorManager.getDefaultType());
|
||||
if (myCanBeFinalCb != null) {
|
||||
JavaRefactoringSettings.getInstance().INTRODUCE_LOCAL_CREATE_FINALS = psiVariable.hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
final Document document = myEditor.getDocument();
|
||||
LOG.assertTrue(psiVariable.isValid());
|
||||
adjustLine(psiVariable, document);
|
||||
|
||||
int startOffset = getExprMarker() != null && getExprMarker().isValid() ? getExprMarker().getStartOffset() : psiVariable.getTextOffset();
|
||||
final PsiFile file = psiVariable.getContainingFile();
|
||||
final PsiReference referenceAt = file.findReferenceAt(startOffset);
|
||||
if (referenceAt != null && referenceAt.resolve() instanceof PsiVariable) {
|
||||
startOffset = referenceAt.getElement().getTextRange().getEndOffset();
|
||||
}
|
||||
else {
|
||||
final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(psiVariable, PsiDeclarationStatement.class);
|
||||
if (declarationStatement != null) {
|
||||
startOffset = declarationStatement.getTextRange().getEndOffset();
|
||||
}
|
||||
}
|
||||
|
||||
myEditor.getCaretModel().moveToOffset(startOffset);
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
if (psiVariable.getInitializer() != null) {
|
||||
appendTypeCasts(getOccurrenceMarkers(), file, myProject, psiVariable);
|
||||
}
|
||||
if (myConflictResolver != null && myInsertedName != null && isIdentifier(myInsertedName, psiVariable.getLanguage())) {
|
||||
myConflictResolver.apply(psiVariable.getName());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceAllOccurrences() {
|
||||
return mySettings.isReplaceAllOccurrences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceAllOccurrences(boolean allOccurrences) {}
|
||||
|
||||
@Override
|
||||
protected boolean startsOnTheSameElement(RefactoringActionHandler handler, PsiElement element) {
|
||||
return handler instanceof IntroduceVariableHandler && super.startsOnTheSameElement(handler, element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected JComponent getComponent() {
|
||||
@@ -265,8 +240,27 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<Psi
|
||||
}
|
||||
|
||||
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
|
||||
final PsiTypeElement typeElement = getVariable().getTypeElement();
|
||||
builder.replaceElement(typeElement, "Variable_Type", AbstractJavaInplaceIntroducer.createExpression(myExpression, typeElement.getText()), true, true);
|
||||
final PsiVariable variable = getVariable();
|
||||
if (variable != null) {
|
||||
final PsiTypeElement typeElement = variable.getTypeElement();
|
||||
if (typeElement != null) {
|
||||
builder.replaceElement(typeElement, "Variable_Type", AbstractJavaInplaceIntroducer.createExpression(myExpression, typeElement.getText()), true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) {
|
||||
if (isReplaceAllOccurrences()) {
|
||||
for (PsiExpression expression : getOccurrences()) {
|
||||
LOG.assertTrue(expression.isValid(), expression.getText());
|
||||
stringUsages.add(Pair.<PsiElement, TextRange>create(expression, new TextRange(0, expression.getTextLength())));
|
||||
}
|
||||
} else if (getExpr() != null && !myReplaceSelf) {
|
||||
final PsiExpression expr = getExpr();
|
||||
LOG.assertTrue(expr.isValid(), expr.getText());
|
||||
stringUsages.add(Pair.<PsiElement, TextRange>create(expr, new TextRange(0, expr.getTextLength())));
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendTypeCasts(List<RangeMarker> occurrenceMarkers,
|
||||
@@ -353,21 +347,49 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<Psi
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected String getTitle() {
|
||||
return myTitle;
|
||||
@Override
|
||||
protected PsiVariable createFieldToStartTemplateOn(String[] names, PsiType psiType) {
|
||||
final PsiVariable variable = ApplicationManager.getApplication().runWriteAction(
|
||||
IntroduceVariableBase.introduce(myProject, myExpr, myEditor, myChosenAnchor.getElement(), getOccurrences(), mySettings));
|
||||
PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myEditor.getDocument());
|
||||
final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(variable, PsiDeclarationStatement.class);
|
||||
myPointer = declarationStatement != null ? SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(declarationStatement) : null;
|
||||
myEditor.putUserData(ReassignVariableUtil.DECLARATION_KEY, myPointer);
|
||||
setAdvertisementText(getAdvertisementText(declarationStatement, variable.getType(), myHasTypeSuggestion));
|
||||
final PsiIdentifier identifier = variable.getNameIdentifier();
|
||||
if (identifier != null) {
|
||||
myEditor.getCaretModel().moveToOffset(identifier.getTextOffset());
|
||||
}
|
||||
try {
|
||||
myDeleteSelf = false;
|
||||
restoreState(variable);
|
||||
}
|
||||
finally {
|
||||
myDeleteSelf = true;
|
||||
}
|
||||
initOccurrencesMarkers();
|
||||
return variable;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static String getAdvertisementText(final boolean hasTypeSuggestion) {
|
||||
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
|
||||
if (hasTypeSuggestion) {
|
||||
final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable");
|
||||
if (shortcuts.length > 0) {
|
||||
return "Press " + shortcuts[0] + " to change type";
|
||||
@Override
|
||||
protected int getCaretOffset() {
|
||||
final PsiVariable variable = getVariable();
|
||||
if (variable != null) {
|
||||
final PsiIdentifier identifier = variable.getNameIdentifier();
|
||||
if (identifier != null) {
|
||||
return identifier.getTextOffset();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return super.getCaretOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] suggestNames(PsiType defaultType, String propName) {
|
||||
return IntroduceVariableBase.getSuggestedName(defaultType, myExpr).names;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VariableKind getVariableKind() {
|
||||
return VariableKind.LOCAL_VARIABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class C {
|
||||
{
|
||||
new <caret>C();
|
||||
new C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class C {
|
||||
{
|
||||
C c = new C();
|
||||
c;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new C();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
{
|
||||
final C c1 = new C();
|
||||
C c = c1;
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
c1;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class C {
|
||||
{
|
||||
Object c1 = new C();
|
||||
C c = (C) c1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class C {
|
||||
{
|
||||
Integer c1 = (Integer) new C();
|
||||
C c = (C) c1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = <caret>new C();
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = <caret>new C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class C {
|
||||
{
|
||||
C expr = new C();
|
||||
C c = expr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
(new <caret>C());
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C expr = new C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
{
|
||||
int[] a = new int[1];
|
||||
a[1] = 42;
|
||||
System.out.println(a<caret>[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class C {
|
||||
{
|
||||
int[] a = new int[1];
|
||||
a[1] = 42;
|
||||
int x = a[1];
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Bar {}
|
||||
class Foo {
|
||||
static Bar bar;
|
||||
}
|
||||
class C {
|
||||
{
|
||||
Bar b = Foo.ba<caret>r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class Bar {}
|
||||
class Foo {
|
||||
static Bar bar;
|
||||
}
|
||||
class C {
|
||||
{
|
||||
Bar expr = Foo.bar;
|
||||
Bar b = expr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C {
|
||||
{
|
||||
C c = new <caret>C();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class C {
|
||||
{
|
||||
C
|
||||
|
||||
c1 = new C();
|
||||
C c = c1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
{
|
||||
int[] a = new int[1];
|
||||
a[1] = 42;
|
||||
System.out.println(a<caret>[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class C {
|
||||
{
|
||||
int[] a = new int[1];
|
||||
int x = a[1];
|
||||
x = 42;
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,6 +3,6 @@ import java.io.File;
|
||||
class Test {
|
||||
java.io.File[] get() {return null;}
|
||||
{
|
||||
File[] files = get();
|
||||
File[] i = get();
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 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.
|
||||
@@ -72,6 +72,10 @@ public abstract class AbstractJavaInplaceIntroduceTest extends AbstractInplaceIn
|
||||
@Override
|
||||
protected AbstractInplaceIntroducer invokeRefactoring() {
|
||||
final MyIntroduceHandler introduceHandler = createIntroduceHandler();
|
||||
return invokeRefactoring(introduceHandler);
|
||||
}
|
||||
|
||||
protected AbstractInplaceIntroducer invokeRefactoring(MyIntroduceHandler introduceHandler) {
|
||||
final PsiExpression expression = getExpressionFromEditor();
|
||||
if (expression != null) {
|
||||
introduceHandler.invokeImpl(LightPlatformTestCase.getProject(), expression, getEditor());
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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;
|
||||
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiLiteralExpression;
|
||||
import com.intellij.psi.PsiLocalVariable;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
|
||||
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableHandler;
|
||||
import com.intellij.testFramework.MapDataContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class InplaceIntroduceVariableTest extends AbstractJavaInplaceIntroduceTest {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiExpression getExpressionFromEditor() {
|
||||
final PsiExpression expression = super.getExpressionFromEditor();
|
||||
if (expression != null) {
|
||||
return expression;
|
||||
}
|
||||
final PsiExpression expr = PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiExpression.class);
|
||||
return expr instanceof PsiLiteralExpression ? expr : null;
|
||||
}
|
||||
|
||||
public void testFromExpression() throws Exception {
|
||||
doTest(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) {
|
||||
type("expr");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testRanges() throws Exception {
|
||||
doTest(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) {
|
||||
type("expr");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testFromParenthesis() throws Exception {
|
||||
doTest(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) {
|
||||
type("expr");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testCast() throws Exception {
|
||||
doTestTypeChange("Integer");
|
||||
}
|
||||
|
||||
public void testCastToObject() throws Exception {
|
||||
doTestTypeChange("Object");
|
||||
}
|
||||
|
||||
public void testEscapePosition() {
|
||||
doTestStopEditing(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer introducer) {
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_ESCAPE);
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_ESCAPE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testEscapePositionIfTyped() {
|
||||
doTestStopEditing(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer introducer) {
|
||||
type("fooBar");
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_ESCAPE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testWritable() throws Exception {
|
||||
doTestReplaceChoice(OccurrencesChooser.ReplaceChoice.ALL);
|
||||
}
|
||||
|
||||
public void testNoWritable() throws Exception {
|
||||
doTestReplaceChoice(OccurrencesChooser.ReplaceChoice.NO_WRITE);
|
||||
}
|
||||
|
||||
public void testAllInsertFinal() throws Exception {
|
||||
doTestReplaceChoice(OccurrencesChooser.ReplaceChoice.ALL);
|
||||
}
|
||||
|
||||
public void testAllIncomplete() throws Exception {
|
||||
doTestReplaceChoice(OccurrencesChooser.ReplaceChoice.ALL);
|
||||
}
|
||||
|
||||
public void testStopEditing() {
|
||||
doTestStopEditing(new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer introducer) {
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT);
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_ENTER);
|
||||
invokeEditorAction(IdeActions.ACTION_EDITOR_ENTER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doTestStopEditing(Pass<AbstractInplaceIntroducer> pass) {
|
||||
String name = getTestName(true);
|
||||
configureByFile(getBasePath() + name + getExtension());
|
||||
final boolean enabled = getEditor().getSettings().isVariableInplaceRenameEnabled();
|
||||
try {
|
||||
TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(true);
|
||||
|
||||
final AbstractInplaceIntroducer introducer = invokeRefactoring();
|
||||
pass.pass(introducer);
|
||||
checkResultByFile(getBasePath() + name + "_after" + getExtension());
|
||||
}
|
||||
finally {
|
||||
TemplateState state = TemplateManagerImpl.getTemplateState(getEditor());
|
||||
if (state != null) {
|
||||
state.gotoEnd(true);
|
||||
}
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestTypeChange(final String newType) {
|
||||
final Pass<AbstractInplaceIntroducer> typeChanger = new Pass<AbstractInplaceIntroducer>() {
|
||||
@Override
|
||||
public void pass(AbstractInplaceIntroducer inplaceIntroduceFieldPopup) {
|
||||
type(newType);
|
||||
}
|
||||
};
|
||||
String name = getTestName(true);
|
||||
configureByFile(getBasePath() + name + getExtension());
|
||||
final boolean enabled = getEditor().getSettings().isVariableInplaceRenameEnabled();
|
||||
try {
|
||||
TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(true);
|
||||
|
||||
final AbstractInplaceIntroducer introducer = invokeRefactoring();
|
||||
TemplateState state = TemplateManagerImpl.getTemplateState(getEditor());
|
||||
assert state != null;
|
||||
state.previousTab();
|
||||
typeChanger.pass(introducer);
|
||||
state.gotoEnd(false);
|
||||
checkResultByFile(getBasePath() + name + "_after" + getExtension());
|
||||
}
|
||||
finally {
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestReplaceChoice(OccurrencesChooser.ReplaceChoice choice) {
|
||||
doTestReplaceChoice(choice, null);
|
||||
}
|
||||
|
||||
private void doTestReplaceChoice(OccurrencesChooser.ReplaceChoice choice, Pass<AbstractInplaceIntroducer> pass) {
|
||||
String name = getTestName(true);
|
||||
configureByFile(getBasePath() + name + getExtension());
|
||||
final boolean enabled = getEditor().getSettings().isVariableInplaceRenameEnabled();
|
||||
try {
|
||||
TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(true);
|
||||
|
||||
MyIntroduceHandler handler = createIntroduceHandler();
|
||||
((MyIntroduceVariableHandler)handler).setChoice(choice);
|
||||
final AbstractInplaceIntroducer introducer = invokeRefactoring(handler);
|
||||
if (pass != null) {
|
||||
pass.pass(introducer);
|
||||
}
|
||||
TemplateState state = TemplateManagerImpl.getTemplateState(getEditor());
|
||||
assert state != null;
|
||||
state.gotoEnd(false);
|
||||
checkResultByFile(getBasePath() + name + "_after" + getExtension());
|
||||
}
|
||||
finally {
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private static void invokeEditorAction(String actionId) {
|
||||
EditorActionManager.getInstance().getActionHandler(actionId)
|
||||
.execute(getEditor(), getEditor().getCaretModel().getCurrentCaret(), new MapDataContext());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/refactoring/inplaceIntroduceVariable/";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MyIntroduceHandler createIntroduceHandler() {
|
||||
return new MyIntroduceVariableHandler();
|
||||
}
|
||||
|
||||
public static class MyIntroduceVariableHandler extends IntroduceVariableHandler implements MyIntroduceHandler {
|
||||
private OccurrencesChooser.ReplaceChoice myChoice = null;
|
||||
|
||||
public void setChoice(OccurrencesChooser.ReplaceChoice choice) {
|
||||
myChoice = choice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean invokeImpl(Project project, @NotNull PsiExpression selectedExpr, Editor editor) {
|
||||
return super.invokeImpl(project, selectedExpr, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean invokeImpl(Project project, PsiLocalVariable localVariable, Editor editor) {
|
||||
return super.invokeImpl(project, localVariable, editor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OccurrencesChooser.ReplaceChoice getOccurrencesChoice() {
|
||||
return myChoice;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInplaceAvailableInTestMode() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -473,10 +473,8 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
|
||||
final RangeMarker exprMarker = getExprMarker();
|
||||
if (exprMarker != null) {
|
||||
myExpr = restoreExpression(containingFile, psiField, exprMarker, myExprText);
|
||||
if (myExpr != null && myExpr.isPhysical()) {
|
||||
myExprMarker = createMarker(myExpr);
|
||||
}
|
||||
}
|
||||
|
||||
if (myLocalMarker != null) {
|
||||
final PsiElement refVariableElement = containingFile.findElementAt(myLocalMarker.getStartOffset());
|
||||
if (refVariableElement != null) {
|
||||
@@ -509,6 +507,9 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
|
||||
}
|
||||
}
|
||||
|
||||
if (myExpr != null && myExpr.isPhysical()) {
|
||||
myExprMarker = createMarker(myExpr);
|
||||
}
|
||||
myOccurrenceMarkers = null;
|
||||
deleteTemplateField(psiField);
|
||||
}
|
||||
@@ -523,24 +524,7 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
|
||||
|
||||
@Override
|
||||
protected boolean performRefactoring() {
|
||||
final String newName = getInputName();
|
||||
if (getLocalVariable() == null && myExpr == null ||
|
||||
newName == null ||
|
||||
getLocalVariable() != null && !getLocalVariable().isValid() ||
|
||||
myExpr != null && !myExpr.isValid()) {
|
||||
super.moveOffsetAfter(false);
|
||||
return false;
|
||||
}
|
||||
if (getLocalVariable() != null) {
|
||||
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
||||
@Override
|
||||
protected void run(Result result) throws Throwable {
|
||||
getLocalVariable().setName(myLocalName);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
if (!isIdentifier(newName, myExpr != null ? myExpr.getLanguage() : getLocalVariable().getLanguage())) return false;
|
||||
if (!ensureValid()) return false;
|
||||
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -562,6 +546,28 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean ensureValid() {
|
||||
final String newName = getInputName();
|
||||
if (getLocalVariable() == null && myExpr == null ||
|
||||
newName == null ||
|
||||
getLocalVariable() != null && !getLocalVariable().isValid() ||
|
||||
myExpr != null && !myExpr.isValid()) {
|
||||
super.moveOffsetAfter(false);
|
||||
return false;
|
||||
}
|
||||
if (getLocalVariable() != null) {
|
||||
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
||||
@Override
|
||||
protected void run(Result result) throws Throwable {
|
||||
getLocalVariable().setName(myLocalName);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
if (!isIdentifier(newName, myExpr != null ? myExpr.getLanguage() : getLocalVariable().getLanguage())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
if (getLocalVariable() != null && getLocalVariable().isValid()) {
|
||||
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -639,6 +639,11 @@ public abstract class InplaceRefactoring {
|
||||
|
||||
protected abstract boolean performRefactoring();
|
||||
|
||||
/**
|
||||
* if brokenOff but not canceled
|
||||
*/
|
||||
protected void performCleanup() {}
|
||||
|
||||
private void addVariable(final PsiReference reference,
|
||||
final PsiElement selectedElement,
|
||||
final TemplateBuilderImpl builder,
|
||||
@@ -847,6 +852,8 @@ public abstract class InplaceRefactoring {
|
||||
super.templateFinished(template, brokenOff);
|
||||
if (!brokenOff) {
|
||||
bind = performRefactoring();
|
||||
} else {
|
||||
performCleanup();
|
||||
}
|
||||
moveOffsetAfter(!brokenOff);
|
||||
}
|
||||
|
||||
+9
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -30,6 +30,10 @@ public abstract class AbstractInplaceIntroduceTest extends LightPlatformCodeInsi
|
||||
protected abstract String getBasePath();
|
||||
|
||||
protected void doTestEscape() {
|
||||
doTestEscape(null);
|
||||
}
|
||||
|
||||
protected void doTestEscape(Pass<AbstractInplaceIntroducer> pass) {
|
||||
String name = getTestName(true);
|
||||
configureByFile(getBasePath() + name + getExtension());
|
||||
final boolean enabled = getEditor().getSettings().isVariableInplaceRenameEnabled();
|
||||
@@ -37,7 +41,10 @@ public abstract class AbstractInplaceIntroduceTest extends LightPlatformCodeInsi
|
||||
TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(true);
|
||||
|
||||
invokeRefactoring();
|
||||
final AbstractInplaceIntroducer introducer = invokeRefactoring();
|
||||
if (pass != null) {
|
||||
pass.pass(introducer);
|
||||
}
|
||||
TemplateState state = TemplateManagerImpl.getTemplateState(getEditor());
|
||||
assert state != null;
|
||||
state.gotoEnd(true);
|
||||
|
||||
Reference in New Issue
Block a user