UsageView refactoring

Extract UsageViewEx interface to abstract UsageViewManagerImpl and SearchForUsagesRunnable from UsageViewImpl to enable alternative UsageView implementation in on-air
This commit is contained in:
andrey zaytsev
2018-03-06 20:40:40 +03:00
parent 76d0c4261d
commit 0735c3996e
4 changed files with 82 additions and 44 deletions
@@ -79,7 +79,7 @@ class SearchForUsagesRunnable implements Runnable {
private final AtomicReference<Usage> myFirstUsage = new AtomicReference<>();
@NotNull
private final Project myProject;
private final AtomicReference<UsageViewImpl> myUsageViewRef;
private final AtomicReference<UsageViewEx> myUsageViewRef;
private final UsageViewPresentation myPresentation;
private final UsageTarget[] mySearchFor;
private final Factory<UsageSearcher> mySearcherFactory;
@@ -91,7 +91,7 @@ class SearchForUsagesRunnable implements Runnable {
SearchForUsagesRunnable(@NotNull UsageViewManagerImpl usageViewManager,
@NotNull Project project,
@NotNull AtomicReference<UsageViewImpl> usageViewRef,
@NotNull AtomicReference<UsageViewEx> usageViewRef,
@NotNull UsageViewPresentation presentation,
@NotNull UsageTarget[] searchFor,
@NotNull Factory<UsageSearcher> searcherFactory,
@@ -303,19 +303,19 @@ class SearchForUsagesRunnable implements Runnable {
rangeBlinker.startBlinking();
}
private UsageViewImpl getUsageView(@NotNull ProgressIndicator indicator) {
UsageViewImpl usageView = myUsageViewRef.get();
private UsageViewEx getUsageView(@NotNull ProgressIndicator indicator) {
UsageViewEx usageView = myUsageViewRef.get();
if (usageView != null) return usageView;
int usageCount = myUsageCountWithoutDefinition.get();
if (usageCount >= 2 || usageCount == 1 && myProcessPresentation.isShowPanelIfOnlyOneUsage()) {
usageView = new UsageViewImpl(myProject, myPresentation, mySearchFor, mySearcherFactory);
usageView = myUsageViewManager.createEmptyUsageView(mySearchFor, myPresentation, mySearcherFactory);
usageView.associateProgress(indicator);
if (myUsageViewRef.compareAndSet(null, usageView)) {
if (myProcessPresentation.isShowFindOptionsPrompt()) {
openView(usageView);
}
else {
UsageViewImpl finalView = usageView;
UsageViewEx finalView = usageView;
SwingUtilities.invokeLater(() -> {
if (myProject.isDisposed()) return;
if (myListener != null) {
@@ -325,12 +325,12 @@ class SearchForUsagesRunnable implements Runnable {
}
final Usage firstUsage = myFirstUsage.get();
if (firstUsage != null) {
final UsageViewImpl finalUsageView = usageView;
final UsageViewEx finalUsageView = usageView;
ApplicationManager.getApplication().runReadAction(() -> finalUsageView.appendUsage(firstUsage));
}
}
else {
UsageViewImpl finalUsageView = usageView;
UsageViewEx finalUsageView = usageView;
// later because dispose does some sort of swing magic e.g. AnAction.unregisterCustomShortcutSet()
UIUtil.invokeLaterIfNeeded(() -> Disposer.dispose(finalUsageView));
}
@@ -339,10 +339,10 @@ class SearchForUsagesRunnable implements Runnable {
return null;
}
private void openView(@NotNull final UsageViewImpl usageView) {
private void openView(@NotNull final UsageViewEx usageView) {
SwingUtilities.invokeLater(() -> {
if (myProject.isDisposed()) return;
myUsageViewManager.addContent(usageView, myPresentation);
myUsageViewManager.showUsageView(usageView, myPresentation);
if (myListener != null) {
myListener.usageViewCreated(usageView);
}
@@ -394,7 +394,7 @@ class SearchForUsagesRunnable implements Runnable {
myFirstUsage.compareAndSet(null, usage);
}
final UsageViewImpl usageView = getUsageView(indicator1);
final UsageViewEx usageView = getUsageView(indicator1);
TooManyUsagesStatus tooManyUsagesStatus= TooManyUsagesStatus.getFrom(indicator1);
if (usageCount > UsageLimitUtil.USAGES_LIMIT && tooManyUsagesStatus.switchTooManyUsagesStatus()) {
@@ -470,12 +470,8 @@ class SearchForUsagesRunnable implements Runnable {
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
else {
final UsageViewImpl usageView = myUsageViewRef.get();
if (usageView != null) {
usageView.drainQueuedUsageNodes();
usageView.setSearchInProgress(false);
}
final UsageViewEx usageView = myUsageViewRef.get();
usageView.searchFinished();
final List<String> lines;
final HyperlinkListener hyperlinkListener;
if (myOutOfScopeUsages.get() == 0 || getPsiElement(mySearchFor)==null) {
@@ -498,7 +494,7 @@ class SearchForUsagesRunnable implements Runnable {
}
}
UsageViewImpl usageView = myUsageViewRef.get();
UsageViewEx usageView = myUsageViewRef.get();
if (usageView != null) {
usageView.waitForUpdateRequestsCompletion();
}
@@ -0,0 +1,25 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.usages.impl;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.usages.Usage;
import com.intellij.usages.UsageView;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface UsageViewEx extends UsageView {
boolean searchHasBeenCancelled();
void cancelCurrentSearch();
void associateProgress(@NotNull ProgressIndicator indicator);
void waitForUpdateRequestsCompletion();
void appendUsagesInBulk(@NotNull Collection<Usage> usages);
void setSearchInProgress(boolean searchInProgress);
void searchFinished();
}
@@ -83,12 +83,10 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.intellij.util.containers.Queue;
/**
* @author max
*/
public class UsageViewImpl implements UsageView {
public class UsageViewImpl implements UsageViewEx {
@NonNls public static final String SHOW_RECENT_FIND_USAGES_ACTION_ID = "UsageView.ShowRecentFindUsages";
private final UsageNodeTreeBuilder myBuilder;
@@ -458,14 +456,20 @@ public class UsageViewImpl implements UsageView {
indicesToFire.clear();
}
}
@Override
public void searchFinished() {
drainQueuedUsageNodes();
setSearchInProgress(false);
}
boolean searchHasBeenCancelled() {
@Override
public boolean searchHasBeenCancelled() {
ProgressIndicator progress = associatedProgress;
return progress != null && progress.isCanceled();
}
void cancelCurrentSearch() {
@Override
public void cancelCurrentSearch() {
ProgressIndicator progress = associatedProgress;
if (progress != null) {
ProgressWrapper.unwrap(progress).cancel();
@@ -1042,7 +1046,8 @@ public class UsageViewImpl implements UsageView {
return configurableTarget == null ? getShowUsagesWithSettingsShortcut() : configurableTarget.getShortcut();
}
void associateProgress(@NotNull ProgressIndicator indicator) {
@Override
public void associateProgress(@NotNull ProgressIndicator indicator) {
associatedProgress = indicator;
}
@@ -1135,7 +1140,8 @@ public class UsageViewImpl implements UsageView {
}
}
void waitForUpdateRequestsCompletion() {
@Override
public void waitForUpdateRequestsCompletion() {
assert !ApplicationManager.getApplication().isDispatchThread();
while (true) {
Future<?> request;
@@ -1152,7 +1158,7 @@ public class UsageViewImpl implements UsageView {
}
}
@SuppressWarnings("WeakerAccess")
@Override
public void appendUsagesInBulk(@NotNull Collection<Usage> usages) {
addUpdateRequest(ApplicationManager.getApplication().executeOnPooledThread(() -> ReadAction.run(() -> {
for (Usage usage : usages) {
@@ -1200,7 +1206,7 @@ public class UsageViewImpl implements UsageView {
.collect(Collectors.toSet());
}
};
myUsageNodes.keySet().removeIf(usage -> usages.contains(usage) ||
myUsageNodes.keySet().removeIf(usage -> usages.contains(usage) ||
usage instanceof UsageInfo2UsageAdapter && mergedInfos.getValue().contains(((UsageInfo2UsageAdapter)usage).getUsageInfo()));
if (!nodes.isEmpty() && !myPresentation.isDetachedMode()) {
@@ -1414,6 +1420,7 @@ public class UsageViewImpl implements UsageView {
return mySearchInProgress;
}
@Override
public void setSearchInProgress(boolean searchInProgress) {
mySearchInProgress = searchInProgress;
if (!myPresentation.isDetachedMode()) {
@@ -61,13 +61,21 @@ public class UsageViewManagerImpl extends UsageViewManager {
myProject = project;
}
@NotNull
protected UsageViewEx createEmptyUsageView(@NotNull UsageTarget[] targets,
@NotNull UsageViewPresentation presentation,
Factory<UsageSearcher> usageSearcherFactory) {
return new UsageViewImpl(myProject, presentation, targets, usageSearcherFactory);
}
@Override
@NotNull
public UsageView createUsageView(@NotNull UsageTarget[] targets,
public UsageViewEx createUsageView(@NotNull UsageTarget[] targets,
@NotNull Usage[] usages,
@NotNull UsageViewPresentation presentation,
Factory<UsageSearcher> usageSearcherFactory) {
UsageViewImpl usageView = new UsageViewImpl(myProject, presentation, targets, usageSearcherFactory);
UsageViewEx usageView = createEmptyUsageView(targets, presentation, usageSearcherFactory);
usageView.appendUsagesInBulk(Arrays.asList(usages));
ProgressManager.getInstance().run(new Task.Modal(myProject, "Waiting For Usages", false) {
@Override
@@ -86,14 +94,16 @@ public class UsageViewManagerImpl extends UsageViewManager {
@NotNull Usage[] foundUsages,
@NotNull UsageViewPresentation presentation,
Factory<UsageSearcher> factory) {
UsageView usageView = createUsageView(searchedFor, foundUsages, presentation, factory);
addContent((UsageViewImpl)usageView, presentation);
showToolWindow(true);
UIUtil.invokeLaterIfNeeded(() -> {
if (!((UsageViewImpl)usageView).isDisposed()) {
((UsageViewImpl)usageView).expandRoot();
}
});
UsageViewEx usageView = createUsageView(searchedFor, foundUsages, presentation, factory);
if (usageView instanceof UsageViewImpl) {
showToolWindow(true);
UIUtil.invokeLaterIfNeeded(() -> {
if (!((UsageViewImpl)usageView).isDisposed()) {
((UsageViewImpl)usageView).expandRoot();
}
});
}
showUsageView(usageView, presentation);
return usageView;
}
@@ -103,7 +113,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
return showUsages(searchedFor, foundUsages, presentation, null);
}
void addContent(@NotNull UsageViewImpl usageView, @NotNull UsageViewPresentation presentation) {
void showUsageView(@NotNull UsageViewEx usageView, @NotNull UsageViewPresentation presentation) {
Content content = com.intellij.usageView.UsageViewManager.getInstance(myProject).addContent(
presentation.getTabText(),
presentation.getTabName(),
@@ -113,7 +123,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
presentation.isOpenInNewTab(),
true
);
usageView.setContent(content);
((UsageViewImpl)usageView).setContent(content);
content.putUserData(USAGE_VIEW_KEY, usageView);
}
@@ -140,7 +150,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
throw new IllegalStateException("Can't start find usages from under write action. Please consider Application.invokeLater() it instead.");
}
final SearchScope searchScopeToWarnOfFallingOutOf = getMaxSearchScopeToWarnOfFallingOutOf(searchFor);
final AtomicReference<UsageViewImpl> usageViewRef = new AtomicReference<>();
final AtomicReference<UsageViewEx> usageViewRef = new AtomicReference<>();
long start = System.currentTimeMillis();
Task.Backgroundable task = new Task.Backgroundable(myProject, getProgressTitle(presentation), true, new SearchInBackgroundOption()) {
@Override
@@ -152,7 +162,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
@NotNull
@Override
public NotificationInfo getNotificationInfo() {
UsageViewImpl usageView = usageViewRef.get();
UsageViewEx usageView = usageViewRef.get();
int count = usageView == null ? 0 : usageView.getUsagesCount();
String notification = StringUtil.capitalizeWords(UsageViewBundle.message("usages.n", count), true);
LOG.debug(notification +" in "+(System.currentTimeMillis()-start) +"ms.");
@@ -219,10 +229,10 @@ public class UsageViewManagerImpl extends UsageViewManager {
@NotNull final ProgressIndicator indicator,
@NotNull final UsageViewPresentation presentation,
final int usageCount,
@Nullable final UsageViewImpl usageView) {
@Nullable final UsageViewEx usageView) {
UIUtil.invokeLaterIfNeeded(() -> {
if (usageView != null && usageView.searchHasBeenCancelled() || indicator.isCanceled()) return;
int shownUsageCount = usageView == null ? usageCount : usageView.getRoot().getRecursiveUsageCount();
int shownUsageCount = usageView instanceof UsageViewImpl ? ((UsageViewImpl)usageView).getRoot().getRecursiveUsageCount() : usageCount;
String message = UsageViewBundle.message("find.excessive.usage.count.prompt", shownUsageCount, StringUtil.pluralize(presentation.getUsagesWord()));
UsageLimitUtil.Result ret = UsageLimitUtil.showTooManyUsagesWarning(project, message, presentation);
if (ret == UsageLimitUtil.Result.ABORT) {