private IntersectionScope( @NotNull GlobalSearchScope scope1, @NotNull GlobalSearchScope scope2, String displayName) { super(scope1.getProject() == null ? scope2.getProject() : scope1.getProject()); myScope1 = scope1; myScope2 = scope2; myDisplayName = displayName; }
private boolean containsScope(@NotNull GlobalSearchScope scope) { if (myScope1.equals(scope) || myScope2.equals(scope) || equals(scope)) return true; if (myScope1 instanceof IntersectionScope && ((IntersectionScope) myScope1).containsScope(scope)) return true; if (myScope2 instanceof IntersectionScope && ((IntersectionScope) myScope2).containsScope(scope)) return true; return false; }
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof IntersectionScope)) return false; IntersectionScope that = (IntersectionScope) o; return myScope1.equals(that.myScope1) && myScope2.equals(that.myScope2); }
@NotNull @Override public String getDisplayName() { if (myDisplayName == null) { return PsiBundle.message( "psi.search.scope.intersection", myScope1.getDisplayName(), myScope2.getDisplayName()); } return myDisplayName; }
@Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { int res1 = myScope1.compare(file1, file2); int res2 = myScope2.compare(file1, file2); if (res1 == 0) return res2; if (res2 == 0) return res1; res1 /= Math.abs(res1); res2 /= Math.abs(res2); if (res1 == res2) return res1; return 0; }
@NotNull static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { SearchScope customScope = findModel.getCustomScope(); VirtualFile directory = getDirectory(findModel); Module module = findModel.getModuleName() == null ? null : ModuleManager.getInstance(project).findModuleByName(findModel.getModuleName()); return findModel.isCustomScope() && customScope != null ? customScope.intersectWith(GlobalSearchScope.allScope(project)) : // we don't have to check for myProjectFileIndex.isExcluded(file) here like // FindInProjectTask.collectFilesInScope() does // because all found usages are guaranteed to be not in excluded dir directory != null ? forDirectory(project, findModel.isWithSubdirectories(), directory) : module != null ? module.getModuleContentScope() : findModel.isProjectScope() ? ProjectScope.getContentScope(project) : GlobalSearchScope.allScope(project); }
@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<VirtualFile> selectedFiles = ContainerUtil.filter(filesOrDirs, file -> !file.isDirectory()); if (!selectedFiles.isEmpty()) { return GlobalSearchScope.filesScope(project, selectedFiles, "Selected Files"); } } return null; }
@NotNull @Override public List<SearchScope> getPredefinedScopes( @NotNull final Project project, @Nullable final DataContext dataContext, boolean suggestSearchInLibs, boolean prevSearchFiles, boolean currentSelection, boolean usageView, boolean showEmptyScopes) { Collection<SearchScope> result = ContainerUtil.newLinkedHashSet(); result.add(GlobalSearchScope.projectScope(project)); if (suggestSearchInLibs) { result.add(GlobalSearchScope.allScope(project)); } if (ModuleUtil.isSupportedRootType(project, JavaSourceRootType.TEST_SOURCE)) { result.add(GlobalSearchScopesCore.projectProductionScope(project)); result.add(GlobalSearchScopesCore.projectTestScope(project)); } final GlobalSearchScope openFilesScope = GlobalSearchScopes.openFilesScope(project); if (openFilesScope != GlobalSearchScope.EMPTY_SCOPE) { result.add(openFilesScope); } else if (showEmptyScopes) { result.add( new LocalSearchScope(PsiElement.EMPTY_ARRAY, IdeBundle.message("scope.open.files"))); } final Editor selectedTextEditor = ApplicationManager.getApplication().isDispatchThread() ? FileEditorManager.getInstance(project).getSelectedTextEditor() : null; final PsiFile psiFile = (selectedTextEditor != null) ? PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument()) : null; PsiFile currentFile = psiFile; if (dataContext != null) { PsiElement dataContextElement = CommonDataKeys.PSI_FILE.getData(dataContext); if (dataContextElement == null) { dataContextElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext); } if (dataContextElement == null && psiFile != null) { dataContextElement = psiFile; } if (dataContextElement != null) { if (!PlatformUtils.isCidr()) { // TODO: have an API to disable module scopes. Module module = ModuleUtilCore.findModuleForPsiElement(dataContextElement); if (module == null) { module = LangDataKeys.MODULE.getData(dataContext); } if (module != null && !(ModuleType.get(module) instanceof InternalModuleType)) { result.add(module.getModuleScope()); } } if (currentFile == null) { currentFile = dataContextElement.getContainingFile(); } } } if (currentFile != null || showEmptyScopes) { PsiElement[] scope = currentFile != null ? new PsiElement[] {currentFile} : PsiElement.EMPTY_ARRAY; result.add(new LocalSearchScope(scope, IdeBundle.message("scope.current.file"))); } if (currentSelection && selectedTextEditor != null && psiFile != null) { SelectionModel selectionModel = selectedTextEditor.getSelectionModel(); if (selectionModel.hasSelection()) { int start = selectionModel.getSelectionStart(); final PsiElement startElement = psiFile.findElementAt(start); if (startElement != null) { int end = selectionModel.getSelectionEnd(); final PsiElement endElement = psiFile.findElementAt(end); if (endElement != null) { final PsiElement parent = PsiTreeUtil.findCommonParent(startElement, endElement); if (parent != null) { final List<PsiElement> elements = new ArrayList<PsiElement>(); final PsiElement[] children = parent.getChildren(); TextRange selection = new TextRange(start, end); for (PsiElement child : children) { if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null && selection.contains(child.getTextOffset())) { elements.add(child); } } if (!elements.isEmpty()) { SearchScope local = new LocalSearchScope( PsiUtilCore.toPsiElementArray(elements), IdeBundle.message("scope.selection")); result.add(local); } } } } } } if (usageView) { addHierarchyScope(project, result); UsageView selectedUsageView = UsageViewManager.getInstance(project).getSelectedUsageView(); if (selectedUsageView != null && !selectedUsageView.isSearchInProgress()) { final Set<Usage> usages = ContainerUtil.newTroveSet(selectedUsageView.getUsages()); usages.removeAll(selectedUsageView.getExcludedUsages()); final List<PsiElement> results = new ArrayList<PsiElement>(usages.size()); if (prevSearchFiles) { final Set<VirtualFile> files = collectFiles(usages, true); if (!files.isEmpty()) { GlobalSearchScope prev = new GlobalSearchScope(project) { private Set<VirtualFile> myFiles = null; @NotNull @Override public String getDisplayName() { return IdeBundle.message("scope.files.in.previous.search.result"); } @Override public synchronized boolean contains(@NotNull VirtualFile file) { if (myFiles == null) { myFiles = collectFiles(usages, false); } return myFiles.contains(file); } @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }; result.add(prev); } } else { for (Usage usage : usages) { if (usage instanceof PsiElementUsage) { final PsiElement element = ((PsiElementUsage) usage).getElement(); if (element != null && element.isValid() && element.getContainingFile() != null) { results.add(element); } } } if (!results.isEmpty()) { result.add( new LocalSearchScope( PsiUtilCore.toPsiElementArray(results), IdeBundle.message("scope.previous.search.results"))); } } } } final FavoritesManager favoritesManager = FavoritesManager.getInstance(project); if (favoritesManager != null) { for (final String favorite : favoritesManager.getAvailableFavoritesListNames()) { final Collection<TreeItem<Pair<AbstractUrl, String>>> rootUrls = favoritesManager.getFavoritesListRootUrls(favorite); if (rootUrls.isEmpty()) continue; // ignore unused root result.add( new GlobalSearchScope(project) { @NotNull @Override public String getDisplayName() { return "Favorite \'" + favorite + "\'"; } @Override public boolean contains(@NotNull final VirtualFile file) { return ApplicationManager.getApplication() .runReadAction( (Computable<Boolean>) () -> favoritesManager.contains(favorite, file)); } @Override public int compare( @NotNull final VirtualFile file1, @NotNull final VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull final Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }); } } ContainerUtil.addIfNotNull(result, getSelectedFilesScope(project, dataContext)); return ContainerUtil.newArrayList(result); }
@NotNull private Collection<PsiFile> collectFilesInScope( @NotNull final Set<PsiFile> alreadySearched, final boolean skipIndexed) { SearchScope customScope = myFindModel.getCustomScope(); final GlobalSearchScope globalCustomScope = toGlobal(customScope); final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject); final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind()); class EnumContentIterator implements ContentIterator { final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>(); @Override public boolean processFile(@NotNull final VirtualFile virtualFile) { ApplicationManager.getApplication() .runReadAction( new Runnable() { @Override public void run() { ProgressManager.checkCanceled(); if (virtualFile.isDirectory() || !virtualFile.isValid() || !myFileMask.value(virtualFile) || globalCustomScope != null && !globalCustomScope.contains(virtualFile)) { return; } if (skipIndexed && isCoveredByIndex(virtualFile) && (fileIndex.isInContent(virtualFile) || fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile))) { return; } PsiFile psiFile = myPsiManager.findFile(virtualFile); if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) { PsiFile sourceFile = (PsiFile) psiFile.getNavigationElement(); if (sourceFile != null) psiFile = sourceFile; if (!psiFile.getFileType().isBinary()) { myFiles.add(psiFile); } } } final FileBasedIndexImpl fileBasedIndex = (FileBasedIndexImpl) FileBasedIndex.getInstance(); private boolean isCoveredByIndex(VirtualFile file) { FileType fileType = file.getFileType(); if (hasTrigrams) { return TrigramIndex.isIndexable(fileType) && fileBasedIndex.isIndexingCandidate(file, TrigramIndex.INDEX_ID); } return IdIndex.isIndexable(fileType) && fileBasedIndex.isIndexingCandidate(file, IdIndex.NAME); } }); return true; } @NotNull private Collection<PsiFile> getFiles() { return myFiles; } } final EnumContentIterator iterator = new EnumContentIterator(); if (customScope instanceof LocalSearchScope) { for (VirtualFile file : getLocalScopeFiles((LocalSearchScope) customScope)) { iterator.processFile(file); } } else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / // FilesScope //noinspection unchecked for (VirtualFile file : (Iterable<VirtualFile>) customScope) { iterator.processFile(file); } } else if (myPsiDirectory != null) { ApplicationManager.getApplication() .runReadAction( new Runnable() { @Override public void run() { if (myPsiDirectory.isValid()) { addFilesUnderDirectory(myPsiDirectory, iterator); } } }); myFileIndex.iterateContentUnderDirectory(myPsiDirectory.getVirtualFile(), iterator); } else { boolean success = myFileIndex.iterateContent(iterator); if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) { final VirtualFile[] librarySources = ApplicationManager.getApplication() .runReadAction( new Computable<VirtualFile[]>() { @Override public VirtualFile[] compute() { OrderEnumerator enumerator = myModule == null ? OrderEnumerator.orderEntries(myProject) : OrderEnumerator.orderEntries(myModule); return enumerator .withoutModuleSourceEntries() .withoutDepModules() .getSourceRoots(); } }); iterateAll(librarySources, globalCustomScope, iterator); } } return iterator.getFiles(); }
public static List<SearchScope> getPredefinedScopes( @NotNull final Project project, @Nullable final DataContext dataContext, boolean suggestSearchInLibs, boolean prevSearchFiles, boolean currentSelection, boolean usageView) { ArrayList<SearchScope> result = new ArrayList<SearchScope>(); result.add(GlobalSearchScope.projectScope(project)); if (suggestSearchInLibs) { result.add(GlobalSearchScope.allScope(project)); } if (!PlatformUtils.isCidr() && ModuleUtil.isSupportedRootType( project, JavaSourceRootType.TEST_SOURCE)) { // TODO: fix these scopes in AppCode result.add(GlobalSearchScopes.projectProductionScope(project)); result.add(GlobalSearchScopes.projectTestScope(project)); } result.add(GlobalSearchScopes.openFilesScope(project)); if (dataContext != null) { PsiElement dataContextElement = CommonDataKeys.PSI_FILE.getData(dataContext); if (dataContextElement == null) { dataContextElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext); } if (dataContextElement != null) { if (!PlatformUtils.isCidr()) { // TODO: have an API to disable module scopes. Module module = ModuleUtilCore.findModuleForPsiElement(dataContextElement); if (module == null) { module = LangDataKeys.MODULE.getData(dataContext); } if (module != null) { result.add(module.getModuleScope()); } } if (dataContextElement.getContainingFile() != null) { result.add( new LocalSearchScope(dataContextElement, IdeBundle.message("scope.current.file"))); } } } if (currentSelection) { FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); final Editor selectedTextEditor = fileEditorManager.getSelectedTextEditor(); if (selectedTextEditor != null) { final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument()); if (psiFile != null) { if (selectedTextEditor.getSelectionModel().hasSelection()) { final PsiElement startElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionStart()); if (startElement != null) { final PsiElement endElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionEnd()); if (endElement != null) { final PsiElement parent = PsiTreeUtil.findCommonParent(startElement, endElement); if (parent != null) { final List<PsiElement> elements = new ArrayList<PsiElement>(); final PsiElement[] children = parent.getChildren(); for (PsiElement child : children) { if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null) { elements.add(child); } } if (!elements.isEmpty()) { SearchScope local = new LocalSearchScope( PsiUtilCore.toPsiElementArray(elements), IdeBundle.message("scope.selection")); result.add(local); } } } } } } } } if (usageView) { UsageView selectedUsageView = UsageViewManager.getInstance(project).getSelectedUsageView(); if (selectedUsageView != null && !selectedUsageView.isSearchInProgress()) { final Set<Usage> usages = selectedUsageView.getUsages(); final List<PsiElement> results = new ArrayList<PsiElement>(usages.size()); if (prevSearchFiles) { final Set<VirtualFile> files = new HashSet<VirtualFile>(); for (Usage usage : usages) { if (usage instanceof PsiElementUsage) { PsiElement psiElement = ((PsiElementUsage) usage).getElement(); if (psiElement != null && psiElement.isValid()) { PsiFile psiFile = psiElement.getContainingFile(); if (psiFile != null) { VirtualFile file = psiFile.getVirtualFile(); if (file != null) files.add(file); } } } } if (!files.isEmpty()) { GlobalSearchScope prev = new GlobalSearchScope(project) { @Override public String getDisplayName() { return IdeBundle.message("scope.files.in.previous.search.result"); } @Override public boolean contains(@NotNull VirtualFile file) { return files.contains(file); } @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }; result.add(prev); } } else { for (Usage usage : usages) { if (usage instanceof PsiElementUsage) { final PsiElement element = ((PsiElementUsage) usage).getElement(); if (element != null && element.isValid() && element.getContainingFile() != null) { results.add(element); } } } if (!results.isEmpty()) { result.add( new LocalSearchScope( PsiUtilCore.toPsiElementArray(results), IdeBundle.message("scope.previous.search.results"))); } } } } final FavoritesManager favoritesManager = FavoritesManager.getInstance(project); if (favoritesManager != null) { for (final String favorite : favoritesManager.getAvailableFavoritesListNames()) { final Collection<TreeItem<Pair<AbstractUrl, String>>> rootUrls = favoritesManager.getFavoritesListRootUrls(favorite); if (rootUrls.isEmpty()) continue; // ignore unused root result.add( new GlobalSearchScope(project) { @Override public String getDisplayName() { return "Favorite \'" + favorite + "\'"; } @Override public boolean contains(@NotNull final VirtualFile file) { return favoritesManager.contains(favorite, file); } @Override public int compare( @NotNull final VirtualFile file1, @NotNull final VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull final Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }); } } if (dataContext != null) { final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext); if (files != null) { final List<VirtualFile> openFiles = Arrays.asList(files); result.add( new DelegatingGlobalSearchScope(GlobalSearchScope.filesScope(project, openFiles)) { @Override public String getDisplayName() { return "Selected Files"; } }); } } return result; }
@Override public int hashCode() { return 31 * myScope1.hashCode() + myScope2.hashCode(); }
@Override public boolean isSearchOutsideRootModel() { return myScope1.isSearchOutsideRootModel() && myScope2.isSearchOutsideRootModel(); }
@Override public boolean isSearchInLibraries() { return myScope1.isSearchInLibraries() && myScope2.isSearchInLibraries(); }
@Override public boolean isSearchInModuleContent( @NotNull final Module aModule, final boolean testSources) { return myScope1.isSearchInModuleContent(aModule, testSources) && myScope2.isSearchInModuleContent(aModule, testSources); }
@Override public boolean isSearchInModuleContent(@NotNull Module aModule) { return myScope1.isSearchInModuleContent(aModule) && myScope2.isSearchInModuleContent(aModule); }
@Override public boolean contains(@NotNull VirtualFile file) { return myScope1.contains(file) && myScope2.contains(file); }