From a88096804f36c6f2c85a8a54e01a4ea32bc6e7d3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 23 Jan 2014 14:09:42 +0400 Subject: [PATCH] IDEA-66430 "Find In Path" doesn't show up in "Recent Find Usages" --- .../InheritanceToDelegationProcessor.java | 4 +- .../safeDelete/JavaSafeDeleteProcessor.java | 4 +- .../ui/MigrationConflictsPanel.java | 8 +- .../typeMigration/ui/MigrationPanel.java | 6 +- .../ui/MigrationUsagesPanel.java | 12 +- .../src/com/intellij/find/FindUtil.java | 13 +- .../find/actions/FindUsagesAction.java | 5 +- .../find/actions/ShowUsagesAction.java | 27 +- .../findInProject/FindInProjectManager.java | 190 ++++-------- .../find/findUsages/FindUsagesManager.java | 271 +++++++----------- .../PsiElement2UsageTargetAdapter.java | 163 ++++++----- .../PsiElement2UsageTargetComposite.java | 70 +++++ .../find/findUsages/UsageHistory.java | 58 ++++ .../intellij/find/impl/FindInProjectUtil.java | 96 ++++--- .../find/impl/ShowRecentFindUsagesAction.java | 46 +-- .../find/impl/ShowRecentFindUsagesGroup.java | 26 +- .../ReplaceInProjectManager.java | 4 +- .../ui/DependenciesUsagesPanel.java | 5 +- .../packageDependencies/ui/UsagesPanel.java | 7 +- .../safeDelete/SafeDeleteProcessor.java | 4 +- .../src/messages/FindBundle.properties | 7 +- .../usages/ConfigurableUsageTarget.java | 8 +- .../usages/FindUsagesProcessPresentation.java | 4 +- .../usages/PsiElementUsageTarget.java | 4 +- .../usages/UsageInfoToUsageConverter.java | 18 +- .../intellij/usages/impl/UsageViewImpl.java | 14 +- .../usages/impl/UsageViewManagerImpl.java | 11 +- 27 files changed, 545 insertions(+), 540 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java create mode 100644 platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java index a21680ee30a8..6c74e8a60193 100644 --- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -851,7 +851,7 @@ public class InheritanceToDelegationProcessor extends BaseRefactoringProcessor { UsageViewManager manager = UsageViewManager.getInstance(myProject); manager.showUsages( new UsageTarget[]{new PsiElement2UsageTargetAdapter(myClass)}, - UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(myClass), usages), + UsageInfoToUsageConverter.convert(new PsiElement[]{myClass}, usages), presentation ); diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java index 02d8786d6dcc..09d752f28adb 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -170,7 +170,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase { } return manager.showUsages(targets, - UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(elements), + UsageInfoToUsageConverter.convert(elements, others.toArray(new UsageInfo[others.size()])), presentation ); diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java index bfb07f1d0e64..ffe30a7b99d5 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -17,8 +17,8 @@ package com.intellij.refactoring.typeMigration.ui; import com.intellij.openapi.project.Project; import com.intellij.packageDependencies.ui.UsagesPanel; +import com.intellij.psi.PsiElement; import com.intellij.usageView.UsageInfo; -import com.intellij.usages.UsageInfoToUsageConverter; import org.jetbrains.annotations.NotNull; /** @@ -39,7 +39,7 @@ public class MigrationConflictsPanel extends UsagesPanel{ } @Override - public void showUsages(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, @NotNull final UsageInfo[] usageInfos) { - super.showUsages(descriptor, usageInfos); + public void showUsages(@NotNull final PsiElement[] primaryElements, @NotNull final UsageInfo[] usageInfos) { + super.showUsages(primaryElements, usageInfos); } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java index c571e76b5a21..29d7c37a41b2 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -163,7 +163,7 @@ public class MigrationPanel extends JPanel implements Disposable { final MigrationNode migrationNode = (MigrationNode)userObject; final UsageInfo[] failedUsages = myLabeler.getFailedUsages(); if (failedUsages.length > 0) { - myConflictsPanel.showUsages(new UsageInfoToUsageConverter.TargetElementsDescriptor(new PsiElement[0]), failedUsages); + myConflictsPanel.showUsages(PsiElement.EMPTY_ARRAY, failedUsages); } final AbstractTreeNode rootNode = migrationNode.getParent(); if (rootNode instanceof MigrationNode) { @@ -450,7 +450,7 @@ public class MigrationPanel extends JPanel implements Disposable { } if (typeElement == null) typeElement = element; PsiDocumentManager.getInstance(element.getProject()).commitAllDocuments(); - final UsagePresentation presentation = UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(typeElement), new UsageInfo(typeElement)).getPresentation(); + final UsagePresentation presentation = UsageInfoToUsageConverter.convert(new PsiElement[]{typeElement}, new UsageInfo(typeElement)).getPresentation(); boolean isPrefix = true; //skip usage position for (TextChunk chunk : presentation.getText()) { if (!isPrefix) append(chunk.getText(), patchAttrs(usageInfo, chunk.getSimpleAttributesIgnoreBackground())); diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java index 968de842a29f..020dccf12a87 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement; import com.intellij.refactoring.typeMigration.TypeMigrationLabeler; import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo; import com.intellij.usageView.UsageInfo; -import com.intellij.usages.UsageInfoToUsageConverter; import java.awt.*; import java.util.ArrayList; @@ -48,8 +47,6 @@ public class MigrationUsagesPanel extends UsagesPanel { public void showRootUsages(UsageInfo root, UsageInfo migration, final TypeMigrationLabeler labeler) { final PsiElement rootElement = root.getElement(); if (rootElement == null) return; - final UsageInfoToUsageConverter.TargetElementsDescriptor targetElementsDescriptor = - new UsageInfoToUsageConverter.TargetElementsDescriptor(rootElement); final Set usages = labeler.getTypeUsages((TypeMigrationUsageInfo)migration, ((TypeMigrationUsageInfo)root)); if (usages != null) { final List infos = new ArrayList(usages.size()); @@ -58,9 +55,10 @@ public class MigrationUsagesPanel extends UsagesPanel { infos.add(new UsageInfo(usage)); } } - showUsages(targetElementsDescriptor, infos.toArray(new UsageInfo[infos.size()])); - } else { - showUsages(targetElementsDescriptor, new UsageInfo[] {migration}); + showUsages(new PsiElement[]{rootElement}, infos.toArray(new UsageInfo[infos.size()])); + } + else { + showUsages(new PsiElement[]{rootElement}, new UsageInfo[] {migration}); } } diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java index fbef4f7d5613..e54074d08461 100644 --- a/platform/lang-impl/src/com/intellij/find/FindUtil.java +++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -307,7 +307,7 @@ public class FindUtil { public static void findAllAndShow(@NotNull Project project, @NotNull Editor editor, @NotNull FindModel findModel) { List usages = findAll(project, editor, findModel); if (usages == null) return; - final UsageTarget[] usageTargets = {new FindInProjectUtil.StringUsageTarget(project, findModel.getStringToFind())}; + final UsageTarget[] usageTargets = {new FindInProjectUtil.StringUsageTarget(project, findModel)}; final UsageViewPresentation usageViewPresentation = FindInProjectUtil.setupViewPresentation(false, findModel); UsageViewManager.getInstance(project).showUsages(usageTargets, usages.toArray(new Usage[usages.size()]), usageViewPresentation); } @@ -931,23 +931,20 @@ public class FindUtil { final UsageTarget[] usageTargets = sourceElement == null ? UsageTarget.EMPTY_ARRAY : new UsageTarget[]{new PsiElement2UsageTargetAdapter(sourceElement)}; - final UsageInfoToUsageConverter.TargetElementsDescriptor targetElementsDescriptor = - sourceElement != null ? new UsageInfoToUsageConverter.TargetElementsDescriptor(sourceElement) - : new UsageInfoToUsageConverter.TargetElementsDescriptor(PsiElement.EMPTY_ARRAY); - final Usage[] usages = {UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(targets[0]))}; + final PsiElement[] primary = sourceElement == null ? PsiElement.EMPTY_ARRAY : new PsiElement[]{sourceElement}; + final Usage[] usages = {UsageInfoToUsageConverter.convert(primary, new UsageInfo(targets[0]))}; final UsageView view = UsageViewManager.getInstance(project).showUsages(usageTargets, usages, presentation); ProgressManager.getInstance().run(new Task.Backgroundable(project, "Updating Usage View ...") { @Override public void run(@NotNull ProgressIndicator indicator) { - for (int i = 1; i < targets.length; i++) { if (((UsageViewImpl)view).isDisposed()) break; final PsiElement target = targets[i]; ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { - final Usage usage = UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(target)); + final Usage usage = UsageInfoToUsageConverter.convert(primary, new UsageInfo(target)); view.appendUsage(usage); } }); diff --git a/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java index d2536ee2483e..3da2b2e15a97 100644 --- a/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,7 +21,6 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction; import com.intellij.find.FindBundle; import com.intellij.find.FindManager; -import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -73,7 +72,7 @@ public class FindUsagesAction extends AnAction { } protected void startFindUsages(@NotNull PsiElement element) { - new PsiElement2UsageTargetAdapter(element).findUsages(); + FindManager.getInstance(element.getProject()).findUsages(element); } @Override diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java index 2c15e36fcb5b..915e15bac07c 100644 --- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.find.FindManager; +import com.intellij.find.FindSettings; import com.intellij.find.findUsages.*; import com.intellij.find.impl.FindManagerImpl; import com.intellij.icons.AllIcons; @@ -47,7 +48,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; -import com.intellij.psi.SmartPsiElementPointer; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.PsiElementProcessor; @@ -232,8 +232,6 @@ public class ShowUsagesAction extends AnAction implements PopupAction { final List usages = new ArrayList(); final Set visibleNodes = new LinkedHashSet(); - UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = - new UsageInfoToUsageConverter.TargetElementsDescriptor(handler.getPrimaryElements(), handler.getSecondaryElements()); final MyTable table = new MyTable(); final AsyncProcessIcon processIcon = new AsyncProcessIcon("xxx"); @@ -253,7 +251,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { SpeedSearchBase speedSearch = new MySpeedSearch(table); speedSearch.setComparator(new SpeedSearchComparator(false)); - final JBPopup popup = createUsagePopup(usages, descriptor, visibleNodes, handler, editor, popupPosition, + final JBPopup popup = createUsagePopup(usages, visibleNodes, handler, editor, popupPosition, maxUsages, usageView, options, table, presentation, processIcon, hadMoreSeparator); Disposer.register(popup, usageView); @@ -333,7 +331,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { } }; - final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, descriptor, collect, options, new Runnable() { + final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, handler.getPrimaryElements(), handler.getSecondaryElements(), collect, options, new Runnable() { @Override public void run() { ApplicationManager.getApplication().invokeLater(new Runnable() { @@ -552,7 +550,6 @@ public class ShowUsagesAction extends AnAction implements PopupAction { @NotNull private JBPopup createUsagePopup(@NotNull final List usages, - @NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, @NotNull Set visibleNodes, @NotNull final FindUsagesHandler handler, final Editor editor, @@ -639,7 +636,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction { } }; final DefaultActionGroup pinGroup = new DefaultActionGroup(); - final ActiveComponent pin = createPinButton(descriptor, usageView, options, popup, pinGroup); + final ActiveComponent pin = createPinButton(handler, usageView, options, popup, pinGroup); builder.setCommandButton(new CompositeActiveComponent(spinningProgress, settingsButton, pin)); DefaultActionGroup toolbar = new DefaultActionGroup(); @@ -672,9 +669,11 @@ public class ShowUsagesAction extends AnAction implements PopupAction { return popup[0]; } - private ActiveComponent createPinButton(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, - final UsageViewImpl usageView, - final FindUsagesOptions options, final JBPopup[] popup, DefaultActionGroup pinGroup) { + private ActiveComponent createPinButton(@NotNull final FindUsagesHandler handler, + @NotNull final UsageViewImpl usageView, + @NotNull final FindUsagesOptions options, + @NotNull final JBPopup[] popup, + @NotNull DefaultActionGroup pinGroup) { final AnAction pinAction = new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", AllIcons.General.AutohideOff) { { @@ -687,12 +686,8 @@ public class ShowUsagesAction extends AnAction implements PopupAction { hideHints(); popup[0].cancel(); FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager(); - FindUsagesManager.SearchData data = new FindUsagesManager.SearchData(); - data.myOptions = options; - List> plist = descriptor.getAllElementPointers(); - - data.myElements = plist.toArray(new SmartPsiElementPointer[plist.size()]); - findUsagesManager.rerunAndRecallFromHistory(data); + findUsagesManager.findUsages(handler.getPrimaryElements(), handler.getSecondaryElements(), handler, options, + FindSettings.getInstance().isSkipResultsWithOneUsage()); } }; pinGroup.add(pinAction); diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java index eff13250fb1e..4c11fe213535 100644 --- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java +++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,30 +21,21 @@ import com.intellij.find.FindModel; import com.intellij.find.FindSettings; import com.intellij.find.FindUtil; import com.intellij.find.impl.FindInProjectUtil; +import com.intellij.find.impl.FindManagerImpl; import com.intellij.find.replaceInProject.ReplaceInProjectManager; -import com.intellij.ide.DataManager; -import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiFile; import com.intellij.ui.content.Content; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewManager; import com.intellij.usages.*; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; public class FindInProjectManager { private final Project myProject; @@ -87,151 +78,68 @@ public class FindInProjectManager { @Override public void run() { findModel.setOpenInNewTabVisible(false); - final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject); - if (findModel.getDirectoryName() != null && psiDirectory == null){ - return; - } if (isOpenInNewTabEnabled) { myToOpenInNewTab = toOpenInNewTab[0] = findModel.isOpenInNewTab(); } - com.intellij.usages.UsageViewManager manager = com.intellij.usages.UsageViewManager.getInstance(myProject); - - if (manager == null) return; - findManager.getFindInProjectModel().copyFrom(findModel); - final FindModel findModelCopy = (FindModel)findModel.clone(); - final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(myToOpenInNewTab, findModelCopy); - final boolean showPanelIfOnlyOneUsage = !FindSettings.getInstance().isSkipResultsWithOneUsage(); - - final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, showPanelIfOnlyOneUsage, presentation); - UsageTarget usageTarget = StringUtil.isEmpty(findModel.getStringToFind()) ? createFileByTypeTarget(findModel) - : new FindInProjectUtil.StringUsageTarget(myProject, findModel.getStringToFind()); - manager.searchAndShowUsages(new UsageTarget[] {usageTarget}, - new Factory() { - @Override - public UsageSearcher create() { - return new UsageSearcher() { - @Override - public void generate(@NotNull final Processor processor) { - myIsFindInProgress = true; - - try { - Processor consumer = new Processor() { - @Override - public boolean process(UsageInfo info) { - Usage usage = UsageInfo2UsageAdapter.CONVERTER.fun(info); - usage.getPresentation().getIcon(); // cache icon - return processor.process(usage); - } - }; - FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation); - } - finally { - myIsFindInProgress = false; - } - } - }; - } - }, - processPresentation, - presentation, - null - ); + startFindInProject(findModel); } + }); findModel.setOpenInNewTabVisible(false); } - @NotNull - private ConfigurableUsageTarget createFileByTypeTarget(@NotNull FindModel model) { - final String filter = model.getFileFilter(); - return new ConfigurableUsageTarget() { - @Override - public void showSettings() { - Content selectedContent = UsageViewManager.getInstance(myProject).getSelectedContent(true); - JComponent component = selectedContent == null ? null : selectedContent.getComponent(); - findInProject(DataManager.getInstance().getDataContext(component)); - } + public void startFindInProject(@NotNull FindModel findModel) { + final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject); + if (findModel.getDirectoryName() != null && psiDirectory == null){ + return; + } - @Override - public void findUsages() { - throw new IncorrectOperationException(); - } + com.intellij.usages.UsageViewManager manager = com.intellij.usages.UsageViewManager.getInstance(myProject); - @Override - public void findUsagesInEditor(@NotNull FileEditor editor) { - throw new IncorrectOperationException(); - } + if (manager == null) return; + final FindManager findManager = FindManager.getInstance(myProject); + findManager.getFindInProjectModel().copyFrom(findModel); + final FindModel findModelCopy = (FindModel)findModel.clone(); + final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(myToOpenInNewTab, findModelCopy); + final boolean showPanelIfOnlyOneUsage = !FindSettings.getInstance().isSkipResultsWithOneUsage(); - @Override - public void highlightUsages(@NotNull PsiFile file, @NotNull Editor editor, boolean clearHighlights) { - throw new IncorrectOperationException(); - } + final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, showPanelIfOnlyOneUsage, presentation); + ConfigurableUsageTarget usageTarget = new FindInProjectUtil.StringUsageTarget(myProject, findModel); - @Override - public boolean isValid() { - return true; - } + ((FindManagerImpl)FindManager.getInstance(myProject)).getFindUsagesManager().addToHistory(usageTarget); - @Override - public boolean isReadOnly() { - return false; - } + manager.searchAndShowUsages(new UsageTarget[] {usageTarget}, + new Factory() { + @Override + public UsageSearcher create() { + return new UsageSearcher() { + @Override + public void generate(@NotNull final Processor processor) { + myIsFindInProgress = true; - @Nullable - @Override - public VirtualFile[] getFiles() { - return VirtualFile.EMPTY_ARRAY; - } - - @Override - public void update() { - } - - @Nullable - @Override - public String getName() { - return "Files with mask \""+filter+"\""; - } - - @Nullable - @Override - public ItemPresentation getPresentation() { - return new ItemPresentation() { - @Nullable - @Override - public String getPresentableText() { - return getName(); - } - - @Nullable - @Override - public String getLocationString() { - return null; - } - - @Nullable - @Override - public Icon getIcon(boolean unused) { - return null; - } - }; - } - - @Override - public void navigate(boolean requestFocus) { - } - - @Override - public boolean canNavigate() { - return false; - } - - @Override - public boolean canNavigateToSource() { - return false; - } - }; + try { + Processor consumer = new Processor() { + @Override + public boolean process(UsageInfo info) { + Usage usage = UsageInfo2UsageAdapter.CONVERTER.fun(info); + usage.getPresentation().getIcon(); // cache icon + return processor.process(usage); + } + }; + FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation); + } + finally { + myIsFindInProgress = false; + } + } + }; + } + }, + processPresentation, + presentation, + null + ); } public boolean isWorkInProgress() { diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 31cba707aca1..df180eb4261d 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.find.FindBundle; +import com.intellij.find.FindSettings; import com.intellij.lang.findUsages.LanguageFindUsages; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.ActionManager; @@ -49,7 +50,6 @@ import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.psi.*; import com.intellij.psi.search.*; -import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.LightweightHint; import com.intellij.ui.content.Content; import com.intellij.usageView.UsageInfo; @@ -57,6 +57,7 @@ import com.intellij.usageView.UsageViewManager; import com.intellij.usageView.UsageViewUtil; import com.intellij.usages.*; import com.intellij.util.CommonProcessors; +import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; @@ -66,13 +67,14 @@ import org.jetbrains.annotations.Nullable; import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; import javax.swing.*; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +/** + * see {@link com.intellij.find.impl.FindManagerImpl#getFindUsagesManager()} + */ public class FindUsagesManager implements JDOMExternalizable { private static final Logger LOG = Logger.getInstance("#com.intellij.find.findParameterUsages.FindUsagesManager"); @@ -89,27 +91,9 @@ public class FindUsagesManager implements JDOMExternalizable { private final com.intellij.usages.UsageViewManager myAnotherManager; private boolean myToOpenInNewTab = true; - public static class SearchData { - public SmartPsiElementPointer[] myElements = null; - public FindUsagesOptions myOptions = null; - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final SearchData that = (SearchData)o; - - return Arrays.equals(myElements, that.myElements) - && (myOptions != null ? myOptions.equals(that.myOptions) : that.myOptions == null); - } - - public int hashCode() { - return myElements != null ? Arrays.hashCode(myElements) : 0; - } - } - - private SearchData myLastSearchInFileData = new SearchData(); - private final List myFindUsagesHistory = ContainerUtil.createLockFreeCopyOnWriteList(); + private PsiElement2UsageTargetComposite myLastSearchInFileData; + private final UsageHistory myHistory = new UsageHistory(); public FindUsagesManager(@NotNull Project project, @NotNull com.intellij.usages.UsageViewManager anotherManager) { myProject = project; @@ -134,8 +118,7 @@ public class FindUsagesManager implements JDOMExternalizable { } public void clearFindingNextUsageInFile() { - myLastSearchInFileData.myOptions = null; - myLastSearchInFileData.myElements = null; + myLastSearchInFileData = null; } public boolean findNextUsageInFile(@NotNull FileEditor editor) { @@ -157,11 +140,16 @@ public class FindUsagesManager implements JDOMExternalizable { } private boolean findUsageInFile(@NotNull FileEditor editor, @NotNull FileSearchScope direction) { - PsiElement[] elements = restorePsiElements(myLastSearchInFileData, true); - if (elements == null) return false; - if (elements.length == 0) return true; //all elements have been invalidated - - UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(elements); + if (myLastSearchInFileData == null) return false; + PsiElement[] primaryElements = myLastSearchInFileData.getPrimaryElements(); + PsiElement[] secondaryElements = myLastSearchInFileData.getSecondaryElements(); + if (primaryElements.length == 0) {//all elements have been invalidated + Messages.showMessageDialog(myProject, FindBundle.message("find.searched.elements.have.been.changed.error"), + FindBundle.message("cannot.search.for.usages.title"), Messages.getInformationIcon()); + // SCR #10022 + //clearFindingNextUsageInFile(); + return false; + } //todo TextEditor textEditor = (TextEditor)editor; @@ -169,49 +157,15 @@ public class FindUsagesManager implements JDOMExternalizable { PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document); if (psiFile == null) return false; - final FindUsagesHandler handler = getFindUsagesHandler(elements[0], false); + final FindUsagesHandler handler = getFindUsagesHandler(primaryElements[0], false); if (handler == null) return false; - findUsagesInEditor(descriptor, handler, psiFile, direction, myLastSearchInFileData.myOptions, textEditor); + findUsagesInEditor(primaryElements, secondaryElements, handler, psiFile, direction, myLastSearchInFileData.myOptions, textEditor); return true; } - // returns null if cannot find, empty Pair if all elements have been changed - @Nullable - private PsiElement[] restorePsiElements(@NotNull SearchData searchData, final boolean showErrorMessage) { - SmartPsiElementPointer[] lastSearchElements = searchData.myElements; - if (lastSearchElements == null) return null; - List elements = new ArrayList(); - for (SmartPsiElementPointer pointer : lastSearchElements) { - PsiElement element = pointer.getElement(); - if (element != null) elements.add(element); - } - if (elements.isEmpty() && showErrorMessage) { - Messages.showMessageDialog(myProject, FindBundle.message("find.searched.elements.have.been.changed.error"), - FindBundle.message("cannot.search.for.usages.title"), Messages.getInformationIcon()); - // SCR #10022 - //clearFindingNextUsageInFile(); - return PsiElement.EMPTY_ARRAY; - } - return PsiUtilCore.toPsiElementArray(elements); - } - - private void initLastSearchElement(@NotNull FindUsagesOptions findUsagesOptions, - @NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor) { - myLastSearchInFileData = createSearchData(descriptor.getAllElements(), findUsagesOptions); - } - - @NotNull - private SearchData createSearchData(@NotNull List psiElements, final FindUsagesOptions findUsagesOptions) { - SearchData data = new SearchData(); - - data.myElements = new SmartPsiElementPointer[psiElements.size()]; - int idx = 0; - for (PsiElement psiElement : psiElements) { - data.myElements[idx++] = SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(psiElement); - } - data.myOptions = findUsagesOptions; - return data; + private void initLastSearchElement(@NotNull FindUsagesOptions findUsagesOptions, @NotNull PsiElement[] primaryElements,@NotNull PsiElement[] secondaryElements) { + myLastSearchInFileData = new PsiElement2UsageTargetComposite(primaryElements, secondaryElements, findUsagesOptions); } @Nullable @@ -274,21 +228,40 @@ public class FindUsagesManager implements JDOMExternalizable { findUsagesOptions.searchScope = getMaximalScope(handler); } + clearFindingNextUsageInFile(); + + startFindUsages(findUsagesOptions, handler, scopeFile, editor); + } + + void startFindUsages(@NotNull PsiElement psiElement, + @NotNull FindUsagesOptions findUsagesOptions, + PsiFile scopeFile, + FileEditor editor) { + FindUsagesHandler handler = getNewFindUsagesHandler(psiElement, false); + if (handler == null) return; + startFindUsages(findUsagesOptions, handler, scopeFile, editor); + } + + void startFindUsages(@NotNull FindUsagesOptions findUsagesOptions, + @NotNull FindUsagesHandler handler, + PsiFile scopeFile, + FileEditor editor) { + boolean singleFile = scopeFile != null; + clearFindingNextUsageInFile(); LOG.assertTrue(handler.getPsiElement().isValid()); PsiElement[] primaryElements = handler.getPrimaryElements(); checkNotNull(primaryElements, handler, "getPrimaryElements()"); PsiElement[] secondaryElements = handler.getSecondaryElements(); checkNotNull(secondaryElements, handler, "getSecondaryElements()"); - UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = - new UsageInfoToUsageConverter.TargetElementsDescriptor(primaryElements, secondaryElements); if (singleFile) { findUsagesOptions = findUsagesOptions.clone(); editor.putUserData(KEY_START_USAGE_AGAIN, null); - findUsagesInEditor(descriptor, handler, scopeFile, FileSearchScope.FROM_START, findUsagesOptions, editor); + findUsagesInEditor(primaryElements, secondaryElements, handler, scopeFile, FileSearchScope.FROM_START, findUsagesOptions, editor); } else { - findUsages(descriptor, handler, dialog.isSkipResultsWhenOneUsage(), dialog.isShowInSeparateWindow(), findUsagesOptions); + boolean skipResultsWithOneUsage = FindSettings.getInstance().isSkipResultsWithOneUsage(); + findUsages(primaryElements, secondaryElements, handler, findUsagesOptions, skipResultsWithOneUsage); } } @@ -299,12 +272,12 @@ public class FindUsagesManager implements JDOMExternalizable { ((ConfigurableUsageTarget)target).showSettings(); } - private static void checkNotNull(@NotNull PsiElement[] primaryElements, + private static void checkNotNull(@NotNull PsiElement[] elements, @NotNull FindUsagesHandler handler, @NonNls @NotNull String methodName) { - for (PsiElement element : primaryElements) { + for (PsiElement element : elements) { if (element == null) { - LOG.error(handler + "." + methodName + " has returned array with null elements: " + Arrays.asList(primaryElements)); + LOG.error(handler + "." + methodName + " has returned array with null elements: " + Arrays.asList(elements)); } } } @@ -312,8 +285,7 @@ public class FindUsagesManager implements JDOMExternalizable { public boolean isUsed(@NotNull PsiElement element, @NotNull FindUsagesOptions findUsagesOptions) { FindUsagesHandler handler = getFindUsagesHandler(element, true); if (handler == null) return false; - UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(element); - UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, null); + UsageSearcher usageSearcher = createUsageSearcher(new PsiElement[]{element}, PsiElement.EMPTY_ARRAY, handler, findUsagesOptions, null); final AtomicBoolean used = new AtomicBoolean(); usageSearcher.generate(new Processor() { @Override @@ -341,11 +313,12 @@ public class FindUsagesManager implements JDOMExternalizable { @NotNull public static ProgressIndicator startProcessUsages(@NotNull FindUsagesHandler handler, - @NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, + @NotNull final PsiElement[] primaryElements, + @NotNull final PsiElement[] secondaryElements, @NotNull final Processor processor, @NotNull FindUsagesOptions findUsagesOptions, @NotNull final Runnable onComplete) { - final UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, null); + final UsageSearcher usageSearcher = createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, null); final ProgressIndicatorBase indicator = new ProgressIndicatorBase(); dropResolveCacheRegularly(indicator, handler.getProject()); @@ -393,16 +366,17 @@ public class FindUsagesManager implements JDOMExternalizable { @NotNull - private static UsageSearcher createUsageSearcher(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, + private static UsageSearcher createUsageSearcher(@NotNull final PsiElement[] primaryElements, + @NotNull final PsiElement[] secondaryElements, @NotNull final FindUsagesHandler handler, - @NotNull FindUsagesOptions _options, + @NotNull FindUsagesOptions options, final PsiFile scopeFile) { - final FindUsagesOptions options = _options.clone(); + final FindUsagesOptions optionsClone = options.clone(); return new UsageSearcher() { @Override public void generate(@NotNull final Processor processor) { if (scopeFile != null) { - options.searchScope = new LocalSearchScope(scopeFile); + optionsClone.searchScope = new LocalSearchScope(scopeFile); } final Processor usageInfoProcessor = new CommonProcessors.UniqueProcessor(new Processor() { @Override @@ -410,21 +384,15 @@ public class FindUsagesManager implements JDOMExternalizable { Usage usage = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public Usage compute() { - return UsageInfoToUsageConverter.convert(descriptor, usageInfo); + return UsageInfoToUsageConverter.convert(primaryElements, usageInfo); } }); return processor.process(usage); } }); - final List elements = - ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public List compute() { - return descriptor.getAllElements(); - } - }); + final Iterable elements = ContainerUtil.concat(primaryElements, secondaryElements); - options.fastTrack = new SearchRequestCollector(new SearchSession()); + optionsClone.fastTrack = new SearchRequestCollector(new SearchSession()); try { for (final PsiElement element : elements) { @@ -434,10 +402,10 @@ public class FindUsagesManager implements JDOMExternalizable { LOG.assertTrue(element.isValid()); } }); - handler.processElementUsages(element, usageInfoProcessor, options); + handler.processElementUsages(element, usageInfoProcessor, optionsClone); for (CustomUsageSearcher searcher : Extensions.getExtensions(CustomUsageSearcher.EP_NAME)) { try { - searcher.processElementUsages(element, processor, options); + searcher.processElementUsages(element, processor, optionsClone); } catch (IndexNotReadyException e) { DumbService.getInstance(element.getProject()).showDumbModeNotification("Find usages is not available during indexing"); @@ -451,11 +419,11 @@ public class FindUsagesManager implements JDOMExternalizable { Project project = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public Project compute() { - return scopeFile != null ? scopeFile.getProject() : !elements.isEmpty() ? elements.get(0).getProject() : handler.getProject(); + return scopeFile != null ? scopeFile.getProject() : primaryElements[0].getProject(); } }); PsiSearchHelper.SERVICE.getInstance(project) - .processRequests(options.fastTrack, new Processor() { + .processRequests(optionsClone.fastTrack, new Processor() { @Override public boolean process(final PsiReference ref) { UsageInfo info = ApplicationManager.getApplication().runReadAction(new Computable() { @@ -470,40 +438,45 @@ public class FindUsagesManager implements JDOMExternalizable { }); } finally { - options.fastTrack = null; + optionsClone.fastTrack = null; } } }; } - @NotNull - private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(@NotNull List elementsToSearch) { - final List targets = new ArrayList(elementsToSearch.size()); - for (PsiElement element : elementsToSearch) { - convertToUsageTarget(targets, element); - } + private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(@NotNull Iterable elementsToSearch, + @NotNull final FindUsagesOptions findUsagesOptions) { + final List targets = ContainerUtil.map(elementsToSearch, + new Function() { + @Override + public PsiElement2UsageTargetAdapter fun(PsiElement element) { + return convertToUsageTarget(element, findUsagesOptions); + } + }); return targets.toArray(new PsiElement2UsageTargetAdapter[targets.size()]); } - private void findUsages(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, - @NotNull final FindUsagesHandler handler, - final boolean toSkipUsagePanelWhenOneUsage, - final boolean toOpenInNewTab, - @NotNull final FindUsagesOptions findUsagesOptions) { - List elements = descriptor.getAllElements(); - if (elements.isEmpty()) { + public void findUsages(@NotNull final PsiElement[] primaryElements, + @NotNull final PsiElement[] secondaryElements, + @NotNull final FindUsagesHandler handler, + @NotNull final FindUsagesOptions findUsagesOptions, + final boolean toSkipUsagePanelWhenOneUsage) { + + if (primaryElements.length == 0) { throw new AssertionError(handler + " " + findUsagesOptions); } - final UsageTarget[] targets = convertToUsageTargets(elements); + Iterable allElements = ContainerUtil.concat(primaryElements, secondaryElements); + final UsageTarget[] targets = convertToUsageTargets(allElements, findUsagesOptions); myAnotherManager.searchAndShowUsages(targets, new Factory() { @Override public UsageSearcher create() { dropResolveCacheRegularly(ProgressManager.getInstance().getProgressIndicator(), myProject); - return createUsageSearcher(descriptor, handler, findUsagesOptions, null); + return createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, null); } - }, !toSkipUsagePanelWhenOneUsage, true, createPresentation(elements.get(0), findUsagesOptions, toOpenInNewTab), null); - addToHistory(elements, findUsagesOptions); + }, !toSkipUsagePanelWhenOneUsage, true, createPresentation(primaryElements[0], findUsagesOptions, shouldOpenInNewTab()), null); + myHistory.add((ConfigurableUsageTarget)targets[0]); + //addToHistory(allElements, findUsagesOptions); } private static void dropResolveCacheRegularly(ProgressIndicator indicator, final Project project) { @@ -546,19 +519,20 @@ public class FindUsagesManager implements JDOMExternalizable { return presentation; } - private void findUsagesInEditor(@NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, + private void findUsagesInEditor(@NotNull final PsiElement[] primaryElements, + @NotNull final PsiElement[] secondaryElements, @NotNull FindUsagesHandler handler, @NotNull PsiFile scopeFile, @NotNull FileSearchScope direction, @NotNull final FindUsagesOptions findUsagesOptions, @NotNull FileEditor fileEditor) { - initLastSearchElement(findUsagesOptions, descriptor); + initLastSearchElement(findUsagesOptions, primaryElements, secondaryElements); clearStatusBar(); final FileEditorLocation currentLocation = fileEditor.getCurrentLocation(); - final UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, scopeFile); + final UsageSearcher usageSearcher = createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, scopeFile); AtomicBoolean usagesWereFound = new AtomicBoolean(); Usage fUsage = findSiblingUsage(usageSearcher, direction, currentLocation, usagesWereFound, fileEditor); @@ -568,12 +542,12 @@ public class FindUsagesManager implements JDOMExternalizable { fUsage.selectInEditor(); } else if (!usagesWereFound.get()) { - String message = getNoUsagesFoundMessage(descriptor.getPrimaryElements()[0]) + " in " + scopeFile.getName(); + String message = getNoUsagesFoundMessage(primaryElements[0]) + " in " + scopeFile.getName(); showHintOrStatusBarMessage(message, fileEditor); } else { fileEditor.putUserData(KEY_START_USAGE_AGAIN, VALUE_START_USAGE_AGAIN); - showHintOrStatusBarMessage(getSearchAgainMessage(descriptor.getPrimaryElements()[0], direction), fileEditor); + showHintOrStatusBarMessage(getSearchAgainMessage(primaryElements[0], direction), fileEditor); } } @@ -675,13 +649,12 @@ public class FindUsagesManager implements JDOMExternalizable { return foundUsage.get(); } - private static void convertToUsageTarget(@NotNull List targets, @NotNull PsiElement elementToSearch) { + private static PsiElement2UsageTargetAdapter convertToUsageTarget(@NotNull PsiElement elementToSearch, + @NotNull FindUsagesOptions findUsagesOptions) { if (elementToSearch instanceof NavigationItem) { - targets.add(new PsiElement2UsageTargetAdapter(elementToSearch)); - } - else { - throw new IllegalArgumentException("Wrong usage target:" + elementToSearch + "; " + elementToSearch.getClass()); + return new PsiElement2UsageTargetAdapter(elementToSearch,findUsagesOptions); } + throw new IllegalArgumentException("Wrong usage target:" + elementToSearch + "; " + elementToSearch.getClass()); } @NotNull @@ -702,55 +675,21 @@ public class FindUsagesManager implements JDOMExternalizable { return LanguageFindUsages.INSTANCE.forLanguage(element.getLanguage()).getHelpId(element); } - private void addToHistory(final List elements, final FindUsagesOptions findUsagesOptions) { - SearchData data = createSearchData(elements, findUsagesOptions); - myFindUsagesHistory.remove(data); - myFindUsagesHistory.add(data); - - // todo configure history depth limit - if (myFindUsagesHistory.size() > 15) { - myFindUsagesHistory.remove(0); - } + public void rerunAndRecallFromHistory(@NotNull ConfigurableUsageTarget usageTarget) { + usageTarget.findUsages(); + addToHistory(usageTarget); } - public void rerunAndRecallFromHistory(@NotNull SearchData searchData) { - myFindUsagesHistory.remove(searchData); - PsiElement[] elements = restorePsiElements(searchData, true); - if (elements == null || elements.length == 0) return; - UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(elements); - final FindUsagesHandler handler = getFindUsagesHandler(elements[0], false); - if (handler == null) return; - findUsages(descriptor, handler, false, false, searchData.myOptions); + public void addToHistory(@NotNull ConfigurableUsageTarget usageTarget) { + myHistory.add(usageTarget); } - // most recent entry is at the end of the list - public List getFindUsageHistory() { - removeInvalidElementsFromHistory(); - return Collections.unmodifiableList(myFindUsagesHistory); - } - - private void removeInvalidElementsFromHistory() { - for (SearchData data : myFindUsagesHistory) { - PsiElement[] elements = restorePsiElements(data, false); - if (elements == null || elements.length == 0) myFindUsagesHistory.remove(data); - } - } - - @NotNull - private static PsiElement[] getPsiElements(@NotNull UsageTarget[] targets) { - List result = new ArrayList(); - for (UsageTarget target : targets) { - if (target instanceof PsiElementUsageTarget) { - PsiElement element = ((PsiElementUsageTarget)target).getElement(); - if (element != null) { - result.add(element); - } - } - } - return PsiUtilCore.toPsiElementArray(result); + public UsageHistory getHistory() { + return myHistory; } + @NotNull public static GlobalSearchScope getMaximalScope(@NotNull FindUsagesHandler handler) { PsiElement element = handler.getPsiElement(); diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java index 30fa59246d76..e5119f26d088 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -17,31 +17,40 @@ package com.intellij.find.findUsages; import com.intellij.codeInsight.highlighting.HighlightUsagesHandler; +import com.intellij.find.FindBundle; import com.intellij.find.FindManager; import com.intellij.find.impl.FindManagerImpl; +import com.intellij.lang.findUsages.DescriptiveNameUtil; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; import com.intellij.navigation.PsiElementNavigationItem; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.actionSystem.DataSink; +import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.actionSystem.TypeSafeDataProvider; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; import com.intellij.psi.meta.PsiPresentableMetaData; import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.ui.ComputableIcon; import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewBundle; import com.intellij.usageView.UsageViewUtil; +import com.intellij.usages.ConfigurableUsageTarget; import com.intellij.usages.PsiElementUsageTarget; import com.intellij.usages.UsageView; +import com.intellij.usages.impl.UsageViewImpl; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -51,49 +60,55 @@ import java.util.Collection; /** * @author max */ -public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, TypeSafeDataProvider, PsiElementNavigationItem { +public class PsiElement2UsageTargetAdapter + implements PsiElementUsageTarget, TypeSafeDataProvider, PsiElementNavigationItem, ItemPresentation, ConfigurableUsageTarget { private final SmartPsiElementPointer myPointer; - private final MyItemPresentation myPresentation; + @NotNull protected final FindUsagesOptions myOptions; - public PsiElement2UsageTargetAdapter(@NotNull PsiElement element) { + public PsiElement2UsageTargetAdapter(@NotNull PsiElement element, @NotNull FindUsagesOptions options) { + myOptions = options; myPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element); if (!(element instanceof NavigationItem)) { throw new IllegalArgumentException("Element is not a navigation item: " + element); } + update(element); + } - myPresentation = new MyItemPresentation(); + public PsiElement2UsageTargetAdapter(@NotNull PsiElement element) { + this(element, new FindUsagesOptions(element.getProject())); } @Override public String getName() { - return getNavigationItem().getName(); + PsiElement element = getElement(); + return element instanceof NavigationItem ? ((NavigationItem)element).getName() : null; } @Override @NotNull public ItemPresentation getPresentation() { - return myPresentation; + return this; } @Override public void navigate(boolean requestFocus) { - if (!canNavigate()) return; - getNavigationItem().navigate(requestFocus); + PsiElement element = getElement(); + if (element instanceof Navigatable && ((Navigatable)element).canNavigate()) { + ((Navigatable)element).navigate(requestFocus); + } } @Override public boolean canNavigate() { - return isValid() && getNavigationItem().canNavigate(); + PsiElement element = getElement(); + return element instanceof Navigatable && ((Navigatable)element).canNavigate(); } @Override public boolean canNavigateToSource() { - return isValid() && getNavigationItem().canNavigateToSource(); - } - - private NavigationItem getNavigationItem() { - return (NavigationItem)getElement(); + PsiElement element = getElement(); + return element instanceof Navigatable && ((Navigatable)element).canNavigateToSource(); } @Override @@ -102,13 +117,14 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ } public String toString() { - return myPresentation.getPresentableText(); + return getPresentableText(); } @Override public void findUsages() { PsiElement element = getElement(); - FindManager.getInstance(element.getProject()).findUsages(element); + if (element == null) return; + ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager().startFindUsages(element, myOptions, null, null); } @Override @@ -164,12 +180,8 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ return virtualFile == null ? null : new VirtualFile[]{virtualFile}; } - @Override - public void update() { - myPresentation.update(); - } - - public static PsiElement2UsageTargetAdapter[] convert(PsiElement[] psiElements) { + @NotNull + public static PsiElement2UsageTargetAdapter[] convert(@NotNull PsiElement[] psiElements) { PsiElement2UsageTargetAdapter[] targets = new PsiElement2UsageTargetAdapter[psiElements.length]; for (int i = 0; i < targets.length; i++) { targets[i] = new PsiElement2UsageTargetAdapter(psiElements[i]); @@ -188,6 +200,27 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ } } + @Override + public KeyboardShortcut getShortcut() { + return UsageViewImpl.getShowUsagesWithSettingsShortcut(); + } + + @NotNull + @Override + public String getLongDescriptiveName() { + SearchScope searchScope = myOptions.searchScope; + String scopeString = searchScope == null ? null : searchScope.getDisplayName(); + PsiElement psiElement = getElement(); + + return psiElement == null ? UsageViewBundle.message("node.invalid") : + FindBundle.message("recent.find.usages.action.popup", StringUtil.capitalize(UsageViewUtil.getType(psiElement)), + DescriptiveNameUtil.getDescriptiveName(psiElement), + scopeString == null + ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName() + : scopeString + ); + } + @Override public void showSettings() { FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(myPointer.getProject())).getFindUsagesManager(); @@ -197,58 +230,56 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ } } - private class MyItemPresentation implements ItemPresentation { - private String myPresentableText; - private ComputableIcon myIconOpen; - private ComputableIcon myIconClosed; + private String myPresentableText; + private ComputableIcon myIconOpen; + private ComputableIcon myIconClosed; - public MyItemPresentation() { - update(); - } + @Override + public void update() { + update(getElement()); + } - public void update() { - final PsiElement element = getElement(); - if (element != null && element.isValid()) { - final ItemPresentation presentation = ((NavigationItem)element).getPresentation(); - myIconOpen = presentation != null ? ComputableIcon.create(presentation, true) : null; - myIconClosed = presentation != null ? ComputableIcon.create(presentation, false) : null; - myPresentableText = presentation != null ? presentation.getPresentableText() : UsageViewUtil.createNodeText(element); - if (myIconOpen == null || myIconClosed == null) { - if (element instanceof PsiMetaOwner) { - final PsiMetaOwner psiMetaOwner = (PsiMetaOwner)element; - final PsiMetaData metaData = psiMetaOwner.getMetaData(); - if (metaData instanceof PsiPresentableMetaData) { - final PsiPresentableMetaData psiPresentableMetaData = (PsiPresentableMetaData)metaData; - if (myIconOpen == null) myIconOpen = ComputableIcon.create(psiPresentableMetaData); - if (myIconClosed == null) myIconClosed = ComputableIcon.create(psiPresentableMetaData); - } + private void update(PsiElement element) { + if (element != null && element.isValid()) { + final ItemPresentation presentation = ((NavigationItem)element).getPresentation(); + myIconOpen = presentation == null ? null : ComputableIcon.create(presentation, true); + myIconClosed = presentation == null ? null : ComputableIcon.create(presentation, false); + myPresentableText = presentation == null ? UsageViewUtil.createNodeText(element) : presentation.getPresentableText(); + if (myIconOpen == null || myIconClosed == null) { + if (element instanceof PsiMetaOwner) { + final PsiMetaOwner psiMetaOwner = (PsiMetaOwner)element; + final PsiMetaData metaData = psiMetaOwner.getMetaData(); + if (metaData instanceof PsiPresentableMetaData) { + final PsiPresentableMetaData psiPresentableMetaData = (PsiPresentableMetaData)metaData; + if (myIconOpen == null) myIconOpen = ComputableIcon.create(psiPresentableMetaData); + if (myIconClosed == null) myIconClosed = ComputableIcon.create(psiPresentableMetaData); } - else if (element instanceof PsiFile) { - final PsiFile psiFile = (PsiFile)element; - final VirtualFile virtualFile = psiFile.getVirtualFile(); - if (virtualFile != null) { - myIconOpen = ComputableIcon.create(virtualFile); - myIconClosed = ComputableIcon.create(virtualFile); - } + } + else if (element instanceof PsiFile) { + final PsiFile psiFile = (PsiFile)element; + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile != null) { + myIconOpen = ComputableIcon.create(virtualFile); + myIconClosed = ComputableIcon.create(virtualFile); } } } } + } - @Override - public String getPresentableText() { - return myPresentableText; - } + @Override + public String getPresentableText() { + return myPresentableText; + } - @Override - public String getLocationString() { - return null; - } + @Override + public String getLocationString() { + return null; + } - @Override - public Icon getIcon(boolean open) { - final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed; - return computableIcon == null? null : computableIcon.getIcon(); - } + @Override + public Icon getIcon(boolean open) { + final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed; + return computableIcon == null ? null : computableIcon.getIcon(); } } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java new file mode 100644 index 000000000000..a16050a08b07 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java @@ -0,0 +1,70 @@ +/* + * 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.find.findUsages; + +import com.intellij.find.FindManager; +import com.intellij.find.FindSettings; +import com.intellij.find.impl.FindManagerImpl; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.usages.UsageInfoToUsageConverter; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public class PsiElement2UsageTargetComposite extends PsiElement2UsageTargetAdapter { + private final UsageInfoToUsageConverter.TargetElementsDescriptor myDescriptor; + public PsiElement2UsageTargetComposite(@NotNull PsiElement[] primaryElements, + @NotNull PsiElement[] secondaryElements, + @NotNull FindUsagesOptions options) { + super(primaryElements[0], options); + myDescriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(primaryElements, secondaryElements); + } + + @Override + public void findUsages() { + PsiElement element = getElement(); + if (element == null) return; + FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager(); + FindUsagesHandler handler = findUsagesManager.getNewFindUsagesHandler(element, false); + boolean skipResultsWithOneUsage = FindSettings.getInstance().isSkipResultsWithOneUsage(); + findUsagesManager.findUsages(myDescriptor.getPrimaryElements(), myDescriptor.getAdditionalElements(), handler, myOptions, skipResultsWithOneUsage); + } + + @Override + public VirtualFile[] getFiles() { + Set files = ContainerUtil.map2Set(myDescriptor.getAllElements(), new Function() { + @Override + public VirtualFile fun(PsiElement element) { + return PsiUtilCore.getVirtualFile(element); + } + }); + return VfsUtilCore.toVirtualFileArray(files); + } + + @NotNull + public PsiElement[] getPrimaryElements() { + return myDescriptor.getPrimaryElements(); + } + @NotNull + public PsiElement[] getSecondaryElements() { + return myDescriptor.getAdditionalElements(); + } +} diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java b/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java new file mode 100644 index 000000000000..7bd5147de340 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java @@ -0,0 +1,58 @@ +/* + * 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.find.findUsages; + +import com.intellij.openapi.util.Condition; +import com.intellij.usages.ConfigurableUsageTarget; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class UsageHistory { + // the last element is the most recent + private final List myHistory = ContainerUtil.createLockFreeCopyOnWriteList(); + + public void add(@NotNull ConfigurableUsageTarget usageTarget) { + final String descriptiveName = usageTarget.getLongDescriptiveName(); + ContainerUtil.retainAll(myHistory, new Condition() { + @Override + public boolean value(ConfigurableUsageTarget existing) { + return !existing.getLongDescriptiveName().equals(descriptiveName); + } + }); + myHistory.add(usageTarget); + + // todo configure history depth limit + if (myHistory.size() > 15) { + myHistory.remove(0); + } + } + + @NotNull + public List getAll() { + removeInvalidElementsFromHistory(); + return Collections.unmodifiableList(myHistory); + } + + private void removeInvalidElementsFromHistory() { + for (ConfigurableUsageTarget target : myHistory) { + if (!target.isValid()) myHistory.remove(target); + } + } + +} diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 078e4225ae9a..53ff0d438a20 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -20,11 +20,10 @@ import com.intellij.BundleBase; import com.intellij.find.*; import com.intellij.find.findInProject.FindInProjectManager; import com.intellij.find.ngrams.TrigramIndex; +import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.navigation.ItemPresentation; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.editor.Document; @@ -459,7 +458,8 @@ public class FindInProjectUtil { @NotNull final Project project, @Nullable final PsiDirectory psiDirectory, final Pattern fileMaskRegExp, - @Nullable final Module module, FileIndex fileIndex) { + @Nullable final Module module, + @NotNull FileIndex fileIndex) { if (DumbService.getInstance(project).isDumb()) { return new Pair>(false, Collections.emptyList()); } @@ -577,7 +577,7 @@ public class FindInProjectUtil { } private static int addToUsages(@NotNull Document document, @NotNull Processor consumer, @NotNull FindModel findModel, - @NotNull final PsiFile psiFile, int[] offsetRef, int maxUsages) { + @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) { int count = 0; CharSequence text = document.getCharsSequence(); int textLength = document.getTextLength(); @@ -616,39 +616,40 @@ public class FindInProjectUtil { return count; } + @NotNull private static String getTitleForScope(@NotNull final FindModel findModel) { - String result; - + String scopeName; if (findModel.isProjectScope()) { - result = FindBundle.message("find.scope.project.title"); + scopeName = FindBundle.message("find.scope.project.title"); } else if (findModel.getModuleName() != null) { - result = FindBundle.message("find.scope.module.title", findModel.getModuleName()); + scopeName = FindBundle.message("find.scope.module.title", findModel.getModuleName()); } else if(findModel.getCustomScopeName() != null) { - result = findModel.getCustomScopeName(); + scopeName = findModel.getCustomScopeName(); } else { - result = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName()); + scopeName = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName()); } + String result = scopeName; if (findModel.getFileFilter() != null) { - result = FindBundle.message("find.scope.files.with.mask", result, findModel.getFileFilter()); + result += " "+FindBundle.message("find.scope.files.with.mask", findModel.getFileFilter()); } return result; } @NotNull - public static UsageViewPresentation setupViewPresentation(final boolean toOpenInNewTab, @NotNull final FindModel findModelCopy) { + public static UsageViewPresentation setupViewPresentation(final boolean toOpenInNewTab, @NotNull FindModel findModel) { final UsageViewPresentation presentation = new UsageViewPresentation(); - final String scope = getTitleForScope(findModelCopy); - final String stringToFind = findModelCopy.getStringToFind(); + final String scope = getTitleForScope(findModel); + final String stringToFind = findModel.getStringToFind(); presentation.setScopeText(scope); if (stringToFind.isEmpty()) { presentation.setTabText("Files"); - presentation.setToolwindowTitle(BundleBase.format("Files in ''{0}''", scope)); + presentation.setToolwindowTitle(BundleBase.format("Files in {0}", scope)); presentation.setUsagesString("files"); } else { @@ -668,7 +669,6 @@ public class FindInProjectUtil { @NotNull final UsageViewPresentation presentation) { FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(); processPresentation.setShowNotFoundMessage(true); - processPresentation.setShowFindOptionsPrompt(false); processPresentation.setShowPanelIfOnlyOneUsage(showPanelIfOnlyOneUsage); processPresentation.setProgressIndicatorFactory( new Factory() { @@ -682,34 +682,43 @@ public class FindInProjectUtil { return processPresentation; } - public static class StringUsageTarget implements ConfigurableUsageTarget { + public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation { @NotNull private final Project myProject; - private final String myStringToFind; + @NotNull private final FindModel myFindModel; - private final ItemPresentation myItemPresentation = new ItemPresentation() { - @Override - public String getPresentableText() { - return FindBundle.message("find.usage.target.string.text", myStringToFind); - } - - @Override - public String getLocationString() { - return myStringToFind + "!!"; - } - - @Override - public Icon getIcon(boolean open) { - return null; - } - }; - - public StringUsageTarget(@NotNull Project project, @NotNull String _stringToFind) { + public StringUsageTarget(@NotNull Project project, @NotNull FindModel findModel) { myProject = project; - myStringToFind = _stringToFind; + myFindModel = findModel; } @Override - public void findUsages() {} + @NotNull + public String getPresentableText() { + UsageViewPresentation presentation = setupViewPresentation(false, myFindModel); + return presentation.getToolwindowTitle(); + } + + @NotNull + @Override + public String getLongDescriptiveName() { + return getPresentableText(); + } + + @Override + public String getLocationString() { + return myFindModel + "!!"; + } + + @Override + public Icon getIcon(boolean open) { + return AllIcons.Actions.Menu_find; + } + + @Override + public void findUsages() { + FindInProjectManager.getInstance(myProject).startFindInProject(myFindModel); + } + @Override public void findUsagesInEditor(@NotNull FileEditor editor) {} @Override @@ -737,12 +746,12 @@ public class FindInProjectUtil { @Override public String getName() { - return myStringToFind; + return myFindModel.getStringToFind().isEmpty() ? myFindModel.getFileFilter() : myFindModel.getStringToFind(); } @Override public ItemPresentation getPresentation() { - return myItemPresentation; + return this; } @Override @@ -767,5 +776,10 @@ public class FindInProjectUtil { FindInProjectManager findInProjectManager = FindInProjectManager.getInstance(myProject); findInProjectManager.findInProject(DataManager.getInstance().getDataContext(component)); } + + @Override + public KeyboardShortcut getShortcut() { + return ActionManager.getInstance().getKeyboardShortcut("FindInPath"); + } } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java index 77835ad8fb1e..4a72450b4287 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -19,21 +19,16 @@ package com.intellij.find.impl; import com.intellij.find.FindBundle; import com.intellij.find.FindManager; import com.intellij.find.findUsages.FindUsagesManager; -import com.intellij.lang.findUsages.DescriptiveNameUtil; +import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.search.ProjectScope; import com.intellij.ui.awt.RelativePoint; -import com.intellij.usageView.UsageViewBundle; -import com.intellij.usageView.UsageViewUtil; +import com.intellij.usages.ConfigurableUsageTarget; import com.intellij.usages.UsageView; import org.jetbrains.annotations.NotNull; @@ -60,7 +55,7 @@ public class ShowRecentFindUsagesAction extends AnAction { UsageView usageView = e.getData(UsageView.USAGE_VIEW_KEY); Project project = e.getData(CommonDataKeys.PROJECT); final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); - List history = new ArrayList(findUsagesManager.getFindUsageHistory()); + List history = new ArrayList(findUsagesManager.getHistory().getAll()); if (!history.isEmpty()) { // skip most recent find usage, it's under your nose @@ -68,42 +63,32 @@ public class ShowRecentFindUsagesAction extends AnAction { Collections.reverse(history); } if (history.isEmpty()) { - history.add(new FindUsagesManager.SearchData()); // to fill the popup + history.add(null); // to fill the popup } - BaseListPopupStep step = - new BaseListPopupStep(FindBundle.message("recent.find.usages.action.title"), history) { + BaseListPopupStep step = + new BaseListPopupStep(FindBundle.message("recent.find.usages.action.title"), history) { @Override - public Icon getIconFor(final FindUsagesManager.SearchData data) { - if (data.myElements == null) { - return null; - } - PsiElement psiElement = data.myElements[0].getElement(); - if (psiElement == null) return null; - return psiElement.getIcon(0); + public Icon getIconFor(final ConfigurableUsageTarget data) { + ItemPresentation presentation = data == null ? null : data.getPresentation(); + return presentation == null ? null : presentation.getIcon(false); } @Override @NotNull - public String getTextFor(final FindUsagesManager.SearchData data) { - if (data.myElements == null) { + public String getTextFor(final ConfigurableUsageTarget data) { + if (data == null) { return FindBundle.message("recent.find.usages.action.nothing"); } - PsiElement psiElement = data.myElements[0].getElement(); - if (psiElement == null) return UsageViewBundle.message("node.invalid"); - String scopeString = data.myOptions.searchScope == null ? null : data.myOptions.searchScope.getDisplayName(); - return FindBundle.message("recent.find.usages.action.description", - StringUtil.capitalize(UsageViewUtil.getType(psiElement)), - DescriptiveNameUtil.getDescriptiveName(psiElement), - scopeString == null ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName() : scopeString); + return data.getLongDescriptiveName(); } @Override - public PopupStep onChosen(final FindUsagesManager.SearchData selectedValue, final boolean finalChoice) { + public PopupStep onChosen(final ConfigurableUsageTarget selectedValue, final boolean finalChoice) { return doFinalStep(new Runnable() { @Override public void run() { - if (selectedValue.myElements != null) { + if (selectedValue != null) { findUsagesManager.rerunAndRecallFromHistory(selectedValue); } } @@ -118,6 +103,5 @@ public class ShowRecentFindUsagesAction extends AnAction { point = new RelativePoint(usageView.getComponent(), new Point(4, 4)); } JBPopupFactory.getInstance().createListPopup(step).show(point); - } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java index d9752a78a784..ccbb9962831c 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java +++ b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -16,16 +16,11 @@ package com.intellij.find.impl; -import com.intellij.find.FindBundle; import com.intellij.find.FindManager; import com.intellij.find.findUsages.FindUsagesManager; -import com.intellij.lang.findUsages.DescriptiveNameUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.search.ProjectScope; -import com.intellij.usageView.UsageViewUtil; +import com.intellij.usages.ConfigurableUsageTarget; import com.intellij.usages.impl.UsageViewImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,27 +47,22 @@ public class ShowRecentFindUsagesGroup extends ActionGroup { Project project = e.getData(CommonDataKeys.PROJECT); if (project == null) return EMPTY_ARRAY; final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); - List history = new ArrayList(findUsagesManager.getFindUsageHistory()); + List history = new ArrayList(findUsagesManager.getHistory().getAll()); Collections.reverse(history); String description = ActionManager.getInstance().getAction(UsageViewImpl.SHOW_RECENT_FIND_USAGES_ACTION_ID).getTemplatePresentation().getDescription(); List children = new ArrayList(history.size()); - for (final FindUsagesManager.SearchData data : history) { - if (data.myElements == null) { + for (final ConfigurableUsageTarget usageTarget : history) { + if (!usageTarget.isValid()) { continue; } - PsiElement psiElement = data.myElements[0].getElement(); - if (psiElement == null) continue; - String scopeString = data.myOptions.searchScope == null ? null : data.myOptions.searchScope.getDisplayName(); - String text = FindBundle.message("recent.find.usages.action.popup", StringUtil.capitalize(UsageViewUtil.getType(psiElement)), - DescriptiveNameUtil.getDescriptiveName(psiElement), - scopeString == null ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName() : scopeString); - AnAction action = new AnAction(text, description, psiElement.getIcon(0)) { + String text = usageTarget.getLongDescriptiveName(); + AnAction action = new AnAction(text, description, null) { @Override public void actionPerformed(final AnActionEvent e) { - findUsagesManager.rerunAndRecallFromHistory(data); + findUsagesManager.rerunAndRecallFromHistory(usageTarget); } }; children.add(action); diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java index c1608af7a6c3..8a14660e4b37 100644 --- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java +++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -162,7 +162,7 @@ public class ReplaceInProjectManager { final FindManager findManager) { presentation.setMergeDupLinesAvailable(false); final ReplaceContext[] context = new ReplaceContext[1]; - manager.searchAndShowUsages(new UsageTarget[]{new FindInProjectUtil.StringUsageTarget(myProject, findModelCopy.getStringToFind())}, + manager.searchAndShowUsages(new UsageTarget[]{new FindInProjectUtil.StringUsageTarget(myProject, findModelCopy)}, usageSearcherFactory, processPresentation, presentation, new UsageViewManager.UsageViewStateListener() { @Override public void usageViewCreated(@NotNull UsageView usageView) { diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java index 773e0994d0a5..2d73d8b18bad 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -32,7 +32,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilCore; import com.intellij.usageView.UsageInfo; -import com.intellij.usages.UsageInfoToUsageConverter; import com.intellij.util.Consumer; import javax.swing.*; @@ -110,7 +109,7 @@ public class DependenciesUsagesPanel extends UsagesPanel { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - showUsages(new UsageInfoToUsageConverter.TargetElementsDescriptor(_elementsToSearch), finalUsages); + showUsages(_elementsToSearch, finalUsages); } }, ModalityState.stateForComponent(DependenciesUsagesPanel.this)); } diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java index 125a4e33e0f6..8f4084b5504e 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -25,6 +25,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.psi.PsiElement; import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; import com.intellij.util.Alarm; @@ -64,12 +65,12 @@ public abstract class UsagesPanel extends JPanel implements Disposable, DataProv } } - protected void showUsages(@NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, @NotNull UsageInfo[] usageInfos) { + protected void showUsages(@NotNull PsiElement[] primaryElements, @NotNull UsageInfo[] usageInfos) { if (myCurrentUsageView != null) { Disposer.dispose(myCurrentUsageView); } try { - Usage[] usages = UsageInfoToUsageConverter.convert(descriptor, usageInfos); + Usage[] usages = UsageInfoToUsageConverter.convert(primaryElements, usageInfos); UsageViewPresentation presentation = new UsageViewPresentation(); presentation.setCodeUsagesString(getCodeUsagesString()); myCurrentUsageView = UsageViewManager.getInstance(myProject).createUsageView(UsageTarget.EMPTY_ARRAY, usages, presentation, null); diff --git a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java index 2cd0f7e19879..e6acbaa4adda 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -279,7 +279,7 @@ public class SafeDeleteProcessor extends BaseRefactoringProcessor { } return manager.showUsages(targets, - UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(myElements), usages), + UsageInfoToUsageConverter.convert(myElements, usages), presentation ); } diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties index 94433d20057c..fddb5b44656e 100644 --- a/platform/platform-resources-en/src/messages/FindBundle.properties +++ b/platform/platform-resources-en/src/messages/FindBundle.properties @@ -100,16 +100,15 @@ find.searching.for.string.in.file.occurrences.progress={0,choice,0#No|1#{0}} {0, find.excessive.total.size.prompt=Usages in files of total size {0} found. {1} may become unresponsive or even fail with OutOfMemoryError if you continue. Continue? find.progress.search.completed=Search completed find.scope.project.title=Project -find.scope.module.title=Module {0} +find.scope.module.title=Module ''{0}'' find.scope.directory.title=Directory {0} -find.scope.files.with.mask={0} Files with mask {1} -find.usage.target.string.text=String ''{0}'' +find.scope.files.with.mask=with mask ''{0}'' find.replace.invalid.replacement.string=You have entered malformed replacement string: ''{0}'' find.replace.invalid.replacement.string.title=Replace Error find.highlight.no.more.highlights.found=No more highlights found find.scope.all.project.classes=All Project Classes find.usage.view.tab.text=Occurrences of ''{0}'' -find.usage.view.toolwindow.title=Occurrences of ''{0}'' in ''{1}'' +find.usage.view.toolwindow.title=Occurrences of ''{0}'' in {1} find.usage.view.usages.text=occurrences of ''{0}'' diff --git a/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java b/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java index 5d250ebf0535..5f51c2ef0291 100644 --- a/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java +++ b/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -15,6 +15,12 @@ */ package com.intellij.usages; +import com.intellij.openapi.actionSystem.KeyboardShortcut; +import org.jetbrains.annotations.NotNull; + public interface ConfigurableUsageTarget extends UsageTarget { void showSettings(); + KeyboardShortcut getShortcut(); + @NotNull + String getLongDescriptiveName(); } diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java index 142a54edaf26..70bad8f859b0 100644 --- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java +++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -39,7 +39,7 @@ public class FindUsagesProcessPresentation { private boolean myShowNotFoundMessage; private Factory myProgressIndicatorFactory; private Collection myLargeFiles; - private boolean myShowFindOptionsPrompt = true; // in the case of find in path, "find options" does not make sense + private boolean myShowFindOptionsPrompt = true; public FindUsagesProcessPresentation() { } diff --git a/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java b/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java index 79c14cb2ae87..71cad734af06 100644 --- a/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java +++ b/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -20,6 +20,6 @@ import com.intellij.psi.PsiElement; /** * @author max */ -public interface PsiElementUsageTarget extends ConfigurableUsageTarget { +public interface PsiElementUsageTarget extends UsageTarget { PsiElement getElement(); } \ No newline at end of file diff --git a/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java b/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java index b55b4413275a..4382cff74946 100644 --- a/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java +++ b/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -128,6 +128,11 @@ public class UsageInfoToUsageConverter { public static Usage convert(@NotNull TargetElementsDescriptor descriptor, @NotNull UsageInfo usageInfo) { PsiElement[] primaryElements = descriptor.getPrimaryElements(); + return convert(primaryElements, usageInfo); + } + + @NotNull + public static Usage convert(@NotNull PsiElement[] primaryElements, @NotNull UsageInfo usageInfo) { PsiElement usageElement = usageInfo.getElement(); for(ReadWriteAccessDetector detector: Extensions.getExtensions(ReadWriteAccessDetector.EP_NAME)) { if (isReadWriteAccessibleElements(primaryElements, detector)) { @@ -149,6 +154,17 @@ public class UsageInfoToUsageConverter { return usages; } + @NotNull + public static Usage[] convert(@NotNull final PsiElement[] primaryElements, @NotNull UsageInfo[] usageInfos) { + Usage[] usages = ContainerUtil.map(usageInfos, new Function() { + @Override + public Usage fun(UsageInfo info) { + return convert(primaryElements, info); + } + }, new Usage[usageInfos.length]); + return usages; + } + private static boolean isReadWriteAccessibleElements(@NotNull PsiElement[] elements, @NotNull ReadWriteAccessDetector detector) { if (elements.length == 0) { return false; diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 70e331b90134..ca39f5122f5f 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -755,13 +755,13 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra return ActionManager.getInstance().getKeyboardShortcut("ShowSettingsAndFindUsages"); } - private static KeyboardShortcut getShowUsagesWithSettingsShortcut(@NotNull UsageTarget[] targets) { - //if (targets.length != 0) { - // NavigationItem target = targets[0]; - // if (target instanceof ConfigurableUsageTarget) { - // return ((ConfigurableUsageTarget)target).getShortcut(); - // } - //} + static KeyboardShortcut getShowUsagesWithSettingsShortcut(@NotNull UsageTarget[] targets) { + if (targets.length != 0) { + NavigationItem target = targets[0]; + if (target instanceof ConfigurableUsageTarget) { + return ((ConfigurableUsageTarget)target).getShortcut(); + } + } return getShowUsagesWithSettingsShortcut(); } diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java index 858f49800f26..bb98e722a555 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -418,7 +418,7 @@ public class UsageViewManagerImpl extends UsageViewManager { myPresentation.getScopeText()); if (notFoundActions.isEmpty()) { - String[] lines = myProcessPresentation.isShowFindOptionsPrompt() ? new String[] {StringUtil.escapeXml(message), createOptionsHtml()} : new String[]{StringUtil.escapeXml(message)}; + String[] lines = myProcessPresentation.isShowFindOptionsPrompt() ? new String[] {StringUtil.escapeXml(message), createOptionsHtml(mySearchFor)} : new String[]{StringUtil.escapeXml(message)}; notifyByFindBalloon(createGotToOptionsListener(mySearchFor), MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject, lines); findStartedBalloonShown.set(false); @@ -453,7 +453,8 @@ public class UsageViewManagerImpl extends UsageViewManager { flashUsageScriptaculously(usage); } notifyByFindBalloon(createGotToOptionsListener(mySearchFor), - MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject,"Only one usage found.", createOptionsHtml()); + MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject,"Only one usage found.", createOptionsHtml( + mySearchFor)); } }, ModalityState.NON_MODAL, myProject.getDisposed()); } @@ -593,9 +594,9 @@ public class UsageViewManagerImpl extends UsageViewManager { } @NotNull - private static String createOptionsHtml() { + private static String createOptionsHtml(@NonNls UsageTarget[] searchFor) { + KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut(searchFor); String shortcutText = ""; - KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut(); if (shortcut != null) { shortcutText = " (" + KeymapUtil.getShortcutText(shortcut) + ")"; }