From 856b5c883cf233be7cf867bbfe342789e2f4a6ea Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 20 Jul 2010 18:48:35 +0400 Subject: [PATCH] rename: balloon notification about filtered unresolvable collisions (IDEA-56611) --- .../refactoring/rename/RenameProcessor.java | 49 ++++++++++++++++--- .../refactoring/rename/RenameUtil.java | 6 ++- .../rename/naming/AutomaticRenamer.java | 18 +++++-- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java index 54a045c4b108..2599740ff7a5 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java @@ -17,12 +17,18 @@ package com.intellij.refactoring.rename; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.ex.StatusBarEx; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.impl.light.LightElement; @@ -39,6 +45,7 @@ import com.intellij.refactoring.util.RelatedUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; @@ -46,6 +53,8 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; import java.util.*; public class RenameProcessor extends BaseRefactoringProcessor { @@ -65,6 +74,7 @@ public class RenameProcessor extends BaseRefactoringProcessor { private NonCodeUsageInfo[] myNonCodeUsages = new NonCodeUsageInfo[0]; private final List myRenamerFactories = new ArrayList(); private final List myRenamers = new ArrayList(); + private final List mySkippedUsages = new ArrayList(); public RenameProcessor(Project project, PsiElement element, @@ -139,8 +149,6 @@ public class RenameProcessor extends BaseRefactoringProcessor { return false; } } - Set usagesSet = new HashSet(Arrays.asList(usagesIn)); - RenameUtil.removeConflictUsages(usagesSet); final List variableUsages = new ArrayList(); if (!myRenamers.isEmpty()) { @@ -174,10 +182,13 @@ public class RenameProcessor extends BaseRefactoringProcessor { } } - if (!variableUsages.isEmpty()) { - usagesSet.addAll(variableUsages); - refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); + final Set usagesSet = new HashSet(Arrays.asList(usagesIn)); + usagesSet.addAll(variableUsages); + final List conflictUsages = RenameUtil.removeConflictUsages(usagesSet); + if (conflictUsages != null) { + mySkippedUsages.addAll(conflictUsages); } + refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); prepareSuccessful(); return true; @@ -192,7 +203,7 @@ public class RenameProcessor extends BaseRefactoringProcessor { final Runnable runnable = new Runnable() { public void run() { for (final AutomaticRenamer renamer : myRenamers) { - renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences); + renamer.findUsages(variableUsages, mySearchInComments, mySearchTextOccurrences, mySkippedUsages); } } }; @@ -326,6 +337,32 @@ public class RenameProcessor extends BaseRefactoringProcessor { } } myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]); + if (!mySkippedUsages.isEmpty()) { + if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + final IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(myProject); + if (ideFrame != null) { + + StatusBarEx statusBar = (StatusBarEx)ideFrame.getStatusBar(); + HyperlinkListener listener = new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) return; + Messages.showMessageDialog("" + + StringUtil.join(mySkippedUsages, new Function() { + public String fun(UnresolvableCollisionUsageInfo unresolvableCollisionUsageInfo) { + return unresolvableCollisionUsageInfo.getDescription(); + } + }, "
") + + "", "Don't panic! They are safe to skip", null); + } + }; + statusBar.notifyProgressByBalloon(MessageType.WARNING, "Unable to rename certain usages. Browse", null, listener); + } + } + }, ModalityState.NON_MODAL); + } + } } protected void performPsiSpoilingRefactoring() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java index a5fe42aa49c6..25a5b074a2d5 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java @@ -239,13 +239,17 @@ public class RenameUtil { ref.handleElementRename(newName); } - public static void removeConflictUsages(Set usages) { + @Nullable + public static List removeConflictUsages(Set usages) { + final List result = new ArrayList(); for (Iterator iterator = usages.iterator(); iterator.hasNext();) { UsageInfo usageInfo = iterator.next(); if (usageInfo instanceof UnresolvableCollisionUsageInfo) { + result.add((UnresolvableCollisionUsageInfo)usageInfo); iterator.remove(); } } + return result.isEmpty() ? null : result; } public static void addConflictDescriptions(UsageInfo[] usages, MultiMap conflicts) { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamer.java index f1c73f546ebd..4ddd95046b5c 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/naming/AutomaticRenamer.java @@ -47,9 +47,16 @@ public abstract class AutomaticRenamer { } public void findUsages(List result, final boolean searchInStringsAndComments, final boolean searchInNonJavaFiles) { + findUsages(result, searchInStringsAndComments, searchInNonJavaFiles, null); + } + + public void findUsages(List result, + final boolean searchInStringsAndComments, + final boolean searchInNonJavaFiles, + List unresolvedUsages) { for (Iterator iterator = myElements.iterator(); iterator.hasNext();) { final PsiNamedElement variable = iterator.next(); - final boolean success = findUsagesForElement(variable, result, searchInStringsAndComments, searchInNonJavaFiles); + final boolean success = findUsagesForElement(variable, result, searchInStringsAndComments, searchInNonJavaFiles, unresolvedUsages); if (!success) { iterator.remove(); } @@ -59,12 +66,17 @@ public abstract class AutomaticRenamer { private boolean findUsagesForElement(PsiNamedElement element, List result, final boolean searchInStringsAndComments, - final boolean searchInNonJavaFiles) { + final boolean searchInNonJavaFiles, List unresolvedUsages) { final String newName = getNewName(element); if (newName != null) { final UsageInfo[] usages = RenameUtil.findUsages(element, newName, searchInStringsAndComments, searchInNonJavaFiles, myRenames); for (final UsageInfo usage : usages) { - if (usage instanceof UnresolvableCollisionUsageInfo) return false; + if (usage instanceof UnresolvableCollisionUsageInfo) { + if (unresolvedUsages != null) { + unresolvedUsages.add((UnresolvableCollisionUsageInfo)usage); + } + return false; + } } ContainerUtil.addAll(result, usages); }