mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
too many usages dialog shows for regular find usages + more user friendly buttons
This commit is contained in:
@@ -45,7 +45,7 @@ public abstract class JavaFindUsagesDialog<T extends JavaFindUsagesOptions> exte
|
||||
}
|
||||
|
||||
private static boolean isTextSearch(PsiElement element, boolean isSingleFile, FindUsagesHandler handler) {
|
||||
return FindUsagesUtil.isSearchForTextOccurencesAvailable(element, isSingleFile, handler);
|
||||
return FindUsagesUtil.isSearchForTextOccurrencesAvailable(element, isSingleFile, handler);
|
||||
}
|
||||
|
||||
public void calcFindUsagesOptions(T options) {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
|
||||
}
|
||||
|
||||
private static boolean isTextSearch(PsiElement element, boolean isSingleFile, FindUsagesHandler handler) {
|
||||
return FindUsagesUtil.isSearchForTextOccurencesAvailable(element, isSingleFile, handler);
|
||||
return FindUsagesUtil.isSearchForTextOccurrencesAvailable(element, isSingleFile, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,9 +23,7 @@ public class FindUsagesUtil {
|
||||
private FindUsagesUtil() {
|
||||
}
|
||||
|
||||
public static boolean isSearchForTextOccurencesAvailable(PsiElement element, boolean isSingleFile, FindUsagesHandler handler) {
|
||||
if (isSingleFile) return false;
|
||||
|
||||
return handler != null && handler.isSearchForTextOccurencesAvailable(element, isSingleFile);
|
||||
public static boolean isSearchForTextOccurrencesAvailable(PsiElement element, boolean isSingleFile, FindUsagesHandler handler) {
|
||||
return !isSingleFile && handler != null && handler.isSearchForTextOccurencesAvailable(element, isSingleFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,7 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.impl.FileIndexImplUtil;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -63,7 +61,6 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.UsageSearchContext;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
@@ -75,6 +72,7 @@ import com.intellij.util.indexing.FileBasedIndex;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntIterator;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -84,7 +82,6 @@ import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FindInProjectUtil {
|
||||
private static final int USAGES_LIMIT = 1000;
|
||||
private static final int USAGES_PER_READ_ACTION = 100;
|
||||
private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
|
||||
private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
|
||||
@@ -191,8 +188,8 @@ public class FindInProjectUtil {
|
||||
return null;
|
||||
}
|
||||
String pattern;
|
||||
final String[] strings = filter.split(",");
|
||||
if (strings.length == 1) {
|
||||
final List<String> strings = StringUtil.split(filter, ",");
|
||||
if (strings.size() == 1) {
|
||||
pattern = PatternUtil.convertToRegex(filter.trim());
|
||||
}
|
||||
else {
|
||||
@@ -219,7 +216,7 @@ public class FindInProjectUtil {
|
||||
int i = 0;
|
||||
long totalFilesSize = 0;
|
||||
int count = 0;
|
||||
final boolean[] warningShown = new boolean[] {false};
|
||||
final boolean[] warningShown = {false};
|
||||
|
||||
final UsageViewManager usageViewManager = UsageViewManager.getInstance(project);
|
||||
for (final PsiFile psiFile : psiFiles) {
|
||||
@@ -253,53 +250,55 @@ public class FindInProjectUtil {
|
||||
progress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
|
||||
}
|
||||
|
||||
int countInFile = processUsagesInFile(psiFile, findModel, consumer, count, warningShown);
|
||||
int countInFile = processUsagesInFile(psiFile, findModel, consumer);
|
||||
|
||||
count += countInFile;
|
||||
if (countInFile > 0) {
|
||||
totalFilesSize += fileLength;
|
||||
if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
|
||||
showTooManyUsagesWaring(project, FindBundle.message("find.excessive.total.size.prompt", presentableSize(totalFilesSize),
|
||||
ApplicationNamesInfo.getInstance().getProductName()));
|
||||
warningShown[0] = true;
|
||||
String message = FindBundle.message("find.excessive.total.size.prompt", presentableSize(totalFilesSize),
|
||||
ApplicationNamesInfo.getInstance().getProductName());
|
||||
UsageLimitUtil.showAndCancelIfAborted(project, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!largeFiles.isEmpty()) {
|
||||
final StringBuilder message = new StringBuilder();
|
||||
message.append("<html><body>");
|
||||
@Language("HTML")
|
||||
String message = "<html><body>";
|
||||
if (largeFiles.size() == 1) {
|
||||
final VirtualFile vFile = largeFiles.iterator().next().getVirtualFile();
|
||||
message.
|
||||
append("File '").
|
||||
append(getPresentablePath(vFile)).
|
||||
append("' (").
|
||||
append(presentableSize(getFileLength(vFile))).
|
||||
append(") is ");
|
||||
message
|
||||
+= "File '"
|
||||
+ getPresentablePath(vFile)
|
||||
+ "' ("
|
||||
+ presentableSize(getFileLength(vFile))
|
||||
+ ") is ";
|
||||
}
|
||||
else {
|
||||
message.append("Files<br> ");
|
||||
message += "Files<br> ";
|
||||
|
||||
int counter = 0;
|
||||
for (PsiFile file : largeFiles) {
|
||||
final VirtualFile vFile = file.getVirtualFile();
|
||||
message.
|
||||
append(getPresentablePath(vFile)).
|
||||
append(" (").
|
||||
append(presentableSize(getFileLength(vFile))).
|
||||
append(")<br> ");
|
||||
message +=
|
||||
getPresentablePath(vFile)
|
||||
+ " ("
|
||||
+ presentableSize(getFileLength(vFile))
|
||||
+ ")<br> ";
|
||||
if (counter++ > 10) break;
|
||||
}
|
||||
|
||||
message.append("are ");
|
||||
message += "are ";
|
||||
}
|
||||
|
||||
message.append("too large and cannot be scanned</body></html>");
|
||||
message += "too large and cannot be scanned</body></html>";
|
||||
|
||||
final String finalMessage = message;
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, MessageType.WARNING, message.toString());
|
||||
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, MessageType.WARNING, finalMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -315,15 +314,13 @@ public class FindInProjectUtil {
|
||||
|
||||
private static int processUsagesInFile(final PsiFile psiFile,
|
||||
final FindModel findModel,
|
||||
final Processor<UsageInfo> consumer,
|
||||
int alreadyCounted,
|
||||
boolean[] warningShown) {
|
||||
final Processor<UsageInfo> consumer) {
|
||||
final VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
if (virtualFile == null) return 0;
|
||||
if (FileTypeManager.getInstance().getFileTypeByFile(virtualFile).isBinary()) return 0; // do not decompile .class files
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
|
||||
if (document == null) return 0;
|
||||
final int[] offset = new int[] {0};
|
||||
final int[] offset = {0};
|
||||
int count = 0;
|
||||
int found;
|
||||
do {
|
||||
@@ -336,12 +333,6 @@ public class FindInProjectUtil {
|
||||
}
|
||||
});
|
||||
count += found;
|
||||
final int total = count + alreadyCounted;
|
||||
if (found > 0 && total > USAGES_LIMIT && !warningShown[0]) {
|
||||
showTooManyUsagesWaring(psiFile.getProject(), FindBundle.message("find.excessive.usage.count.prompt", total));
|
||||
warningShown[0] = true;
|
||||
}
|
||||
|
||||
}
|
||||
while (found != 0);
|
||||
return count;
|
||||
@@ -372,42 +363,6 @@ public class FindInProjectUtil {
|
||||
return length[0];
|
||||
}
|
||||
|
||||
private static void showTooManyUsagesWaring(final Project project, final String message) {
|
||||
int retCode = invokeAndWait(new Computable<Integer>() {
|
||||
public Integer compute() {
|
||||
return Messages.showYesNoDialog(project, message, FindBundle.message("find.excessive.usages.title"), Messages.getWarningIcon());
|
||||
}
|
||||
});
|
||||
|
||||
if (retCode != DialogWrapper.OK_EXIT_CODE) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
private static int invokeAndWait(final Computable<Integer> f) {
|
||||
final int[] answer = new int[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
answer[0] = f.compute();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
answer[0] = 0;
|
||||
}
|
||||
|
||||
return answer[0];
|
||||
}
|
||||
|
||||
private static int showMessage(final Project project, final String message, final String title, final String[] buttons) {
|
||||
return invokeAndWait(new Computable<Integer>() {
|
||||
public Integer compute() {
|
||||
return Messages.showDialog(project, message, title, buttons, 0, Messages.getWarningIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Collection<PsiFile> getFilesToSearchIn(final FindModel findModel, final Project project, final PsiDirectory psiDirectory) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiFile>>() {
|
||||
public Collection<PsiFile> compute() {
|
||||
@@ -689,14 +644,6 @@ public class FindInProjectUtil {
|
||||
return presentation;
|
||||
}
|
||||
|
||||
public static boolean hasReadOnlyUsages(final Collection<Usage> usages) {
|
||||
for (Usage usage : usages) {
|
||||
if (usage.isReadOnly()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static FindUsagesProcessPresentation setupProcessPresentation(final Project project,
|
||||
final boolean showPanelIfOnlyOneUsage,
|
||||
final UsageViewPresentation presentation) {
|
||||
|
||||
+10
-2
@@ -66,6 +66,14 @@ public class ReplaceInProjectManager {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public static boolean hasReadOnlyUsages(final Collection<Usage> usages) {
|
||||
for (Usage usage : usages) {
|
||||
if (usage.isReadOnly()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static class ReplaceContext {
|
||||
private final UsageView usageView;
|
||||
private final FindModel findModel;
|
||||
@@ -168,7 +176,7 @@ public class ReplaceInProjectManager {
|
||||
private void replaceWithPrompt(final ReplaceContext replaceContext) {
|
||||
final List<Usage> _usages = replaceContext.getUsageView().getSortedUsages();
|
||||
|
||||
if (FindInProjectUtil.hasReadOnlyUsages(_usages)) {
|
||||
if (hasReadOnlyUsages(_usages)) {
|
||||
WindowManager.getInstance().getStatusBar(myProject)
|
||||
.setInfo(FindBundle.message("find.replace.occurrences.found.in.read.only.files.status"));
|
||||
return;
|
||||
@@ -363,7 +371,7 @@ public class ReplaceInProjectManager {
|
||||
ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtil.toVirtualFileArray(readOnlyFiles));
|
||||
}
|
||||
|
||||
if (FindInProjectUtil.hasReadOnlyUsages(selectedUsages)) {
|
||||
if (hasReadOnlyUsages(selectedUsages)) {
|
||||
int result = Messages.showOkCancelDialog(replaceContext.getUsageView().getComponent(),
|
||||
FindBundle.message("find.replace.occurrences.in.read.only.files.prompt"),
|
||||
FindBundle.message("find.replace.occurrences.in.read.only.files.title"),
|
||||
|
||||
@@ -152,7 +152,7 @@ public class TextOccurrencesUtil {
|
||||
public static boolean isSearchTextOccurencesEnabled(@NotNull PsiElement element) {
|
||||
final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager();
|
||||
final FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(element, true);
|
||||
return FindUsagesUtil.isSearchForTextOccurencesAvailable(element, false, handler);
|
||||
return FindUsagesUtil.isSearchForTextOccurrencesAvailable(element, false, handler);
|
||||
}
|
||||
|
||||
public interface UsageInfoFactory {
|
||||
|
||||
@@ -36,9 +36,6 @@ import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class UsageViewUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.usageView.UsageViewUtil");
|
||||
|
||||
|
||||
@@ -96,10 +96,8 @@ find.origin.entire.scope.radio=E&ntire scope
|
||||
find.searching.for.string.in.file.progress=Searching for ''{0}'' in {1}...
|
||||
find.searching.for.string.in.file.occurrences.progress={0,choice,0#No|1#{0}} {0,choice,0#occurrences|1#occurrence|2#occurrences} found so far
|
||||
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.excessive.usage.count.prompt={0} usages found so far. Are you sure you wish to continue?
|
||||
find.progress.search.completed=Search completed
|
||||
find.file.size.megabytes={0} megabytes
|
||||
find.excessive.usages.title=Too Many Usages
|
||||
find.scope.project.title=Project
|
||||
find.scope.module.title=Module {0}
|
||||
find.scope.directory.title=Directory {0}
|
||||
|
||||
@@ -62,3 +62,7 @@ show.usages.only.usage=It''s the only usage in {0}
|
||||
all.usages.are.in.this.line=All {0} usages in {1} are in this line
|
||||
no.usages.found.in=No usages found in {0}
|
||||
sort.alphabetically.action.text=Sort Members Alphabetically
|
||||
button.text.continue=Continue
|
||||
button.text.abort=Abort
|
||||
find.excessive.usages.title=Too Many Usages
|
||||
find.excessive.usage.count.prompt={0} usages found so far. Are you sure you wish to continue?
|
||||
|
||||
@@ -350,7 +350,7 @@ public class UsageInfo2UsageAdapter implements UsageInModule, UsageInLibrary, Us
|
||||
@NotNull
|
||||
public TextChunk[] getText() {
|
||||
if (isValid()) {
|
||||
// the check below makes sence only for valid PsiElement
|
||||
// the check below makes sense only for valid PsiElement
|
||||
final long currentModificationStamp = getCurrentModificationStamp();
|
||||
if (currentModificationStamp != myModificationStamp) {
|
||||
initChunks();
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.usages;
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.usageView.UsageViewBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
public class UsageLimitUtil {
|
||||
public static final int USAGES_LIMIT = 1000;
|
||||
|
||||
public static void showAndCancelIfAborted(final Project project, final String message) {
|
||||
int retCode = showTooManyUsagesWarning(project, message);
|
||||
|
||||
if (retCode != DialogWrapper.OK_EXIT_CODE) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
public static int showTooManyUsagesWarning(@NotNull Project project, @NotNull String message) {
|
||||
String[] buttons = {UsageViewBundle.message("button.text.continue"), UsageViewBundle.message("button.text.abort")};
|
||||
return showMessage(project, message, UsageViewBundle.message("find.excessive.usages.title"), buttons);
|
||||
}
|
||||
|
||||
private static int invokeAndWait(final Computable<Integer> f) {
|
||||
final int[] answer = new int[1];
|
||||
try {
|
||||
GuiUtils.runOrInvokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
answer[0] = f.compute();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
answer[0] = 0;
|
||||
}
|
||||
|
||||
return answer[0];
|
||||
}
|
||||
|
||||
private static int showMessage(final Project project, final String message, final String title, final String[] buttons) {
|
||||
return invokeAndWait(new Computable<Integer>() {
|
||||
public Integer compute() {
|
||||
return Messages.showDialog(project, message, title, buttons, 0, Messages.getWarningIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import com.intellij.usages.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.ui.RangeBlinker;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -52,6 +53,7 @@ import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -280,23 +282,37 @@ public class UsageViewManagerImpl extends UsageViewManager {
|
||||
|
||||
private void searchUsages() {
|
||||
UsageSearcher usageSearcher = mySearcherFactory.create();
|
||||
final AtomicBoolean warningShown = new AtomicBoolean();
|
||||
usageSearcher.generate(new Processor<Usage>() {
|
||||
public boolean process(final Usage usage) {
|
||||
checkSearchCanceled();
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (searchHasBeenCancelled() || indicator != null && indicator.isCanceled()) return false;
|
||||
|
||||
boolean incrementCounter = !isSelfUsage(usage, mySearchFor);
|
||||
|
||||
if (incrementCounter) {
|
||||
int usageCount = myUsageCountWithoutDefinition.incrementAndGet();
|
||||
final int usageCount = myUsageCountWithoutDefinition.incrementAndGet();
|
||||
if (usageCount == 1 && !myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
|
||||
myFirstUsage.compareAndSet(null, usage);
|
||||
}
|
||||
if (usageCount > UsageLimitUtil.USAGES_LIMIT && !warningShown.get() && warningShown.compareAndSet(false, true)) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (searchHasBeenCancelled() || indicator != null && indicator.isCanceled()) return;
|
||||
String message = UsageViewBundle.message("find.excessive.usage.count.prompt", myUsageCountWithoutDefinition.get());
|
||||
int ret = UsageLimitUtil.showTooManyUsagesWarning(myProject, message);
|
||||
if (ret != 0) {
|
||||
setCurrentSearchCancelled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
UsageViewImpl usageView = getUsageView();
|
||||
if (usageView != null) {
|
||||
usageView.appendUsageLater(usage);
|
||||
}
|
||||
}
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
return indicator == null || !indicator.isCanceled();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user