@NotNull private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) { Set<VirtualFile> files = new LinkedHashSet<VirtualFile>(); for (PsiElement element : scope.getScope()) { PsiFile file = element.getContainingFile(); if (file != null) { ContainerUtil.addIfNotNull(files, file.getVirtualFile()); } } return files; }
private static int addToUsages( @NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel, @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) { int count = 0; CharSequence text = document.getCharsSequence(); int textLength = document.getTextLength(); int offset = offsetRef[0]; Project project = psiFile.getProject(); FindManager findManager = FindManager.getInstance(project); while (offset < textLength) { FindResult result = findManager.findString(text, offset, findModel, psiFile.getVirtualFile()); if (!result.isStringFound()) break; final SearchScope customScope = findModel.getCustomScope(); if (customScope instanceof LocalSearchScope) { final TextRange range = new TextRange(result.getStartOffset(), result.getEndOffset()); if (!((LocalSearchScope) customScope).containsRange(psiFile, range)) break; } UsageInfo info = new FindResultUsageInfo(findManager, psiFile, offset, findModel, result); if (!consumer.process(info)) { throw new ProcessCanceledException(); } count++; final int prevOffset = offset; offset = result.getEndOffset(); if (prevOffset == offset) { // for regular expr the size of the match could be zero -> could be infinite loop in finding // usages! ++offset; } if (maxUsages > 0 && count >= maxUsages) { break; } } offsetRef[0] = offset; return count; }
// returns number of hits static int processUsagesInFile( @NotNull final PsiFile psiFile, @NotNull final FindModel findModel, @NotNull final Processor<UsageInfo> consumer) { if (findModel.getStringToFind().isEmpty()) { if (!ApplicationManager.getApplication() .runReadAction((Computable<Boolean>) () -> consumer.process(new UsageInfo(psiFile)))) { throw new ProcessCanceledException(); } return 1; } final VirtualFile virtualFile = psiFile.getVirtualFile(); if (virtualFile == null) return 0; if (virtualFile.getFileType().isBinary()) return 0; // do not decompile .class files final Document document = ApplicationManager.getApplication() .runReadAction( (Computable<Document>) () -> virtualFile.isValid() ? FileDocumentManager.getInstance().getDocument(virtualFile) : null); if (document == null) return 0; final int[] offset = {0}; int count = 0; int found; ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator()); TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.getFrom(indicator); do { tooManyUsagesStatus.pauseProcessingIfTooManyUsages(); // wait for user out of read action found = ApplicationManager.getApplication() .runReadAction( (Computable<Integer>) () -> { if (!psiFile.isValid()) return 0; return addToUsages( document, consumer, findModel, psiFile, offset, USAGES_PER_READ_ACTION); }); count += found; } while (found != 0); return count; }
@NotNull private Set<PsiFile> getFilesForFastWordSearch() { String stringToFind = myFindModel.getStringToFind(); if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) { return Collections.emptySet(); } SearchScope customScope = myFindModel.getCustomScope(); GlobalSearchScope scope = myPsiDirectory != null ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true) : myModule != null ? myModule.getModuleContentScope() : customScope instanceof GlobalSearchScope ? (GlobalSearchScope) customScope : toGlobal(customScope); if (scope == null) { scope = ProjectScope.getContentScope(myProject); } final Set<PsiFile> resultFiles = new LinkedHashSet<PsiFile>(); if (TrigramIndex.ENABLED) { final Set<Integer> keys = ContainerUtil.newTroveSet(); TrigramBuilder.processTrigrams( stringToFind, new TrigramBuilder.TrigramProcessor() { @Override public boolean execute(int value) { keys.add(value); return true; } }); if (!keys.isEmpty()) { final List<VirtualFile> hits = new ArrayList<VirtualFile>(); final GlobalSearchScope finalScope = scope; ApplicationManager.getApplication() .runReadAction( new Runnable() { @Override public void run() { FileBasedIndex.getInstance() .getFilesWithKey( TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), finalScope); } }); for (VirtualFile hit : hits) { if (myFileMask.value(hit)) { PsiFile file = findFile(hit); if (file != null) { resultFiles.add(file); } } } return resultFiles; } } PsiSearchHelperImpl helper = (PsiSearchHelperImpl) PsiSearchHelper.SERVICE.getInstance(myProject); helper.processFilesWithText( scope, UsageSearchContext.ANY, myFindModel.isCaseSensitive(), stringToFind, new Processor<VirtualFile>() { @Override public boolean process(VirtualFile file) { if (myFileMask.value(file)) { ContainerUtil.addIfNotNull(resultFiles, findFile(file)); } return true; } }); // in case our word splitting is incorrect CacheManager cacheManager = CacheManager.SERVICE.getInstance(myProject); PsiFile[] filesWithWord = cacheManager.getFilesWithWord( stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive()); for (PsiFile file : filesWithWord) { if (myFileMask.value(file.getVirtualFile())) { resultFiles.add(file); } } return resultFiles; }
private void searchInFiles( @NotNull Collection<PsiFile> psiFiles, @NotNull FindUsagesProcessPresentation processPresentation, @NotNull final Processor<UsageInfo> consumer) { int i = 0; long totalFilesSize = 0; int count = 0; for (final PsiFile psiFile : psiFiles) { final VirtualFile virtualFile = psiFile.getVirtualFile(); final int index = i++; if (virtualFile == null) continue; long fileLength = UsageViewManagerImpl.getFileLength(virtualFile); if (fileLength == -1) continue; // Binary or invalid final boolean skipProjectFile = ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !myFindModel.isSearchInProjectFiles(); if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue; if (fileLength > SINGLE_FILE_SIZE_LIMIT) { myLargeFiles.add(psiFile); continue; } myProgress.checkCanceled(); myProgress.setFraction((double) index / psiFiles.size()); String text = FindBundle.message( "find.searching.for.string.in.file.progress", myFindModel.getStringToFind(), virtualFile.getPresentableUrl()); myProgress.setText(text); myProgress.setText2( FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count)); int countInFile = FindInProjectUtil.processUsagesInFile( psiFile, myFindModel, new Processor<UsageInfo>() { @Override public boolean process(UsageInfo info) { return skipProjectFile || consumer.process(info); } }); if (countInFile > 0 && skipProjectFile) { processPresentation.projectFileUsagesFound( new Runnable() { @Override public void run() { FindModel model = myFindModel.clone(); model.setSearchInProjectFiles(true); FindInProjectManager.getInstance(myProject).startFindInProject(model); } }); continue; } count += countInFile; if (countInFile > 0) { totalFilesSize += fileLength; if (totalFilesSize > FILES_SIZE_LIMIT && !myWarningShown) { myWarningShown = true; String message = FindBundle.message( "find.excessive.total.size.prompt", UsageViewManagerImpl.presentableSize(totalFilesSize), ApplicationNamesInfo.getInstance().getProductName()); UsageLimitUtil.showAndCancelIfAborted( myProject, message, processPresentation.getUsageViewPresentation()); } } } }