From d6f812f06cf8acc2dc02dc2c2e7e195cf5d47899 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 5 Aug 2019 16:18:16 +0200 Subject: [PATCH] allow selecting directories in "selected files" scope (IDEA-76212) GitOrigin-RevId: e73d9330e4f506a2223e01e71268e2d87abdcbe6 --- .../PredefinedSearchScopeProviderImpl.java | 75 ++++++++++++++++--- .../src/messages/IdeBundle.properties | 3 + 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java index e6c44cb599fc..590fc4fcd14f 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.DumbUnawareHider; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; @@ -89,8 +90,8 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv showEmptyScopes ? new LocalSearchScope(PsiElement.EMPTY_ARRAY, IdeBundle.message("scope.open.files")) : null); Editor selectedTextEditor = ApplicationManager.getApplication().isDispatchThread() - ? FileEditorManager.getInstance(project).getSelectedTextEditor() - : null; + ? FileEditorManager.getInstance(project).getSelectedTextEditor() + : null; PsiFile psiFile = selectedTextEditor == null ? null : PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument()); PsiFile currentFile = psiFile; @@ -214,7 +215,7 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv } } - ContainerUtil.addIfNotNull(result, getSelectedFilesScope(project, dataContext)); + ContainerUtil.addIfNotNull(result, getSelectedFilesScope(project, dataContext, currentFile)); return new ArrayList<>(result); } @@ -252,15 +253,14 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv } @Nullable - private static SearchScope getSelectedFilesScope(final Project project, @Nullable DataContext dataContext) { - final VirtualFile[] filesOrDirs = dataContext == null ? null : CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext); - if (filesOrDirs != null) { - final List selectedFiles = ContainerUtil.filter(filesOrDirs, file -> !file.isDirectory()); - if (!selectedFiles.isEmpty()) { - return GlobalSearchScope.filesScope(project, selectedFiles, "Selected Files"); - } + private static SearchScope getSelectedFilesScope(final Project project, + @Nullable DataContext dataContext, + @Nullable PsiFile currentFile) { + final VirtualFile[] filesOrDirs = (dataContext == null) ? null : CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext); + if (filesOrDirs == null || filesOrDirs.length == 1 && currentFile != null && filesOrDirs[0].equals(currentFile.getVirtualFile())) { + return null; } - return null; + return new SelectedFilesScope(project, filesOrDirs); } @NotNull @@ -283,4 +283,57 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv } return files; } + + static class SelectedFilesScope extends GlobalSearchScope { + + private final Set myFiles = new THashSet<>(); + private final Set myDirectories = new THashSet<>(); + + SelectedFilesScope(Project project, VirtualFile... filesOrDirs) { + super(project); + if (filesOrDirs.length == 0) { + throw new IllegalArgumentException("array is empty"); + } + for (VirtualFile fileOrDir : filesOrDirs) { + if (fileOrDir.isDirectory()) { + myDirectories.add(fileOrDir); + } + else { + myFiles.add(fileOrDir); + } + } + } + + @Override + public boolean isSearchInModuleContent(@NotNull Module aModule) { + return true; + } + + @Override + public boolean isSearchInLibraries() { + return true; + } + + @Override + public boolean contains(@NotNull VirtualFile file) { + for (VirtualFile virtualFile : myFiles) { + if (virtualFile.equals(file)) { + return true; + } + } + return VfsUtilCore.isUnder(file, myDirectories); + } + + @NotNull + @Override + public String getDisplayName() { + if (myFiles.isEmpty()) { + return IdeBundle.message("scope.selected.directories", myDirectories.size()); + } + if (myDirectories.isEmpty()) { + return IdeBundle.message("scope.selected.files", myFiles.size()); + } + return IdeBundle.message("scope.selected.files.and.directories", myFiles.size(), myDirectories.size()); + } + } } diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index e404dd56a551..308b55009ee2 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -876,6 +876,9 @@ scope.hierarchy=Hierarchy of {0} scope.recent.files=Recently Viewed Files scope.recent.modified.files=Recently Changed Files scope.modified.files=All Changed Files +scope.selected.files=Selected {0,choice,1#File|2#Files} +scope.selected.directories=Selected {0,choice,1#Directory|2#Directories} +scope.selected.files.and.directories=Selected {0,choice,1#File|2#Files} \\& {1,choice,1#Directory|2#Directories} prompt.choose.base.class.of.the.hierarchy=Choose Base Class of the Hierarchy to Search In progress.searching= searching... title.tip.of.the.day=Tip of the Day