mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
infer nullity: preview with ability to exclude some usages(IDEA-123110), remember "annotate local" checkbox
This commit is contained in:
@@ -18,23 +18,24 @@ package com.intellij.codeInspection.inferNullity;
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.SequentialModalProgressTask;
|
||||
import com.intellij.util.SequentialTask;
|
||||
|
||||
class AnnotateTask implements SequentialTask {
|
||||
private final Project myProject;
|
||||
private final NullityInferrer myInferrer;
|
||||
private UsageInfo[] myInfos;
|
||||
private final SequentialModalProgressTask myTask;
|
||||
private int myCount = 0;
|
||||
private final int myTotal;
|
||||
private final NullableNotNullManager myNotNullManager;
|
||||
|
||||
public AnnotateTask(Project project, NullityInferrer inferrer, SequentialModalProgressTask progressTask) {
|
||||
public AnnotateTask(Project project, SequentialModalProgressTask progressTask, UsageInfo[] infos) {
|
||||
myProject = project;
|
||||
myInfos = infos;
|
||||
myNotNullManager = NullableNotNullManager.getInstance(myProject);
|
||||
myInferrer = inferrer;
|
||||
myTask = progressTask;
|
||||
myTotal = myInferrer.getCount();
|
||||
myTotal = infos.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,7 +54,7 @@ class AnnotateTask implements SequentialTask {
|
||||
indicator.setFraction(((double)myCount) / myTotal);
|
||||
}
|
||||
|
||||
myInferrer.apply(myCount++, myProject, myNotNullManager);
|
||||
NullityInferrer.apply(myProject, myNotNullManager, myInfos[myCount++]);
|
||||
|
||||
return isDone();
|
||||
}
|
||||
|
||||
+117
-13
@@ -25,13 +25,14 @@ import com.intellij.codeInsight.daemon.impl.quickfix.LocateLibraryDialog;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.history.LocalHistory;
|
||||
import com.intellij.history.LocalHistoryAction;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -41,24 +42,35 @@ import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryUtil;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.ui.TitledSeparator;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.usages.*;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SequentialModalProgressTask;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
@NonNls private static final String INFER_NULLITY_ANNOTATIONS = "Infer Nullity Annotations";
|
||||
@NonNls private static final String ANNOTATE_LOCAL_VARIABLES = "annotate.local.variables";
|
||||
private JCheckBox myAnnotateLocalVariablesCb;
|
||||
|
||||
public InferNullityAnnotationsAction() {
|
||||
@@ -67,6 +79,9 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
|
||||
@Override
|
||||
protected void analyze(@NotNull final Project project, @NotNull final AnalysisScope scope) {
|
||||
|
||||
PropertiesComponent.getInstance().setValue(ANNOTATE_LOCAL_VARIABLES, String.valueOf(myAnnotateLocalVariablesCb.isSelected()));
|
||||
|
||||
final ProgressManager progressManager = ProgressManager.getInstance();
|
||||
final int totalFiles = scope.getFileCount();
|
||||
|
||||
@@ -91,7 +106,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
}
|
||||
progressIndicator.setFraction(((double)myFileCount) / totalFiles);
|
||||
}
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(file);
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module != null && !processed.contains(module)) {
|
||||
processed.add(module);
|
||||
if (JavaPsiFacade.getInstance(project)
|
||||
@@ -173,12 +188,32 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
return;
|
||||
}
|
||||
if (scope.checkScopeWritable(project)) return;
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
final UsageInfo[] usageInfos = findUsages(project, scope);
|
||||
if (usageInfos == null) return;
|
||||
|
||||
if (usageInfos.length < 5) {
|
||||
SwingUtilities.invokeLater(applyRunnable(project, new Computable<UsageInfo[]>() {
|
||||
@Override
|
||||
public UsageInfo[] compute() {
|
||||
return usageInfos;
|
||||
}
|
||||
}));
|
||||
}
|
||||
else {
|
||||
showUsageView(project, usageInfos, scope);
|
||||
}
|
||||
}
|
||||
|
||||
private UsageInfo[] findUsages(final Project project,
|
||||
final AnalysisScope scope) {
|
||||
final NullityInferrer inferrer = new NullityInferrer(myAnnotateLocalVariablesCb.isSelected(), project);
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
if (!progressManager.runProcessWithProgressSynchronously(new Runnable() {
|
||||
final Runnable searchForUsages = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int totalFiles = scope.getFileCount();
|
||||
scope.accept(new PsiElementVisitor() {
|
||||
int myFileCount = 0;
|
||||
|
||||
@@ -191,9 +226,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
if (document == null || virtualFile.getFileType().isBinary()) return; //do not inspect binary files
|
||||
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (progressIndicator != null) {
|
||||
if (virtualFile != null) {
|
||||
progressIndicator.setText2(ProjectUtil.calcRelativeToProjectPath(virtualFile, project));
|
||||
}
|
||||
progressIndicator.setText2(ProjectUtil.calcRelativeToProjectPath(virtualFile, project));
|
||||
progressIndicator.setFraction(((double)myFileCount) / totalFiles);
|
||||
}
|
||||
if (file instanceof PsiJavaFile) {
|
||||
@@ -202,11 +235,22 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
}
|
||||
});
|
||||
}
|
||||
}, INFER_NULLITY_ANNOTATIONS, true, project)) {
|
||||
return;
|
||||
};
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(searchForUsages, INFER_NULLITY_ANNOTATIONS, true, project)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
searchForUsages.run();
|
||||
}
|
||||
|
||||
final Runnable applyRunnable = new Runnable() {
|
||||
final List<UsageInfo> usages = new ArrayList<UsageInfo>();
|
||||
inferrer.collect(usages);
|
||||
return usages.toArray(new UsageInfo[usages.size()]);
|
||||
}
|
||||
|
||||
private static Runnable applyRunnable(final Project project, final Computable<UsageInfo[]> computable) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final LocalHistoryAction action = LocalHistory.getInstance().startAction(INFER_NULLITY_ANNOTATIONS);
|
||||
@@ -214,11 +258,14 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
new WriteCommandAction(project, INFER_NULLITY_ANNOTATIONS) {
|
||||
@Override
|
||||
protected void run(Result result) throws Throwable {
|
||||
if (!inferrer.nothingFoundMessage(project)) {
|
||||
final UsageInfo[] infos = computable.compute();
|
||||
if (infos.length > 0) {
|
||||
final SequentialModalProgressTask progressTask = new SequentialModalProgressTask(project, INFER_NULLITY_ANNOTATIONS, false);
|
||||
progressTask.setMinIterationTime(200);
|
||||
progressTask.setTask(new AnnotateTask(project, inferrer, progressTask));
|
||||
progressTask.setTask(new AnnotateTask(project, progressTask, infos));
|
||||
ProgressManager.getInstance().run(progressTask);
|
||||
} else {
|
||||
NullityInferrer.nothingFoundMessage(project);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
@@ -228,7 +275,6 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(applyRunnable);
|
||||
}
|
||||
|
||||
private void restartAnalysis(final Project project, final AnalysisScope scope) {
|
||||
@@ -241,11 +287,69 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction {
|
||||
}
|
||||
|
||||
|
||||
private void showUsageView(final Project project, final UsageInfo[] usageInfos, AnalysisScope scope) {
|
||||
final UsageTarget[] targets = UsageTarget.EMPTY_ARRAY;
|
||||
final Ref<Usage[]> convertUsagesRef = new Ref<Usage[]>();
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
convertUsagesRef.set(UsageInfo2UsageAdapter.convert(usageInfos));
|
||||
}
|
||||
});
|
||||
}
|
||||
}, "Preprocess usages", true, project)) return;
|
||||
|
||||
if (convertUsagesRef.isNull()) return;
|
||||
final Usage[] usages = convertUsagesRef.get();
|
||||
|
||||
final UsageViewPresentation presentation = new UsageViewPresentation();
|
||||
presentation.setTabText("Infer Nullity Preview");
|
||||
presentation.setShowReadOnlyStatusAsRed(true);
|
||||
presentation.setShowCancelButton(true);
|
||||
presentation.setUsagesString(RefactoringBundle.message("usageView.usagesText"));
|
||||
|
||||
final UsageView usageView = UsageViewManager.getInstance(project).showUsages(targets, usages, presentation, rerunFactory(project, scope));
|
||||
|
||||
final Runnable refactoringRunnable = applyRunnable(project, new Computable<UsageInfo[]>() {
|
||||
@Override
|
||||
public UsageInfo[] compute() {
|
||||
final Set<UsageInfo> infos = UsageViewUtil.getNotExcludedUsageInfos(usageView);
|
||||
return infos.toArray(new UsageInfo[infos.size()]);
|
||||
}
|
||||
});
|
||||
|
||||
String canNotMakeString = "Cannot perform operation.\nThere were changes in code after usages have been found.\nPlease perform operation search again.";
|
||||
|
||||
usageView.addPerformOperationAction(refactoringRunnable, INFER_NULLITY_ANNOTATIONS, canNotMakeString, INFER_NULLITY_ANNOTATIONS, false);
|
||||
}
|
||||
|
||||
private Factory<UsageSearcher> rerunFactory(final Project project, final AnalysisScope scope) {
|
||||
return new Factory<UsageSearcher>() {
|
||||
@Override
|
||||
public UsageSearcher create() {
|
||||
return new UsageInfoSearcherAdapter() {
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
return InferNullityAnnotationsAction.this.findUsages(project, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull Processor<Usage> processor) {
|
||||
processUsages(processor, project);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent getAdditionalActionSettings(Project project, BaseAnalysisActionDialog dialog) {
|
||||
final JPanel panel = new JPanel(new VerticalFlowLayout());
|
||||
panel.add(new TitledSeparator());
|
||||
myAnnotateLocalVariablesCb = new JCheckBox("Annotate local variables", false);
|
||||
myAnnotateLocalVariablesCb = new JCheckBox("Annotate local variables", PropertiesComponent.getInstance().getBoolean(ANNOTATE_LOCAL_VARIABLES, false));
|
||||
panel.add(myAnnotateLocalVariablesCb);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.codeInspection.inferNullity;
|
||||
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -27,6 +26,7 @@ import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Query;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -145,49 +145,40 @@ public class NullityInferrer {
|
||||
public void apply(final Project project) {
|
||||
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
|
||||
for (SmartPsiElementPointer<? extends PsiModifierListOwner> pointer : myNullableSet) {
|
||||
annotateNullable(project, manager, pointer);
|
||||
annotateNullable(project, manager, pointer.getElement());
|
||||
}
|
||||
|
||||
for (SmartPsiElementPointer<? extends PsiModifierListOwner> pointer : myNotNullSet) {
|
||||
annotateNotNull(project, manager, pointer);
|
||||
annotateNotNull(project, manager, pointer.getElement());
|
||||
}
|
||||
|
||||
nothingFoundMessage(project);
|
||||
}
|
||||
|
||||
public boolean nothingFoundMessage(final Project project) {
|
||||
if (myNullableSet.isEmpty() && myNotNullSet.isEmpty()) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
throw new RuntimeException(NOTHING_FOUND_TO_INFER);
|
||||
}
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Messages.showInfoMessage(project, "No places found to infer @Nullable/@NotNull", "Infer Nullity Results");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
throw new RuntimeException(NOTHING_FOUND_TO_INFER);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void annotateNotNull(Project project,
|
||||
NullableNotNullManager manager,
|
||||
SmartPsiElementPointer<? extends PsiModifierListOwner> pointer) {
|
||||
final PsiModifierListOwner element = pointer.getElement();
|
||||
public static void nothingFoundMessage(final Project project) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Messages.showInfoMessage(project, "No places found to infer @Nullable/@NotNull", "Infer Nullity Results");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void annotateNotNull(Project project,
|
||||
NullableNotNullManager manager,
|
||||
final PsiModifierListOwner element) {
|
||||
if (element != null) {
|
||||
if (shouldIgnore(element)) return;
|
||||
if (element instanceof PsiField && ((PsiField)element).hasInitializer() && element.hasModifierProperty(PsiModifier.FINAL)) return;
|
||||
invoke(project, element, manager.getDefaultNotNull(), manager.getDefaultNullable());
|
||||
}
|
||||
}
|
||||
|
||||
private void annotateNullable(Project project,
|
||||
NullableNotNullManager manager,
|
||||
SmartPsiElementPointer<? extends PsiModifierListOwner> pointer) {
|
||||
final PsiModifierListOwner element = pointer.getElement();
|
||||
private static void annotateNullable(Project project,
|
||||
NullableNotNullManager manager,
|
||||
final PsiModifierListOwner element) {
|
||||
if (element != null) {
|
||||
if (shouldIgnore(element)) return;
|
||||
invoke(project, element, manager.getDefaultNullable(), manager.getDefaultNotNull());
|
||||
}
|
||||
}
|
||||
@@ -207,12 +198,11 @@ public class NullityInferrer {
|
||||
return myNotNullSet.size() + myNullableSet.size();
|
||||
}
|
||||
|
||||
public void apply(int i, Project project, NullableNotNullManager manager) {
|
||||
if (i < myNullableSet.size()) {
|
||||
annotateNullable(project, manager, myNullableSet.get(i));
|
||||
} else {
|
||||
i -= myNullableSet.size();
|
||||
annotateNotNull(project, manager, myNotNullSet.get(i));
|
||||
public static void apply(Project project, NullableNotNullManager manager, UsageInfo info) {
|
||||
if (info instanceof NullableUsageInfo) {
|
||||
annotateNullable(project, manager, (PsiModifierListOwner)info.getElement());
|
||||
} else if (info instanceof NotNullUsageInfo) {
|
||||
annotateNotNull(project, manager, (PsiModifierListOwner)info.getElement());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +233,33 @@ public class NullityInferrer {
|
||||
numAnnotationsAdded++;
|
||||
}
|
||||
|
||||
private static class NullableUsageInfo extends UsageInfo {
|
||||
public NullableUsageInfo(@NotNull PsiElement element) {
|
||||
super(element);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NotNullUsageInfo extends UsageInfo {
|
||||
private NotNullUsageInfo(@NotNull PsiElement element) {
|
||||
super(element);
|
||||
}
|
||||
}
|
||||
|
||||
public void collect(List<UsageInfo> usages) {
|
||||
collect(usages, true);
|
||||
collect(usages, false);
|
||||
}
|
||||
|
||||
private void collect(List<UsageInfo> usages, boolean nullable) {
|
||||
final List<SmartPsiElementPointer<? extends PsiModifierListOwner>> set = nullable ? myNullableSet : myNotNullSet;
|
||||
for (SmartPsiElementPointer<? extends PsiModifierListOwner> elementPointer : set) {
|
||||
final PsiModifierListOwner element = elementPointer.getElement();
|
||||
if (element != null && !shouldIgnore(element)) {
|
||||
usages.add(nullable ? new NullableUsageInfo(element) : new NotNullUsageInfo(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ExpressionIsNeverNullVisitor extends JavaElementVisitor {
|
||||
private boolean neverNull = true;
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
Factory<UsageSearcher> factory = new Factory<UsageSearcher>() {
|
||||
@Override
|
||||
public UsageSearcher create() {
|
||||
return new UsageSearcher() {
|
||||
return new UsageInfoSearcherAdapter() {
|
||||
@Override
|
||||
public void generate(@NotNull final Processor<Usage> processor) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@@ -249,38 +249,12 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
refreshElements(elements);
|
||||
}
|
||||
});
|
||||
final Ref<UsageInfo[]> refUsages = new Ref<UsageInfo[]>();
|
||||
final Ref<Boolean> dumbModeOccurred = new Ref<Boolean>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
refUsages.set(findUsages());
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
dumbModeOccurred.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!dumbModeOccurred.isNull()) {
|
||||
DumbService.getInstance(myProject).showDumbModeNotification("Usage search is not available until indices are ready");
|
||||
return;
|
||||
}
|
||||
final Usage[] usages = ApplicationManager.getApplication().runReadAction(new Computable<Usage[]>() {
|
||||
@Override
|
||||
public Usage[] compute() {
|
||||
return UsageInfo2UsageAdapter.convert(refUsages.get());
|
||||
}
|
||||
});
|
||||
processUsages(processor, myProject);
|
||||
}
|
||||
|
||||
for (final Usage usage : usages) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processor.process(usage);
|
||||
}
|
||||
});
|
||||
}
|
||||
@Override
|
||||
protected UsageInfo[] findUsages() {
|
||||
return BaseRefactoringProcessor.this.findUsages();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -418,7 +392,7 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
final Runnable refactoringRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Set<UsageInfo> usagesToRefactor = getUsageInfosToRefactor(usageView);
|
||||
Set<UsageInfo> usagesToRefactor = UsageViewUtil.getNotExcludedUsageInfos(usageView);
|
||||
final UsageInfo[] infos = usagesToRefactor.toArray(new UsageInfo[usagesToRefactor.size()]);
|
||||
if (ensureElementsWritable(infos, viewDescriptor)) {
|
||||
execute(infos);
|
||||
@@ -436,19 +410,6 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
RefactoringBundle.message("usageView.doAction"), false);
|
||||
}
|
||||
|
||||
private static Set<UsageInfo> getUsageInfosToRefactor(final UsageView usageView) {
|
||||
Set<Usage> excludedUsages = usageView.getExcludedUsages();
|
||||
|
||||
Set<UsageInfo> usageInfos = new LinkedHashSet<UsageInfo>();
|
||||
for (Usage usage : usageView.getUsages()) {
|
||||
if (usage instanceof UsageInfo2UsageAdapter && !excludedUsages.contains(usage)) {
|
||||
UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo();
|
||||
usageInfos.add(usageInfo);
|
||||
}
|
||||
}
|
||||
return usageInfos;
|
||||
}
|
||||
|
||||
private void doRefactoring(@NotNull final Collection<UsageInfo> usageInfoSet) {
|
||||
for (Iterator<UsageInfo> iterator = usageInfoSet.iterator(); iterator.hasNext();) {
|
||||
UsageInfo usageInfo = iterator.next();
|
||||
|
||||
@@ -30,6 +30,9 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo;
|
||||
import com.intellij.refactoring.util.NonCodeUsageInfo;
|
||||
import com.intellij.usages.Usage;
|
||||
import com.intellij.usages.UsageInfo2UsageAdapter;
|
||||
import com.intellij.usages.UsageView;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -163,4 +166,17 @@ public class UsageViewUtil {
|
||||
Project project = info.getProject();
|
||||
FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file, offset), requestFocus);
|
||||
}
|
||||
|
||||
public static Set<UsageInfo> getNotExcludedUsageInfos(final UsageView usageView) {
|
||||
Set<Usage> excludedUsages = usageView.getExcludedUsages();
|
||||
|
||||
Set<UsageInfo> usageInfos = new LinkedHashSet<UsageInfo>();
|
||||
for (Usage usage : usageView.getUsages()) {
|
||||
if (usage instanceof UsageInfo2UsageAdapter && !excludedUsages.contains(usage)) {
|
||||
UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo();
|
||||
usageInfos.add(usageInfo);
|
||||
}
|
||||
}
|
||||
return usageInfos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class UsageInfoSearcherAdapter implements UsageSearcher {
|
||||
protected void processUsages(final @NotNull Processor<Usage> processor, Project project) {
|
||||
final Ref<UsageInfo[]> refUsages = new Ref<UsageInfo[]>();
|
||||
final Ref<Boolean> dumbModeOccurred = new Ref<Boolean>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
refUsages.set(findUsages());
|
||||
}
|
||||
catch (IndexNotReadyException e) {
|
||||
dumbModeOccurred.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!dumbModeOccurred.isNull()) {
|
||||
DumbService.getInstance(project).showDumbModeNotification("Usage search is not available until indices are ready");
|
||||
return;
|
||||
}
|
||||
final Usage[] usages = ApplicationManager.getApplication().runReadAction(new Computable<Usage[]>() {
|
||||
@Override
|
||||
public Usage[] compute() {
|
||||
return UsageInfo2UsageAdapter.convert(refUsages.get());
|
||||
}
|
||||
});
|
||||
|
||||
for (final Usage usage : usages) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processor.process(usage);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract UsageInfo[] findUsages();
|
||||
}
|
||||
Reference in New Issue
Block a user