inplace: decouple introduces from rename (I)

This commit is contained in:
anna
2012-01-12 13:20:52 +01:00
parent 2662a93971
commit c83de1280e
19 changed files with 1050 additions and 914 deletions
@@ -172,33 +172,31 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
}
@Override
protected void moveOffsetAfter(boolean success) {
if (success) {
JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS = myMoveToAnotherClassCb.isSelected();
if (myMoveToAnotherClassCb.isSelected()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myEditor.putUserData(ACTIVE_INTRODUCE, InplaceIntroduceConstantPopup.this);
try {
final IntroduceConstantHandler constantHandler = new IntroduceConstantHandler();
final PsiLocalVariable localVariable = (PsiLocalVariable)getLocalVariable();
if (localVariable != null) {
constantHandler.invokeImpl(myProject, localVariable, myEditor);
}
else {
constantHandler.invokeImpl(myProject, myExpr, myEditor);
}
protected boolean performRefactoring() {
JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_MOVE_TO_ANOTHER_CLASS = myMoveToAnotherClassCb.isSelected();
if (myMoveToAnotherClassCb.isSelected()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myEditor.putUserData(ACTIVE_INTRODUCE, InplaceIntroduceConstantPopup.this);
try {
final IntroduceConstantHandler constantHandler = new IntroduceConstantHandler();
final PsiLocalVariable localVariable = (PsiLocalVariable)getLocalVariable();
if (localVariable != null) {
constantHandler.invokeImpl(myProject, localVariable, myEditor);
}
finally {
myEditor.putUserData(ACTIVE_INTRODUCE, null);
else {
constantHandler.invokeImpl(myProject, myExpr, myEditor);
}
}
});
return;
}
finally {
myEditor.putUserData(ACTIVE_INTRODUCE, null);
}
}
});
return false;
}
super.moveOffsetAfter(success);
return super.performRefactoring();
}
@Override
@@ -249,8 +247,4 @@ public class InplaceIntroduceConstantPopup extends AbstractInplaceIntroduceField
protected String getActionName() {
return "IntroduceConstant";
}
public String getCommandName() {
return IntroduceConstantHandler.REFACTORING_NAME;
}
}
@@ -185,11 +185,6 @@ public class InplaceIntroduceFieldPopup extends AbstractInplaceIntroduceFieldPop
return "IntroduceField";
}
@Override
protected String getCommandName() {
return IntroduceFieldHandler.REFACTORING_NAME;
}
public BaseExpressionToFieldHandler.InitializationPlace getInitializerPlace() {
return myIntroduceFieldPanel.getInitializerPlace();
}
@@ -287,10 +287,6 @@ public class InplaceIntroduceParameterPopup extends AbstractJavaInplaceIntroduce
return "IntroduceParameter";
}
public String getCommandName() {
return IntroduceParameterHandler.REFACTORING_NAME;
}
private void normalizeParameterIdxAccordingToRemovedParams(TIntArrayList parametersToRemove) {
parametersToRemove.forEach(new TIntProcedure() {
@Override
@@ -573,7 +573,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
IntroduceVariableBase.REFACTORING_NAME);
renamer.initInitialText(expressionText);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
renamer.performInplaceRename(false, new LinkedHashSet<String>(Arrays.asList(suggestedName.names)));
renamer.performInplaceRefactoring(new LinkedHashSet<String>(Arrays.asList(suggestedName.names)));
}
}
}
@@ -194,7 +194,7 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer<Psi
myCanBeFinalCb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new WriteCommandAction(myProject, IntroduceVariableBase.REFACTORING_NAME, IntroduceVariableBase.REFACTORING_NAME) {
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
@Override
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
@@ -27,7 +27,7 @@ import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.Nullable;
@@ -153,10 +153,10 @@ public class ReassignVariableUtil {
private static void finishTemplate(Editor editor) {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
final VariableInplaceRenamer renamer = editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER);
final InplaceRefactoring renamer = editor.getUserData(InplaceRefactoring.INPLACE_RENAMER);
if (templateState != null && renamer != null) {
templateState.gotoEnd(true);
editor.putUserData(VariableInplaceRenamer.INPLACE_RENAMER, null);
editor.putUserData(InplaceRefactoring.INPLACE_RENAMER, null);
}
}
}
@@ -54,7 +54,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PairProcessor;
import com.intellij.util.containers.HashMap;
@@ -505,7 +505,7 @@ public class TemplateState implements Disposable {
final LookupImpl lookup = (LookupImpl)lookupManager.showLookup(myEditor, lookupItems);
if (lookup == null) return;
if (CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP && myEditor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER) == null) {
if (CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP && myEditor.getUserData(InplaceRefactoring.INPLACE_RENAMER) == null) {
lookup.setStartCompletionWhenNothingMatches(true);
}
@@ -40,11 +40,10 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.ui.DottedBorder;
import com.intellij.util.ui.PositionTracker;
@@ -70,7 +69,6 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
protected final String myExprText;
private final String myLocalName;
protected String myConstantName;
public static final Key<AbstractInplaceIntroducer> ACTIVE_INTRODUCE = Key.create("ACTIVE_INTRODUCE");
private EditorEx myPreview;
@@ -168,13 +166,6 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
*/
protected abstract String getActionName();
/**
* Returns the name of the command performed by the refactoring.
*
* @return command name
*/
protected abstract String getCommandName();
/**
* Creates an initial version of the declaration for the introduced element. Note that this method is not called in a write action
* and most likely needs to create one itself.
@@ -231,7 +222,7 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
initOccurrencesMarkers();
setElementToRename(variable);
updateTitle(getVariable());
started = AbstractInplaceIntroducer.super.performInplaceRename(false, nameSuggestions);
started = AbstractInplaceIntroducer.super.performInplaceRefactoring(nameSuggestions);
if (started) {
myDocumentAdapter = new DocumentAdapter() {
@Override
@@ -239,7 +230,7 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
if (myPreview == null) return;
final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
if (templateState != null) {
final TextResult value = templateState.getVariableValue(VariableInplaceRenamer.PRIMARY_VARIABLE_NAME);
final TextResult value = templateState.getVariableValue(InplaceRefactoring.PRIMARY_VARIABLE_NAME);
if (value != null) {
updateTitle(getVariable(), value.getText());
}
@@ -320,7 +311,7 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
}
public String getInputName() {
return myConstantName;
return myInsertedName;
}
@@ -367,12 +358,7 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
}
@Override
protected boolean appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages) {
return true;
}
@Override
protected void collectAdditionalElementsToRename(boolean processTextOccurrences, List<Pair<PsiElement, TextRange>> stringUsages) {
protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) {
if (isReplaceAllOccurrences()) {
for (E expression : getOccurrences()) {
stringUsages.add(Pair.<PsiElement, TextRange>create(expression, new TextRange(0, expression.getTextLength())));
@@ -425,7 +411,6 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
}
protected void restoreState(final V psiField) {
myConstantName = psiField.getName();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final PsiFile containingFile = psiField.getContainingFile();
@@ -480,29 +465,32 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
}
@Override
protected void moveOffsetAfter(boolean success) {
if (success) {
if (getLocalVariable() == null && myExpr == null ||
getInputName() == null ||
getLocalVariable() != null && !getLocalVariable().isValid() ||
myExpr != null && !myExpr.isValid()) {
super.moveOffsetAfter(false);
return;
}
if (getLocalVariable() != null) {
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
@Override
protected void run(Result result) throws Throwable {
getLocalVariable().setName(myLocalName);
}
}.execute();
}
performIntroduce();
V variable = getVariable();
if (variable != null) {
saveSettings(variable);
}
protected boolean performRefactoring() {
if (getLocalVariable() == null && myExpr == null ||
getInputName() == 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();
}
performIntroduce();
V variable = getVariable();
if (variable != null) {
saveSettings(variable);
}
return false;
}
@Override
protected void moveOffsetAfter(boolean success) {
if (getLocalVariable() != null && getLocalVariable().isValid()) {
myEditor.getCaretModel().moveToOffset(getLocalVariable().getTextOffset());
myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
@@ -552,11 +540,6 @@ public abstract class AbstractInplaceIntroducer<V extends PsiNameIdentifierOwner
}
}
@Override
protected void restoreStateBeforeDialogWouldBeShown() {
stopIntroduce(InjectedLanguageUtil.getTopLevelEditor(myEditor));
}
@Override
protected void navigateToAlreadyStarted(Document oldDocument, int exitCode) {
finish();
@@ -25,20 +25,16 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.impl.StartMarkAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.PositionTracker;
import org.jetbrains.annotations.Nullable;
@@ -54,7 +50,7 @@ import java.util.List;
* User: anna
* Date: 3/15/11
*/
public class InplaceVariableIntroducer<E extends PsiElement> extends VariableInplaceRenamer {
public abstract class InplaceVariableIntroducer<E extends PsiElement> extends InplaceRefactoring {
public static final Key<Boolean> INTRODUCE_RESTART = Key.create("INTRODUCE_RESTART");
protected E myExpr;
@@ -66,13 +62,14 @@ public class InplaceVariableIntroducer<E extends PsiElement> extends VariableInp
protected Balloon myBalloon;
protected String myTitle;
protected RelativePoint myTarget;
private RangeMarker myCaretRangeMarker;
public InplaceVariableIntroducer(PsiNamedElement elementToRename,
Editor editor,
Project project,
String title, E[] occurrences,
@Nullable E expr) {
super(elementToRename, editor, project);
super(editor, elementToRename, project);
myTitle = title;
myOccurrences = occurrences;
myExpr = expr;
@@ -86,8 +83,8 @@ public class InplaceVariableIntroducer<E extends PsiElement> extends VariableInp
}
@Override
protected int getOffsetForCaret(RangeMarker rangeMarker, int offset) {
return rangeMarker.isValid() ? rangeMarker.getStartOffset() : offset;
protected int restoreCaretOffset(int offset) {
return myCaretRangeMarker.isValid() ? myCaretRangeMarker.getStartOffset() : offset;
}
@Override
@@ -141,8 +138,28 @@ public class InplaceVariableIntroducer<E extends PsiElement> extends VariableInp
}
@Override
public boolean performInplaceRename(boolean processTextOccurrences, LinkedHashSet<String> nameSuggestions) {
final boolean result = super.performInplaceRename(processTextOccurrences, nameSuggestions);
protected boolean performRefactoring() {
return false;
}
@Override
protected void beforeTemplateStart() {
myCaretRangeMarker = myEditor.getDocument()
.createRangeMarker(new TextRange(myEditor.getCaretModel().getOffset(), myEditor.getCaretModel().getOffset()));
}
@Override
protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) {
}
@Override
protected String getCommandName() {
return myTitle;
}
@Override
public boolean performInplaceRefactoring(LinkedHashSet<String> nameSuggestions) {
final boolean result = super.performInplaceRefactoring(nameSuggestions);
if (result) {
if (myBalloon == null) {
showBalloon();
@@ -225,21 +242,7 @@ public class InplaceVariableIntroducer<E extends PsiElement> extends VariableInp
}
}
}
return super.createLookupItems(lookupItems, name);
return lookupItems;
}
@Override
protected TextRange preserveSelectedRange(SelectionModel selectionModel) {
return null;
}
@Override
protected void performOnInvalidIdentifier(String newName, LinkedHashSet<String> nameSuggestions) {
//move logic to performRefactoring
}
@Override
protected boolean performAutomaticRename() {
return false;
}
}
@@ -33,7 +33,7 @@ public class CompletionContributorForInplaceRename extends CompletionContributor
final Editor editor = parameters.getLookup().getEditor();
final TemplateState state = TemplateManagerImpl.getTemplateState(editor);
if (state != null) {
if (editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER) != null) {
if (editor.getUserData(InplaceRefactoring.INPLACE_RENAMER) != null) {
result.stopHere();
}
}
@@ -39,7 +39,7 @@ public class EscapeHandler extends EditorActionHandler {
final SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.hasSelection()) {
final TemplateState state = TemplateManagerImpl.getTemplateState(editor);
if (state != null && editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER) != null) {
if (state != null && editor.getUserData(InplaceRefactoring.INPLACE_RENAMER) != null) {
final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup != null) {
selectionModel.removeSelection();
@@ -0,0 +1,722 @@
/*
* 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.
* 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.rename.inplace;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.Result;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.*;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.impl.FinishMarkAction;
import com.intellij.openapi.command.impl.StartMarkAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.TextEditor;
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.roots.ProjectRootManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.rename.NameSuggestionProvider;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
/**
* User: anna
* Date: 1/11/12
*/
public abstract class InplaceRefactoring {
protected static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.inplace.VariableInplaceRenamer");
@NonNls protected static final String PRIMARY_VARIABLE_NAME = "PrimaryVariable";
@NonNls protected static final String OTHER_VARIABLE_NAME = "OtherVariable";
protected static final Stack<InplaceRefactoring> ourRenamersStack = new Stack<InplaceRefactoring>();
public static final Key<InplaceRefactoring> INPLACE_RENAMER = Key.create("EditorInplaceRenamer");
protected PsiNamedElement myElementToRename;
protected final Editor myEditor;
protected final Project myProject;
protected RangeMarker myRenameOffset;
private String myAdvertisementText;
private ArrayList<RangeHighlighter> myHighlighters;
protected String myInitialName;
protected final String myOldName;
protected RangeMarker myBeforeRevert = null;
protected String myInsertedName;
protected LinkedHashSet<String> myNameSuggestions;
protected StartMarkAction myMarkAction;
protected PsiElement myScope;
public InplaceRefactoring(Editor editor, PsiNamedElement elementToRename, Project project) {
this(editor, elementToRename, project, elementToRename != null ? elementToRename.getName() : null,
elementToRename != null ? elementToRename.getName() : null);
}
public InplaceRefactoring(Editor editor, PsiNamedElement elementToRename, Project project, final String oldName) {
this(editor, elementToRename, project, elementToRename != null ? elementToRename.getName() : null, oldName);
}
public InplaceRefactoring(
Editor editor, PsiNamedElement elementToRename, Project project, String initialName, final String oldName) {
myEditor = /*(editor instanceof EditorWindow)? ((EditorWindow)editor).getDelegate() : */editor;
myElementToRename = elementToRename;
myProject = project;
myOldName = oldName;
if (myElementToRename != null) {
myInitialName = initialName;
final PsiFile containingFile = myElementToRename.getContainingFile();
if (!notSameFile(getTopLevelVirtualFile(containingFile.getViewProvider()), containingFile)) {
myRenameOffset = myElementToRename != null && myElementToRename.getTextRange() != null ? myEditor.getDocument()
.createRangeMarker(myElementToRename.getTextRange()) : null;
}
}
}
public void setAdvertisementText(String advertisementText) {
myAdvertisementText = advertisementText;
}
public boolean performInplaceRefactoring(final LinkedHashSet<String> nameSuggestions) {
myNameSuggestions = nameSuggestions;
if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(myElementToRename)) {
return false;
}
final FileViewProvider fileViewProvider = myElementToRename.getContainingFile().getViewProvider();
VirtualFile file = getTopLevelVirtualFile(fileViewProvider);
SearchScope referencesSearchScope = getReferencesSearchScope(file);
final Collection<PsiReference> refs = collectRefs(referencesSearchScope);
addReferenceAtCaret(refs);
for (PsiReference ref : refs) {
final PsiFile containingFile = ref.getElement().getContainingFile();
if (notSameFile(file, containingFile)) {
return false;
}
}
final PsiElement scope = checkLocalScope();
if (scope == null) {
return false; // Should have valid local search scope for inplace rename
}
final PsiFile containingFile = scope.getContainingFile();
if (containingFile == null) {
return false; // Should have valid local search scope for inplace rename
}
//no need to process further when file is read-only
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, containingFile)) return true;
myEditor.putUserData(INPLACE_RENAMER, this);
ourRenamersStack.push(this);
final List<Pair<PsiElement, TextRange>> stringUsages = new ArrayList<Pair<PsiElement, TextRange>>();
collectAdditionalElementsToRename(stringUsages);
return buildTemplateAndStart(refs, stringUsages, scope, containingFile);
}
protected boolean notSameFile(@Nullable VirtualFile file, PsiFile containingFile) {
return getTopLevelVirtualFile(containingFile.getViewProvider()) != file;
}
protected SearchScope getReferencesSearchScope(VirtualFile file) {
return file == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(file)
? ProjectScope.getProjectScope(myElementToRename.getProject())
: new LocalSearchScope(myElementToRename.getContainingFile());
}
@Nullable
protected PsiElement checkLocalScope() {
final SearchScope searchScope = PsiSearchHelper.SERVICE.getInstance(myElementToRename.getProject()).getUseScope(myElementToRename);
if (searchScope instanceof LocalSearchScope) {
final PsiElement[] elements = ((LocalSearchScope)searchScope).getScope();
return PsiTreeUtil.findCommonParent(elements);
}
return null;
}
protected abstract void collectAdditionalElementsToRename(final List<Pair<PsiElement, TextRange>> stringUsages);
protected abstract boolean shouldSelectAll();
protected abstract LookupElement[] createLookupItems(LookupElement[] lookupItems, String name);
protected Collection<PsiReference> collectRefs(SearchScope referencesSearchScope) {
return ReferencesSearch.search(myElementToRename, referencesSearchScope, false).findAll();
}
protected boolean buildTemplateAndStart(final Collection<PsiReference> refs,
final Collection<Pair<PsiElement, TextRange>> stringUsages,
final PsiElement scope,
final PsiFile containingFile) {
final PsiElement context = containingFile.getContext();
myScope = context != null ? context.getContainingFile() : scope;
final TemplateBuilderImpl builder = new TemplateBuilderImpl(myScope);
PsiElement nameIdentifier = getNameIdentifier();
int offset = myEditor.getCaretModel().getOffset();
PsiElement selectedElement = getSelectedInEditorElement(nameIdentifier, refs, stringUsages, offset);
if (nameIdentifier != null) addVariable(nameIdentifier, selectedElement, builder);
for (PsiReference ref : refs) {
addVariable(ref, selectedElement, builder, offset);
}
for (Pair<PsiElement, TextRange> usage : stringUsages) {
addVariable(usage.first, usage.second, selectedElement, builder);
}
addAdditionalVariables(builder);
try {
myMarkAction = startRename();
}
catch (final StartMarkAction.AlreadyStartedException e) {
final Document oldDocument = e.getDocument();
if (oldDocument != myEditor.getDocument()) {
final int exitCode = Messages.showOkCancelDialog(myProject, e.getMessage(), getCommandName(),
"Navigate to continue", "Cancel started", Messages.getErrorIcon());
if (exitCode == -1) return true;
navigateToAlreadyStarted(oldDocument, exitCode);
return true;
}
else {
revertState();
}
return false;
}
beforeTemplateStart();
new WriteCommandAction(myProject, getCommandName()) {
@Override
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
startTemplate(builder);
}
}.execute();
return true;
}
protected abstract void beforeTemplateStart();
private void startTemplate(final TemplateBuilderImpl builder) {
final DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject);
final boolean previousUpdate;
if (daemonCodeAnalyzer != null) {
previousUpdate = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).isUpdateByTimerEnabled();
daemonCodeAnalyzer.setUpdateByTimerEnabled(false);
}
else {
previousUpdate = false;
}
final MyTemplateListener templateListener = new MyTemplateListener() {
@Override
protected void restoreDaemonUpdateState() {
if (daemonCodeAnalyzer != null) {
daemonCodeAnalyzer.setUpdateByTimerEnabled(previousUpdate);
}
}
};
final int offset = myEditor.getCaretModel().getOffset();
Template template = builder.buildInlineTemplate();
template.setToShortenLongNames(false);
TextRange range = myScope.getTextRange();
assert range != null;
myHighlighters = new ArrayList<RangeHighlighter>();
Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
topLevelEditor.getCaretModel().moveToOffset(range.getStartOffset());
TemplateManager.getInstance(myProject).startTemplate(topLevelEditor, template, templateListener);
restoreOldCaretPositionAndSelection(offset);
highlightTemplateVariables(template, topLevelEditor);
}
private void highlightTemplateVariables(Template template, Editor topLevelEditor) {
//add highlights
if (myHighlighters != null) { // can be null if finish is called during testing
Map<TextRange, TextAttributes> rangesToHighlight = new HashMap<TextRange, TextAttributes>();
final TemplateState templateState = TemplateManagerImpl.getTemplateState(topLevelEditor);
if (templateState != null) {
EditorColorsManager colorsManager = EditorColorsManager.getInstance();
for (int i = 0; i < templateState.getSegmentsCount(); i++) {
final TextRange segmentOffset = templateState.getSegmentRange(i);
final String name = template.getSegmentName(i);
TextAttributes attributes = null;
if (name.equals(PRIMARY_VARIABLE_NAME)) {
attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES);
}
else if (name.equals(OTHER_VARIABLE_NAME)) {
attributes = colorsManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
}
if (attributes == null) continue;
rangesToHighlight.put(segmentOffset, attributes);
}
}
addHighlights(rangesToHighlight, topLevelEditor, myHighlighters, HighlightManager.getInstance(myProject));
}
}
private void restoreOldCaretPositionAndSelection(final int offset) {
//move to old offset
Runnable runnable = new Runnable() {
public void run() {
myEditor.getCaretModel().moveToOffset(restoreCaretOffset(offset));
restoreSelection();
}
};
final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(myEditor);
if (lookup != null && lookup.getLookupStart() <= (restoreCaretOffset(offset))) {
lookup.setFocused(false);
lookup.performGuardedChange(runnable);
}
else {
runnable.run();
}
}
protected void restoreSelection() {
}
protected int restoreCaretOffset(int offset) {
return offset;
}
protected void navigateToAlreadyStarted(Document oldDocument, int exitCode) {
final PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(oldDocument);
if (file != null) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
final FileEditor[] editors = FileEditorManager.getInstance(myProject).getEditors(virtualFile);
for (FileEditor editor : editors) {
if (editor instanceof TextEditor) {
final Editor textEditor = ((TextEditor)editor).getEditor();
final TemplateState templateState = TemplateManagerImpl.getTemplateState(textEditor);
if (templateState != null) {
if (exitCode == DialogWrapper.OK_EXIT_CODE) {
final TextRange range = templateState.getVariableRange(PRIMARY_VARIABLE_NAME);
if (range != null) {
new OpenFileDescriptor(myProject, virtualFile, range.getStartOffset()).navigate(true);
return;
}
}
else {
templateState.gotoEnd();
return;
}
}
}
}
}
}
}
@Nullable
protected PsiElement getNameIdentifier() {
return myElementToRename instanceof PsiNameIdentifierOwner ? ((PsiNameIdentifierOwner)myElementToRename).getNameIdentifier() : null;
}
@Nullable
protected StartMarkAction startRename() throws StartMarkAction.AlreadyStartedException {
final StartMarkAction[] markAction = new StartMarkAction[1];
final StartMarkAction.AlreadyStartedException[] ex = new StartMarkAction.AlreadyStartedException[1];
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
try {
markAction[0] = StartMarkAction.start(myEditor, myProject, getCommandName());
}
catch (StartMarkAction.AlreadyStartedException e) {
ex[0] = e;
}
}
}, getCommandName(), null);
if (ex[0] != null) throw ex[0];
return markAction[0];
}
@Nullable
protected PsiNamedElement getVariable() {
if (myElementToRename != null && myElementToRename.isValid()) return myElementToRename;
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
if (psiFile != null) {
return PsiTreeUtil.getParentOfType(psiFile.findElementAt(myRenameOffset.getStartOffset()), PsiNameIdentifierOwner.class);
}
return myElementToRename;
}
/**
* Called after the completion of the refactoring, either a successful or a failed one.
*
* @param success true if the refactoring was accepted, false if it was cancelled (by undo or Esc)
*/
protected void moveOffsetAfter(boolean success) {
}
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
}
protected void addReferenceAtCaret(Collection<PsiReference> refs) {
PsiFile myEditorFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
// Note, that myEditorFile can be different from myElement.getContainingFile() e.g. in injections: myElement declaration in one
// file / usage in another !
final PsiReference reference = (myEditorFile != null ?
myEditorFile : myElementToRename.getContainingFile())
.findReferenceAt(myEditor.getCaretModel().getOffset());
if (reference != null && !refs.contains(reference)) {
refs.add(reference);
}
}
protected void showDialogAdvertisement(final String actionId) {
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
final Shortcut[] shortcuts = keymap.getShortcuts(actionId);
if (shortcuts.length > 0) {
setAdvertisementText("Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to show dialog");
}
}
public String getInitialName() {
if (myInitialName == null) {
final PsiNamedElement variable = getVariable();
if (variable != null) {
return variable.getName();
}
}
return myInitialName;
}
protected void revertState() {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final TemplateState state = TemplateManagerImpl.getTemplateState(topLevelEditor);
assert state != null;
final int segmentsCount = state.getSegmentsCount();
final Document document = topLevelEditor.getDocument();
for (int i = 0; i < segmentsCount; i++) {
final TextRange segmentRange = state.getSegmentRange(i);
document.replaceString(segmentRange.getStartOffset(), segmentRange.getEndOffset(), myOldName);
}
}
});
PsiDocumentManager.getInstance(myProject).commitDocument(topLevelEditor.getDocument());
}
}, getCommandName(), null);
}
/**
* Returns the name of the command performed by the refactoring.
*
* @return command name
*/
protected abstract String getCommandName();
public void finish() {
if (!ourRenamersStack.isEmpty() && ourRenamersStack.peek() == this) {
ourRenamersStack.pop();
}
if (myHighlighters != null) {
if (!myProject.isDisposed()) {
final HighlightManager highlightManager = HighlightManager.getInstance(myProject);
for (RangeHighlighter highlighter : myHighlighters) {
highlightManager.removeSegmentHighlighter(myEditor, highlighter);
}
}
myHighlighters = null;
myEditor.putUserData(INPLACE_RENAMER, null);
}
}
protected void addHighlights(@NotNull Map<TextRange, TextAttributes> ranges,
@NotNull Editor editor,
@NotNull Collection<RangeHighlighter> highlighters,
@NotNull HighlightManager highlightManager) {
for (Map.Entry<TextRange, TextAttributes> entry : ranges.entrySet()) {
TextRange range = entry.getKey();
TextAttributes attributes = entry.getValue();
highlightManager.addOccurrenceHighlight(editor, range.getStartOffset(), range.getEndOffset(), attributes, 0, highlighters, null);
}
for (RangeHighlighter highlighter : highlighters) {
highlighter.setGreedyToLeft(true);
highlighter.setGreedyToRight(true);
}
}
protected abstract boolean performRefactoring();
private void addVariable(final PsiReference reference,
final PsiElement selectedElement,
final TemplateBuilderImpl builder,
int offset) {
if (reference.getElement() == selectedElement &&
contains(reference.getRangeInElement().shiftRight(selectedElement.getTextRange().getStartOffset()), offset)) {
Expression expression = new MyExpression(getInitialName(), myNameSuggestions);
builder.replaceElement(reference, PRIMARY_VARIABLE_NAME, expression, true);
}
else {
builder.replaceElement(reference, OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
}
}
private void addVariable(final PsiElement element,
final PsiElement selectedElement,
final TemplateBuilderImpl builder) {
addVariable(element, null, selectedElement, builder);
}
private void addVariable(final PsiElement element,
@Nullable final TextRange textRange,
final PsiElement selectedElement,
final TemplateBuilderImpl builder) {
if (element == selectedElement) {
Expression expression = new MyExpression(getInitialName(), myNameSuggestions);
builder.replaceElement(element, PRIMARY_VARIABLE_NAME, expression, true);
}
else if (textRange != null) {
builder.replaceElement(element, textRange, OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
}
else {
builder.replaceElement(element, OTHER_VARIABLE_NAME, PRIMARY_VARIABLE_NAME, false);
}
}
public void setElementToRename(PsiNamedElement elementToRename) {
myElementToRename = elementToRename;
}
protected static VirtualFile getTopLevelVirtualFile(final FileViewProvider fileViewProvider) {
VirtualFile file = fileViewProvider.getVirtualFile();
if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
return file;
}
@TestOnly
public static void checkCleared() {
try {
assert ourRenamersStack.isEmpty() : ourRenamersStack;
}
finally {
ourRenamersStack.clear();
}
}
private static PsiElement getSelectedInEditorElement(@Nullable PsiElement nameIdentifier,
final Collection<PsiReference> refs,
Collection<Pair<PsiElement, TextRange>> stringUsages,
final int offset) {
if (nameIdentifier != null) {
final TextRange range = nameIdentifier.getTextRange();
if (contains(range, offset)) return nameIdentifier;
}
for (PsiReference ref : refs) {
final PsiElement element = ref.getElement();
if (contains(ref.getRangeInElement().shiftRight(element.getTextRange().getStartOffset()), offset)) return element;
}
for (Pair<PsiElement, TextRange> stringUsage : stringUsages) {
final PsiElement element = stringUsage.first;
if (contains(stringUsage.second.shiftRight(element.getTextRange().getStartOffset()), offset)) return element;
}
LOG.assertTrue(false);
return null;
}
private static boolean contains(final TextRange range, final int offset) {
return range.getStartOffset() <= offset && offset <= range.getEndOffset();
}
protected class MyExpression extends Expression {
private final String myName;
private final LookupElement[] myLookupItems;
protected MyExpression(String name, LinkedHashSet<String> names) {
myName = name;
if (names == null) {
names = new LinkedHashSet<String>();
for (NameSuggestionProvider provider : Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) {
provider.getSuggestedNames(myElementToRename, myElementToRename, names);
}
}
myLookupItems = new LookupElement[names.size()];
final Iterator<String> iterator = names.iterator();
for (int i = 0; i < myLookupItems.length; i++) {
final String suggestion = iterator.next();
myLookupItems[i] = LookupElementBuilder.create(suggestion).setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
if (shouldSelectAll()) return;
final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
final TemplateState templateState = TemplateManagerImpl.getTemplateState(topLevelEditor);
if (templateState != null) {
final TextRange range = templateState.getCurrentVariableRange();
if (range != null) {
topLevelEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), suggestion);
}
}
}
});
}
}
public LookupElement[] calculateLookupItems(ExpressionContext context) {
return createLookupItems(myLookupItems, myName);
}
public Result calculateQuickResult(ExpressionContext context) {
return calculateResult(context);
}
public Result calculateResult(ExpressionContext context) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
final TextResult insertedValue = templateState != null ? templateState.getVariableValue(PRIMARY_VARIABLE_NAME) : null;
if (insertedValue != null) {
if (!insertedValue.getText().isEmpty()) return insertedValue;
}
return new TextResult(myName);
}
@Override
public String getAdvertisingText() {
return myAdvertisementText;
}
}
private abstract class MyTemplateListener extends TemplateEditingAdapter {
protected abstract void restoreDaemonUpdateState();
public void beforeTemplateFinished(final TemplateState templateState, Template template) {
try {
final TextResult value = templateState.getVariableValue(PRIMARY_VARIABLE_NAME);
myInsertedName = value != null ? value.toString() : null;
final int currentOffset = myEditor.getCaretModel().getOffset();
myBeforeRevert =
myRenameOffset != null && myRenameOffset.getEndOffset() >= currentOffset && myRenameOffset.getStartOffset() <= currentOffset
? myEditor.getDocument().createRangeMarker(myRenameOffset.getStartOffset(), currentOffset)
: null;
if (myBeforeRevert != null) {
myBeforeRevert.setGreedyToRight(true);
}
finish();
}
finally {
restoreDaemonUpdateState();
}
}
@Override
public void templateFinished(Template template, final boolean brokenOff) {
boolean bind = false;
try {
super.templateFinished(template, brokenOff);
if (!brokenOff) {
bind = performRefactoring();
}
moveOffsetAfter(!brokenOff);
}
finally {
if (!bind) {
FinishMarkAction.finish(myProject, myEditor, myMarkAction);
if (myBeforeRevert != null) {
myBeforeRevert.dispose();
}
}
}
}
public void templateCancelled(Template template) {
try {
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
documentManager.commitAllDocuments();
finish();
moveOffsetAfter(false);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
documentManager.doPostponedOperationsAndUnblockDocument(myEditor.getDocument());
}
});
}
finally {
try {
restoreDaemonUpdateState();
}
finally {
FinishMarkAction.finish(myProject, myEditor, myMarkAction);
}
}
}
}
}
@@ -48,7 +48,7 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler {
}
@Override
public VariableInplaceRenamer doRename(@NotNull final PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
public InplaceRefactoring doRename(@NotNull final PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
if (elementToRename instanceof PsiNameIdentifierOwner) {
final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(elementToRename);
if (processor.isInplaceRenameSupported()) {
@@ -138,7 +138,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
}
@Override
protected boolean appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages) {
protected boolean appendAdditionalElement(Collection<Pair<PsiElement, TextRange>> stringUsages) {
boolean showChooser = super.appendAdditionalElement(stringUsages);
PsiNamedElement variable = getVariable();
if (variable != null) {
@@ -157,7 +157,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
return showChooser;
}
private void appendAdditionalElement(List<Pair<PsiElement, TextRange>> stringUsages,
private void appendAdditionalElement(Collection<Pair<PsiElement, TextRange>> stringUsages,
PsiNamedElement variable,
PsiElement element) {
if (element != variable && element instanceof PsiNameIdentifierOwner &&
@@ -170,7 +170,6 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
}
protected void performRefactoringRename(final String newName,
PsiElement context,
final StartMarkAction markAction) {
try {
final PsiNamedElement variable = getVariable();
@@ -216,20 +215,16 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
}
@Override
protected void collectAdditionalElementsToRename(boolean processTextOccurrences, List<Pair<PsiElement, TextRange>> stringUsages) {
protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) {
//do not highlight non-code usages in file
}
@Override
protected void restoreStateBeforeTemplateIsFinished() {
public void finish() {
super.finish();
revertState();
}
@Override
protected String getNewName(String newName, ResolveSnapshotProvider.ResolveSnapshot snapshot) {
return newName;
}
@Nullable
public PsiElement getSubstituted() {
if (mySubstituted != null && mySubstituted.isValid()) return mySubstituted;
@@ -0,0 +1,119 @@
/*
* 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.
* 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.rename.inplace;
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.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.util.*;
/**
* User: anna
* Date: 1/11/12
*/
abstract class RenameChooser {
@NonNls private static final String CODE_OCCURRENCES = "Rename code occurrences";
@NonNls private static final String ALL_OCCURRENCES = "Rename all occurrences";
private final Set<RangeHighlighter> myRangeHighlighters = new HashSet<RangeHighlighter>();
private final Editor myEditor;
private final TextAttributes myAttributes;
public RenameChooser(Editor editor) {
myEditor = editor;
myAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
}
protected abstract void runRenameTemplate(Collection<Pair<PsiElement, TextRange>> stringUsages);
public void showChooser(final Collection<PsiReference> refs,
final Collection<Pair<PsiElement, TextRange>> stringUsages) {
final DefaultListModel model = new DefaultListModel();
model.addElement(CODE_OCCURRENCES);
model.addElement(ALL_OCCURRENCES);
final JList list = new JBList(model);
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(final ListSelectionEvent e) {
final String selectedValue = (String)list.getSelectedValue();
if (selectedValue == null) return;
dropHighlighters();
final MarkupModel markupModel = myEditor.getMarkupModel();
if (selectedValue == ALL_OCCURRENCES) {
for (Pair<PsiElement, TextRange> pair : stringUsages) {
final TextRange textRange = pair.second.shiftRight(pair.first.getTextOffset());
final RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter(
textRange.getStartOffset(), textRange.getEndOffset(), HighlighterLayer.SELECTION - 1, myAttributes,
HighlighterTargetArea.EXACT_RANGE);
myRangeHighlighters.add(rangeHighlighter);
}
}
for (PsiReference reference : refs) {
final PsiElement element = reference.getElement();
if (element == null) continue;
final TextRange textRange = element.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("String occurrences found")
.setMovable(false)
.setResizable(false)
.setRequestFocus(true)
.setItemChoosenCallback(new Runnable() {
public void run() {
runRenameTemplate(list.getSelectedValue() == ALL_OCCURRENCES ? stringUsages : new ArrayList<Pair<PsiElement, TextRange>>());
}
})
.addListener(new JBPopupAdapter() {
@Override
public void onClosed(LightweightWindowEvent event) {
dropHighlighters();
}
})
.createPopup().showInBestPositionFor(myEditor);
}
private void dropHighlighters() {
for (RangeHighlighter highlight : myRangeHighlighters) {
highlight.dispose();
}
myRangeHighlighters.clear();
}
}
@@ -107,7 +107,7 @@ public class VariableInplaceRenameHandler implements RenameHandler {
}
@Nullable
public VariableInplaceRenamer doRename(final @NotNull PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
public InplaceRefactoring doRename(final @NotNull PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
VariableInplaceRenamer renamer = createRenamer(elementToRename, editor);
boolean startedRename = renamer == null ? false : renamer.performInplaceRename();
@@ -36,7 +36,7 @@ import com.intellij.psi.codeStyle.CodeStyleSchemes;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.testFramework.exceptionCases.AbstractExceptionCase;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
@@ -195,7 +195,7 @@ public abstract class UsefulTestCase extends TestCase {
myOldCodeStyleSettings = null;
try {
VariableInplaceRenamer.checkCleared();
InplaceRefactoring.checkCleared();
}
catch (AssertionError e) {
result.add(e);
@@ -40,8 +40,8 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler;
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -165,7 +165,7 @@ public class CodeInsightTestUtil {
TemplateManagerImpl templateManager = (TemplateManagerImpl)TemplateManager.getInstance(project);
try {
templateManager.setTemplateTesting(true);
VariableInplaceRenamer renamer = handler.doRename(elementAtCaret, editor, null);
InplaceRefactoring renamer = handler.doRename(elementAtCaret, editor, null);
if (editor instanceof EditorWindow) {
editor = ((EditorWindow)editor).getDelegate();
}