2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.find.impl;
19 import com.intellij.find.*;
20 import com.intellij.find.ngrams.TrigramIndex;
21 import com.intellij.navigation.ItemPresentation;
22 import com.intellij.openapi.actionSystem.DataContext;
23 import com.intellij.openapi.actionSystem.LangDataKeys;
24 import com.intellij.openapi.actionSystem.PlatformDataKeys;
25 import com.intellij.openapi.application.ApplicationManager;
26 import com.intellij.openapi.application.ApplicationNamesInfo;
27 import com.intellij.openapi.editor.Document;
28 import com.intellij.openapi.editor.Editor;
29 import com.intellij.openapi.fileEditor.FileDocumentManager;
30 import com.intellij.openapi.fileEditor.FileEditor;
31 import com.intellij.openapi.fileTypes.FileTypeManager;
32 import com.intellij.openapi.module.Module;
33 import com.intellij.openapi.module.ModuleManager;
34 import com.intellij.openapi.progress.ProcessCanceledException;
35 import com.intellij.openapi.progress.ProgressIndicator;
36 import com.intellij.openapi.progress.ProgressManager;
37 import com.intellij.openapi.project.DumbService;
38 import com.intellij.openapi.project.IndexNotReadyException;
39 import com.intellij.openapi.project.Project;
40 import com.intellij.openapi.project.ProjectUtil;
41 import com.intellij.openapi.roots.*;
42 import com.intellij.openapi.roots.impl.FileIndexImplUtil;
43 import com.intellij.openapi.ui.MessageType;
44 import com.intellij.openapi.util.Computable;
45 import com.intellij.openapi.util.Factory;
46 import com.intellij.openapi.util.Pair;
47 import com.intellij.openapi.util.TextRange;
48 import com.intellij.openapi.util.registry.Registry;
49 import com.intellij.openapi.util.text.StringUtil;
50 import com.intellij.openapi.util.text.TrigramBuilder;
51 import com.intellij.openapi.vfs.JarFileSystem;
52 import com.intellij.openapi.vfs.LocalFileSystem;
53 import com.intellij.openapi.vfs.VirtualFile;
54 import com.intellij.openapi.vfs.VirtualFileFilter;
55 import com.intellij.openapi.wm.ToolWindowId;
56 import com.intellij.openapi.wm.ToolWindowManager;
57 import com.intellij.psi.*;
58 import com.intellij.psi.impl.cache.CacheManager;
59 import com.intellij.psi.search.*;
60 import com.intellij.usageView.UsageInfo;
61 import com.intellij.usages.*;
62 import com.intellij.util.CommonProcessors;
63 import com.intellij.util.Function;
64 import com.intellij.util.PatternUtil;
65 import com.intellij.util.Processor;
66 import com.intellij.util.containers.ContainerUtil;
67 import com.intellij.util.indexing.FileBasedIndex;
68 import gnu.trove.THashSet;
69 import gnu.trove.TIntHashSet;
70 import gnu.trove.TIntIterator;
71 import org.intellij.lang.annotations.Language;
72 import org.jetbrains.annotations.NotNull;
73 import org.jetbrains.annotations.Nullable;
78 import java.util.regex.Pattern;
80 public class FindInProjectUtil {
81 private static final int USAGES_PER_READ_ACTION = 100;
82 private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
83 private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
85 private FindInProjectUtil() {}
87 public static void setDirectoryName(FindModel model, DataContext dataContext) {
88 PsiElement psiElement;
90 psiElement = LangDataKeys.PSI_ELEMENT.getData(dataContext);
92 catch (IndexNotReadyException e) {
96 String directoryName = null;
98 if (psiElement instanceof PsiDirectory) {
99 directoryName = ((PsiDirectory)psiElement).getVirtualFile().getPresentableUrl();
102 final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext);
103 if (psiFile != null) {
104 PsiDirectory psiDirectory = psiFile.getContainingDirectory();
105 if (psiDirectory != null) {
106 directoryName = psiDirectory.getVirtualFile().getPresentableUrl();
111 if (directoryName == null && psiElement instanceof PsiDirectoryContainer) {
112 final PsiDirectory[] directories = ((PsiDirectoryContainer)psiElement).getDirectories();
113 directoryName = directories.length == 1 ? directories[0].getVirtualFile().getPresentableUrl():null;
116 Module module = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
117 if (module != null) {
118 model.setModuleName(module.getName());
121 Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
122 if (model.getModuleName() == null || editor == null) {
123 model.setDirectoryName(directoryName);
124 model.setProjectScope(directoryName == null && module == null && !model.isCustomScope() || editor != null);
129 public static PsiDirectory getPsiDirectory(final FindModel findModel, Project project) {
130 String directoryName = findModel.getDirectoryName();
131 if (findModel.isProjectScope() || directoryName == null) {
135 final PsiManager psiManager = PsiManager.getInstance(project);
136 String path = directoryName.replace(File.separatorChar, '/');
137 VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
138 if (virtualFile == null || !virtualFile.isDirectory()) {
139 if (!path.contains(JarFileSystem.JAR_SEPARATOR)) {
140 path += JarFileSystem.JAR_SEPARATOR;
142 virtualFile = JarFileSystem.getInstance().findFileByPath(path);
144 return virtualFile == null ? null : psiManager.findDirectory(virtualFile);
147 private static void addFilesUnderDirectory(PsiDirectory directory, Collection<PsiFile> fileList, boolean isRecursive, Pattern fileMaskRegExp) {
148 final PsiElement[] children = directory.getChildren();
150 for (PsiElement child : children) {
151 if (child instanceof PsiFile &&
152 (fileMaskRegExp == null ||
153 fileMaskRegExp.matcher(((PsiFile)child).getName()).matches()
156 PsiFile file = (PsiFile)child;
157 PsiFile sourceFile = (PsiFile)file.getNavigationElement();
158 if (sourceFile != null) file = sourceFile;
161 else if (isRecursive && child instanceof PsiDirectory) {
162 addFilesUnderDirectory((PsiDirectory)child, fileList, isRecursive, fileMaskRegExp);
168 public static List<UsageInfo> findUsages(final FindModel findModel, final PsiDirectory psiDirectory, final Project project) {
170 final CommonProcessors.CollectProcessor<UsageInfo> collector = new CommonProcessors.CollectProcessor<UsageInfo>();
171 findUsages(findModel, psiDirectory, project, collector);
173 return new ArrayList<UsageInfo>(collector.getResults());
177 private static Pattern createFileMaskRegExp(FindModel findModel) {
178 final String filter = findModel.getFileFilter();
179 return createFileMaskRegExp(filter);
182 public static Pattern createFileMaskRegExp(String filter) {
183 if (filter == null) {
187 final List<String> strings = StringUtil.split(filter, ",");
188 if (strings.size() == 1) {
189 pattern = PatternUtil.convertToRegex(filter.trim());
192 pattern = StringUtil.join(strings, new Function<String, String>() {
194 public String fun(String s) {
195 return "(" + PatternUtil.convertToRegex(s.trim()) + ")";
199 return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
202 public static void findUsages(final FindModel findModel,
203 final PsiDirectory psiDirectory,
204 final Project project,
205 final Processor<UsageInfo> consumer) {
206 final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
208 final Collection<PsiFile> psiFiles = getFilesToSearchIn(findModel, project, psiDirectory);
210 final Set<PsiFile> largeFiles = new THashSet<PsiFile>();
213 long totalFilesSize = 0;
215 final boolean[] warningShown = {false};
217 final UsageViewManager usageViewManager = UsageViewManager.getInstance(project);
218 for (final PsiFile psiFile : psiFiles) {
219 usageViewManager.checkSearchCanceled();
220 final VirtualFile virtualFile = psiFile.getVirtualFile();
221 final int index = i++;
222 if (virtualFile == null) continue;
224 long fileLength = getFileLength(virtualFile);
225 if (fileLength == -1) continue; // Binary or invalid
227 if (ProjectUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
229 if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
230 largeFiles.add(psiFile);
234 if (progress != null) {
235 progress.setFraction((double)index / psiFiles.size());
236 String text = FindBundle.message("find.searching.for.string.in.file.progress",
237 findModel.getStringToFind(), virtualFile.getPresentableUrl());
238 progress.setText(text);
239 progress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
242 int countInFile = processUsagesInFile(psiFile, findModel, consumer);
244 count += countInFile;
245 if (countInFile > 0) {
246 totalFilesSize += fileLength;
247 if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
248 warningShown[0] = true;
249 String message = FindBundle.message("find.excessive.total.size.prompt", presentableSize(totalFilesSize),
250 ApplicationNamesInfo.getInstance().getProductName());
251 UsageLimitUtil.showAndCancelIfAborted(project, message);
256 if (!largeFiles.isEmpty()) {
258 String message = "<html><body>";
259 if (largeFiles.size() == 1) {
260 final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile();
261 message += "File " + presentableFileInfo(vFile) + " is ";
264 message += "Files<br> ";
267 for (PsiFile file : largeFiles) {
268 final VirtualFile vFile = file.getVirtualFile();
269 message += presentableFileInfo(vFile) + "<br> ";
270 if (counter++ > 10) break;
276 message += "too large and cannot be scanned</body></html>";
278 final String finalMessage = message;
279 ApplicationManager.getApplication().invokeLater(new Runnable() {
282 ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, MessageType.WARNING, finalMessage);
284 }, project.getDisposed());
287 catch (ProcessCanceledException e) {
291 if (progress != null) {
292 progress.setText(FindBundle.message("find.progress.search.completed"));
296 private static String presentableFileInfo(VirtualFile vFile) {
297 return getPresentablePath(vFile)
299 + presentableSize(getFileLength(vFile))
303 private static int processUsagesInFile(final PsiFile psiFile,
304 final FindModel findModel,
305 final Processor<UsageInfo> consumer) {
306 final VirtualFile virtualFile = psiFile.getVirtualFile();
307 if (virtualFile == null) return 0;
308 if (virtualFile.getFileType().isBinary()) return 0; // do not decompile .class files
309 final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
310 if (document == null) return 0;
311 final int[] offset = {0};
315 found = ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
318 public Integer compute() {
319 if (!psiFile.isValid()) return 0;
320 return addToUsages(document, consumer, findModel, psiFile, offset, USAGES_PER_READ_ACTION);
329 private static String getPresentablePath(final VirtualFile virtualFile) {
330 return "'" + ApplicationManager.getApplication().runReadAction(new Computable<String>() {
332 public String compute() {
333 return virtualFile.getPresentableUrl();
338 private static String presentableSize(long bytes) {
339 long megabytes = bytes / (1024 * 1024);
340 return FindBundle.message("find.file.size.megabytes", Long.toString(megabytes));
343 private static long getFileLength(final VirtualFile virtualFile) {
344 final long[] length = {-1L};
345 ApplicationManager.getApplication().runReadAction(new Runnable() {
348 if (!virtualFile.isValid()) return;
349 if (virtualFile.getFileType().isBinary()) return;
350 length[0] = virtualFile.getLength();
356 private static Collection<PsiFile> getFilesToSearchIn(final FindModel findModel, final Project project, final PsiDirectory psiDirectory) {
357 return ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiFile>>() {
359 public Collection<PsiFile> compute() {
360 return getFilesToSearchInReadAction(findModel, project, psiDirectory);
364 private static Collection<PsiFile> getFilesToSearchInReadAction(final FindModel findModel, final Project project, final PsiDirectory psiDirectory) {
365 String moduleName = findModel.getModuleName();
366 Module module = moduleName == null ? null : ModuleManager.getInstance(project).findModuleByName(moduleName);
367 final FileIndex fileIndex = module == null ?
368 ProjectRootManager.getInstance(project).getFileIndex() :
369 ModuleRootManager.getInstance(module).getFileIndex();
371 if (psiDirectory == null || findModel.isWithSubdirectories() && fileIndex.isInContent(psiDirectory.getVirtualFile())) {
372 final Pattern fileMaskRegExp = createFileMaskRegExp(findModel);
374 Pair<Boolean, Collection<PsiFile>> fastWords = getFilesForFastWordSearch(findModel, project, psiDirectory, fileMaskRegExp, module);
375 final Collection<PsiFile> filesForFastWordSearch = fastWords.getSecond();
377 if (fastWords.getFirst() && canOptimizeForFastWordSearch(findModel)) return filesForFastWordSearch;
379 final GlobalSearchScope customScope = toGlobal(project, findModel.getCustomScope());
381 class EnumContentIterator implements ContentIterator {
382 final List<PsiFile> myFiles = new ArrayList<PsiFile>(filesForFastWordSearch);
383 final PsiManager psiManager = PsiManager.getInstance(project);
386 public boolean processFile(VirtualFile virtualFile) {
387 if (!virtualFile.isDirectory() &&
388 (fileMaskRegExp == null || fileMaskRegExp.matcher(virtualFile.getName()).matches()) &&
389 (customScope == null || customScope.contains(virtualFile))) {
390 final PsiFile psiFile = psiManager.findFile(virtualFile);
391 if (psiFile != null && !filesForFastWordSearch.contains(psiFile)) {
392 myFiles.add(psiFile);
398 private Collection<PsiFile> getFiles() {
402 final EnumContentIterator iterator = new EnumContentIterator();
404 if (psiDirectory == null) {
405 boolean success = fileIndex.iterateContent(iterator);
406 if (success && customScope instanceof GlobalSearchScope && ((GlobalSearchScope)customScope).isSearchInLibraries()) {
407 OrderEnumerator enumerator = module == null ? OrderEnumerator.orderEntries(project) : OrderEnumerator.orderEntries(module);
408 final VirtualFile[] librarySources = enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
409 iterateAll(librarySources, (GlobalSearchScope)customScope, iterator);
413 fileIndex.iterateContentUnderDirectory(psiDirectory.getVirtualFile(), iterator);
415 return iterator.getFiles();
418 Collection<PsiFile> fileList = new THashSet<PsiFile>();
420 addFilesUnderDirectory(psiDirectory,
422 findModel.isWithSubdirectories(),
423 createFileMaskRegExp(findModel));
428 private static boolean iterateAll(VirtualFile[] files, final GlobalSearchScope searchScope, final ContentIterator iterator) {
429 final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
430 final VirtualFileFilter contentFilter = new VirtualFileFilter() {
432 public boolean accept(final VirtualFile file) {
433 return file.isDirectory() ||
434 !fileTypeManager.isFileIgnored(file) && !file.getFileType().isBinary() && searchScope.contains(file);
437 for (VirtualFile file : files) {
438 if (!FileIndexImplUtil.iterateRecursively(file, contentFilter, iterator)) return false;
444 private static GlobalSearchScope toGlobal(Project project, @Nullable SearchScope scope) {
445 if (scope instanceof GlobalSearchScope) {
446 return (GlobalSearchScope)scope;
448 Set<VirtualFile> files = new HashSet<VirtualFile>();
449 for (PsiElement element : ((LocalSearchScope)scope).getScope()) {
450 PsiFile file = element.getContainingFile();
452 ContainerUtil.addIfNotNull(files, file.getVirtualFile());
455 return GlobalSearchScope.filesScope(project, files);
459 private static Pair<Boolean, Collection<PsiFile>> getFilesForFastWordSearch(final FindModel findModel, final Project project,
460 final PsiDirectory psiDirectory, final Pattern fileMaskRegExp,
461 final Module module) {
462 if (DumbService.getInstance(project).isDumb()) {
463 return new Pair<Boolean, Collection<PsiFile>>(false, Collections.<PsiFile>emptyList());
466 PsiManager pm = PsiManager.getInstance(project);
467 CacheManager cacheManager = CacheManager.SERVICE.getInstance(project);
468 SearchScope customScope = findModel.getCustomScope();
469 @NotNull GlobalSearchScope scope = psiDirectory != null
470 ? GlobalSearchScopes.directoryScope(psiDirectory, true)
472 ? moduleContentScope(module)
473 : customScope instanceof GlobalSearchScope
474 ? (GlobalSearchScope)customScope
475 : GlobalSearchScope.projectScope(project);
477 Set<Integer> keys = new THashSet<Integer>(30);
478 Set<PsiFile> resultFiles = new THashSet<PsiFile>();
479 boolean fast = false;
481 if (TrigramIndex.ENABLED) {
482 TIntHashSet trigrams = TrigramBuilder.buildTrigram(findModel.getStringToFind());
483 TIntIterator it = trigrams.iterator();
484 while (it.hasNext()) {
488 if (!keys.isEmpty()) {
490 List<VirtualFile> hits = new ArrayList<VirtualFile>();
491 FileBasedIndex.getInstance()
492 .getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), scope);
494 for (VirtualFile hit : hits) {
495 resultFiles.add(pm.findFile(hit));
498 filterMaskedFiles(resultFiles, fileMaskRegExp);
499 if (resultFiles.isEmpty()) return new Pair<Boolean, Collection<PsiFile>>(true, resultFiles);
504 // $ is used to separate words when indexing plain-text files but not when indexing
505 // Java identifiers, so we can't consistently break a string containing $ characters into words
507 fast |= findModel.isWholeWordsOnly() && findModel.getStringToFind().indexOf('$') < 0;
509 List<String> words = StringUtil.getWordsIn(findModel.getStringToFind());
511 // hope long words are rare
512 Collections.sort(words, new Comparator<String>() {
514 public int compare(final String o1, final String o2) {
515 return o2.length() - o1.length();
519 for (int i = 0; i < words.size(); i++) {
520 String word = words.get(i);
522 PsiFile[] files = cacheManager.getFilesWithWord(word, UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
523 if (files.length == 0) {
528 final List<PsiFile> psiFiles = Arrays.asList(files);
530 if (i == 0 && keys.isEmpty()) {
531 resultFiles.addAll(psiFiles);
534 resultFiles.retainAll(psiFiles);
537 filterMaskedFiles(resultFiles, fileMaskRegExp);
538 if (resultFiles.isEmpty()) break;
541 // in case our word splitting is incorrect
542 PsiFile[] allWordsFiles =
543 cacheManager.getFilesWithWord(findModel.getStringToFind(), UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
544 ContainerUtil.addAll(resultFiles, allWordsFiles);
546 filterMaskedFiles(resultFiles, fileMaskRegExp);
548 return new Pair<Boolean, Collection<PsiFile>>(fast, resultFiles);
551 private static GlobalSearchScope moduleContentScope(final Module module) {
552 VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
553 GlobalSearchScope result = null;
554 PsiManager psiManager = PsiManager.getInstance(module.getProject());
555 for (VirtualFile root : contentRoots) {
556 PsiDirectory directory = psiManager.findDirectory(root);
557 if (directory != null) {
558 GlobalSearchScope moduleContent = GlobalSearchScopes.directoryScope(directory, true);
559 result = result == null ? moduleContent : result.uniteWith(moduleContent);
562 if (result == null) {
563 result = GlobalSearchScope.EMPTY_SCOPE;
568 private static void filterMaskedFiles(final Set<PsiFile> resultFiles, final Pattern fileMaskRegExp) {
569 if (fileMaskRegExp != null) {
570 for (Iterator<PsiFile> iterator = resultFiles.iterator(); iterator.hasNext();) {
571 PsiFile file = iterator.next();
572 if (!fileMaskRegExp.matcher(file.getName()).matches()) {
579 private static boolean canOptimizeForFastWordSearch(final FindModel findModel) {
580 return !findModel.isRegularExpressions()
581 && (findModel.getCustomScope() == null || findModel.getCustomScope() instanceof GlobalSearchScope);
584 private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
585 @NotNull final PsiFile psiFile, int[] offsetRef, int maxUsages) {
587 CharSequence text = document.getCharsSequence();
588 int textLength = document.getTextLength();
589 int offset = offsetRef[0];
591 Project project = psiFile.getProject();
593 UsageViewManager usageViewManager = UsageViewManager.getInstance(project);
594 FindManager findManager = FindManager.getInstance(project);
595 while (offset < textLength) {
596 usageViewManager.checkSearchCanceled();
597 FindResult result = findManager.findString(text, offset, findModel, psiFile.getVirtualFile());
598 if (!result.isStringFound()) break;
600 final SearchScope customScope = findModel.getCustomScope();
601 if (customScope instanceof LocalSearchScope) {
602 final TextRange range = new TextRange(result.getStartOffset(), result.getEndOffset());
603 if (!((LocalSearchScope)customScope).containsRange(psiFile, range)) break;
605 UsageInfo info = new UsageInfo(psiFile, result.getStartOffset(), result.getEndOffset());
606 if (!consumer.process(info)) break;
609 final int prevOffset = offset;
610 offset = result.getEndOffset();
612 if (prevOffset == offset) {
613 // for regular expr the size of the match could be zero -> could be infinite loop in finding usages!
616 if (maxUsages > 0 && count >= maxUsages) {
620 offsetRef[0] = offset;
624 private static String getTitleForScope(final FindModel findModel) {
627 if (findModel.isProjectScope()) {
628 result = FindBundle.message("find.scope.project.title");
630 else if (findModel.getModuleName() != null) {
631 result = FindBundle.message("find.scope.module.title", findModel.getModuleName());
633 else if(findModel.getCustomScopeName() != null) {
634 result = findModel.getCustomScopeName();
637 result = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName());
640 if (findModel.getFileFilter() != null) {
641 result = FindBundle.message("find.scope.files.with.mask", result, findModel.getFileFilter());
647 public static UsageViewPresentation setupViewPresentation(final boolean toOpenInNewTab, final FindModel findModelCopy) {
648 final UsageViewPresentation presentation = new UsageViewPresentation();
650 final String scope = getTitleForScope(findModelCopy);
651 final String stringToFind = findModelCopy.getStringToFind();
652 presentation.setScopeText(scope);
653 presentation.setTabText(FindBundle.message("find.usage.view.tab.text", stringToFind));
654 presentation.setToolwindowTitle(FindBundle.message("find.usage.view.toolwindow.title", stringToFind, scope));
655 presentation.setUsagesString(FindBundle.message("find.usage.view.usages.text", stringToFind));
656 presentation.setOpenInNewTab(toOpenInNewTab);
657 presentation.setCodeUsages(false);
662 public static FindUsagesProcessPresentation setupProcessPresentation(final Project project,
663 final boolean showPanelIfOnlyOneUsage,
664 final UsageViewPresentation presentation) {
665 FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation();
666 processPresentation.setShowNotFoundMessage(true);
667 processPresentation.setShowPanelIfOnlyOneUsage(showPanelIfOnlyOneUsage);
668 processPresentation.setProgressIndicatorFactory(
669 new Factory<ProgressIndicator>() {
671 public ProgressIndicator create() {
672 return new FindProgressIndicator(project, presentation.getScopeText());
676 return processPresentation;
679 public static class StringUsageTarget implements UsageTarget {
680 private final String myStringToFind;
682 private final ItemPresentation myItemPresentation = new ItemPresentation() {
684 public String getPresentableText() {
685 return FindBundle.message("find.usage.target.string.text", myStringToFind);
689 public String getLocationString() {
690 return myStringToFind + "!!";
694 public Icon getIcon(boolean open) {
699 public StringUsageTarget(String _stringToFind) {
700 myStringToFind = _stringToFind;
704 public void findUsages() {}
706 public void findUsagesInEditor(@NotNull FileEditor editor) {}
708 public void highlightUsages(PsiFile file, Editor editor, boolean clearHighlights) {}
711 public boolean isValid() {
716 public boolean isReadOnly() {
722 public VirtualFile[] getFiles() {
727 public void update() {
731 public String getName() {
732 return myStringToFind;
736 public ItemPresentation getPresentation() {
737 return myItemPresentation;
741 public void navigate(boolean requestFocus) {
742 throw new UnsupportedOperationException();
746 public boolean canNavigate() {
751 public boolean canNavigateToSource() {