use of com.intellij.usageView.UsageInfo in project intellij-community by JetBrains.
the class ShowUsagesAction method showElementUsages.
private void showElementUsages(final Editor editor, @NotNull final RelativePoint popupPosition, @NotNull final FindUsagesHandler handler, final int maxUsages, @NotNull final FindUsagesOptions options) {
ApplicationManager.getApplication().assertIsDispatchThread();
final UsageViewSettings usageViewSettings = UsageViewSettings.getInstance();
final UsageViewSettings savedGlobalSettings = new UsageViewSettings();
savedGlobalSettings.loadState(usageViewSettings);
usageViewSettings.loadState(myUsageViewSettings);
final Project project = handler.getProject();
UsageViewManager manager = UsageViewManager.getInstance(project);
FindUsagesManager findUsagesManager = ((FindManagerImpl) FindManager.getInstance(project)).getFindUsagesManager();
final UsageViewPresentation presentation = findUsagesManager.createPresentation(handler, options);
presentation.setDetachedMode(true);
UsageViewImpl usageView = (UsageViewImpl) manager.createUsageView(UsageTarget.EMPTY_ARRAY, Usage.EMPTY_ARRAY, presentation, null);
if (editor != null) {
PsiReference reference = TargetElementUtil.findReference(editor);
if (reference != null) {
UsageInfo2UsageAdapter origin = new UsageInfo2UsageAdapter(new UsageInfo(reference));
usageView.setOriginUsage(origin);
}
}
Disposer.register(usageView, () -> {
myUsageViewSettings.loadState(usageViewSettings);
usageViewSettings.loadState(savedGlobalSettings);
});
final MyTable table = new MyTable();
final AsyncProcessIcon processIcon = new AsyncProcessIcon("xxx");
addUsageNodes(usageView.getRoot(), usageView, new ArrayList<>());
final List<Usage> usages = new ArrayList<>();
final Set<UsageNode> visibleNodes = new LinkedHashSet<>();
final List<UsageNode> data = collectData(usages, visibleNodes, usageView, presentation);
final AtomicInteger outOfScopeUsages = new AtomicInteger();
setTableModel(table, usageView, data, outOfScopeUsages, options.searchScope);
boolean isPreviewMode = Boolean.TRUE == PreviewManager.SERVICE.preview(handler.getProject(), UsagesPreviewPanelProvider.ID, Pair.create(usageView, table), false);
Runnable itemChosenCallback = prepareTable(table, editor, popupPosition, handler, maxUsages, options, isPreviewMode);
@Nullable final JBPopup popup = isPreviewMode ? null : createUsagePopup(usages, visibleNodes, handler, editor, popupPosition, maxUsages, usageView, options, table, itemChosenCallback, presentation, processIcon);
if (popup != null) {
Disposer.register(popup, usageView);
// show popup only if find usages takes more than 300ms, otherwise it would flicker needlessly
Alarm alarm = new Alarm(usageView);
alarm.addRequest(() -> showPopupIfNeedTo(popup, popupPosition), 300);
}
final PingEDT pingEDT = new PingEDT("Rebuild popup in EDT", o -> popup != null && popup.isDisposed(), 100, () -> {
if (popup != null && popup.isDisposed())
return;
final List<UsageNode> nodes = new ArrayList<>();
List<Usage> copy;
synchronized (usages) {
// open up popup as soon as several usages 've been found
if (popup != null && !popup.isVisible() && (usages.size() <= 1 || !showPopupIfNeedTo(popup, popupPosition))) {
return;
}
addUsageNodes(usageView.getRoot(), usageView, nodes);
copy = new ArrayList<>(usages);
}
rebuildTable(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed(), outOfScopeUsages, options.searchScope);
});
final MessageBusConnection messageBusConnection = project.getMessageBus().connect(usageView);
messageBusConnection.subscribe(UsageFilteringRuleProvider.RULES_CHANGED, pingEDT::ping);
final UsageTarget[] myUsageTarget = { new PsiElement2UsageTargetAdapter(handler.getPsiElement()) };
Processor<Usage> collect = usage -> {
if (!UsageViewManagerImpl.isInScope(usage, options.searchScope)) {
if (outOfScopeUsages.getAndIncrement() == 0) {
visibleNodes.add(USAGES_OUTSIDE_SCOPE_NODE);
usages.add(USAGES_OUTSIDE_SCOPE_SEPARATOR);
}
return true;
}
synchronized (usages) {
if (visibleNodes.size() >= maxUsages)
return false;
if (UsageViewManager.isSelfUsage(usage, myUsageTarget))
return true;
UsageNode node = ReadAction.compute(() -> usageView.doAppendUsage(usage));
usages.add(usage);
if (node != null) {
visibleNodes.add(node);
boolean continueSearch = true;
if (visibleNodes.size() == maxUsages) {
visibleNodes.add(MORE_USAGES_SEPARATOR_NODE);
usages.add(MORE_USAGES_SEPARATOR);
continueSearch = false;
}
pingEDT.ping();
return continueSearch;
}
}
return true;
};
final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, handler.getPrimaryElements(), handler.getSecondaryElements(), collect, options, () -> ApplicationManager.getApplication().invokeLater(() -> {
Disposer.dispose(processIcon);
Container parent = processIcon.getParent();
if (parent != null) {
parent.remove(processIcon);
parent.repaint();
}
// repaint title
pingEDT.ping();
synchronized (usages) {
if (visibleNodes.isEmpty()) {
if (usages.isEmpty()) {
String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(options));
hint(editor, text, handler, popupPosition, maxUsages, options, false);
cancel(popup);
}
// else all usages filtered out
} else if (visibleNodes.size() == 1) {
if (usages.size() == 1) {
//the only usage
Usage usage = visibleNodes.iterator().next().getUsage();
if (usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) {
hint(editor, UsageViewManagerImpl.outOfScopeMessage(outOfScopeUsages.get(), options.searchScope), handler, popupPosition, maxUsages, options, true);
} else {
String message = UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(options));
navigateAndHint(usage, message, handler, popupPosition, maxUsages, options);
}
cancel(popup);
} else {
assert usages.size() > 1 : usages;
// usage view can filter usages down to one
Usage visibleUsage = visibleNodes.iterator().next().getUsage();
if (areAllUsagesInOneLine(visibleUsage, usages)) {
String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(options));
navigateAndHint(visibleUsage, hint, handler, popupPosition, maxUsages, options);
cancel(popup);
}
}
} else {
if (popup != null) {
String title = presentation.getTabText();
boolean shouldShowMoreSeparator = visibleNodes.contains(MORE_USAGES_SEPARATOR_NODE);
String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator, visibleNodes.size() - (shouldShowMoreSeparator ? 1 : 0), false);
((AbstractPopup) popup).setCaption(fullTitle);
}
}
}
}, project.getDisposed()));
if (popup != null) {
Disposer.register(popup, indicator::cancel);
}
}
use of com.intellij.usageView.UsageInfo in project intellij-community by JetBrains.
the class ShowUsagesAction method prepareTable.
@NotNull
private Runnable prepareTable(final MyTable table, final Editor editor, final RelativePoint popupPosition, final FindUsagesHandler handler, final int maxUsages, @NotNull final FindUsagesOptions options, final boolean previewMode) {
SpeedSearchBase<JTable> speedSearch = new MySpeedSearch(table);
speedSearch.setComparator(new SpeedSearchComparator(false));
table.setRowHeight(PlatformIcons.CLASS_ICON.getIconHeight() + 2);
table.setShowGrid(false);
table.setShowVerticalLines(false);
table.setShowHorizontalLines(false);
table.setTableHeader(null);
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
table.setIntercellSpacing(new Dimension(0, 0));
final AtomicReference<List<Object>> selectedUsages = new AtomicReference<>();
final AtomicBoolean moreUsagesSelected = new AtomicBoolean();
final AtomicBoolean outsideScopeUsagesSelected = new AtomicBoolean();
table.getSelectionModel().addListSelectionListener(e -> {
selectedUsages.set(null);
outsideScopeUsagesSelected.set(false);
moreUsagesSelected.set(false);
List<Object> usages = null;
for (int i : table.getSelectedRows()) {
Object value = table.getValueAt(i, 0);
if (value instanceof UsageNode) {
Usage usage = ((UsageNode) value).getUsage();
if (usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) {
outsideScopeUsagesSelected.set(true);
usages = null;
break;
} else if (usage == MORE_USAGES_SEPARATOR) {
moreUsagesSelected.set(true);
usages = null;
break;
} else {
if (usages == null)
usages = new ArrayList<>();
usages.add(usage instanceof UsageInfo2UsageAdapter ? ((UsageInfo2UsageAdapter) usage).getUsageInfo().copy() : usage);
}
}
}
selectedUsages.set(usages);
});
final Runnable itemChosenCallback = () -> {
if (moreUsagesSelected.get()) {
appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
return;
}
if (outsideScopeUsagesSelected.get()) {
options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
showElementUsages(editor, popupPosition, handler, maxUsages, options);
return;
}
List<Object> usages = selectedUsages.get();
if (usages != null) {
for (Object usage : usages) {
if (usage instanceof UsageInfo) {
UsageViewUtil.navigateTo((UsageInfo) usage, true);
} else if (usage instanceof Navigatable) {
((Navigatable) usage).navigate(true);
}
}
}
};
if (previewMode) {
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED) && !UIUtil.isSelectionButtonDown(e) && !e.isConsumed()) {
itemChosenCallback.run();
}
}
});
table.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
itemChosenCallback.run();
}
}
});
}
return itemChosenCallback;
}
use of com.intellij.usageView.UsageInfo in project intellij-community by JetBrains.
the class FindUtil method findAll.
@Nullable
public static List<Usage> findAll(@NotNull Project project, @NotNull Editor editor, @NotNull FindModel findModel) {
final Document document = editor.getDocument();
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (psiFile == null)
return null;
CharSequence text = document.getCharsSequence();
int textLength = document.getTextLength();
final List<Usage> usages = new ArrayList<>();
FindManager findManager = FindManager.getInstance(project);
// when find all there is no diff in direction
findModel.setForward(true);
int offset = 0;
VirtualFile virtualFile = getVirtualFile(editor);
while (offset < textLength) {
FindResult result = findManager.findString(text, offset, findModel, virtualFile);
if (!result.isStringFound())
break;
usages.add(new UsageInfo2UsageAdapter(new UsageInfo(psiFile, result.getStartOffset(), result.getEndOffset())));
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;
}
}
return usages;
}
use of com.intellij.usageView.UsageInfo in project intellij-community by JetBrains.
the class VariableInplaceRenamer method performRefactoringRename.
protected void performRefactoringRename(final String newName, final StartMarkAction markAction) {
final String refactoringId = getRefactoringId();
try {
PsiNamedElement elementToRename = getVariable();
if (refactoringId != null) {
final RefactoringEventData beforeData = new RefactoringEventData();
beforeData.addElement(elementToRename);
beforeData.addStringProperties(myOldName);
myProject.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(refactoringId, beforeData);
}
if (!isIdentifier(newName, myLanguage)) {
return;
}
if (elementToRename != null) {
new WriteCommandAction(myProject, getCommandName()) {
@Override
protected void run(@NotNull Result result) throws Throwable {
renameSynthetic(newName);
}
}.execute();
}
AutomaticRenamerFactory[] factories = Extensions.getExtensions(AutomaticRenamerFactory.EP_NAME);
for (AutomaticRenamerFactory renamerFactory : factories) {
if (elementToRename != null && renamerFactory.isApplicable(elementToRename)) {
final List<UsageInfo> usages = new ArrayList<>();
final AutomaticRenamer renamer = renamerFactory.createRenamer(elementToRename, newName, new ArrayList<>());
if (renamer.hasAnythingToRename()) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
final AutomaticRenamingDialog renamingDialog = new AutomaticRenamingDialog(myProject, renamer);
if (!renamingDialog.showAndGet()) {
continue;
}
}
final Runnable runnable = () -> ApplicationManager.getApplication().runReadAction(() -> renamer.findUsages(usages, false, false));
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, RefactoringBundle.message("searching.for.variables"), true, myProject)) {
return;
}
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, PsiUtilCore.toPsiElementArray(renamer.getElements())))
return;
final Runnable performAutomaticRename = () -> {
CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject);
final UsageInfo[] usageInfos = usages.toArray(new UsageInfo[usages.size()]);
final MultiMap<PsiElement, UsageInfo> classified = RenameProcessor.classifyUsages(renamer.getElements(), usageInfos);
for (final PsiNamedElement element : renamer.getElements()) {
final String newElementName = renamer.getNewName(element);
if (newElementName != null) {
final Collection<UsageInfo> infos = classified.get(element);
RenameUtil.doRename(element, newElementName, infos.toArray(new UsageInfo[infos.size()]), myProject, RefactoringElementListener.DEAF);
}
}
};
final WriteCommandAction writeCommandAction = new WriteCommandAction(myProject, getCommandName()) {
@Override
protected void run(@NotNull Result result) throws Throwable {
performAutomaticRename.run();
}
};
if (ApplicationManager.getApplication().isUnitTestMode()) {
writeCommandAction.execute();
} else {
ApplicationManager.getApplication().invokeLater(() -> writeCommandAction.execute());
}
}
}
}
} finally {
if (refactoringId != null) {
final RefactoringEventData afterData = new RefactoringEventData();
afterData.addElement(getVariable());
afterData.addStringProperties(newName);
myProject.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(refactoringId, afterData);
}
try {
((EditorImpl) InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumbLater();
} finally {
FinishMarkAction.finish(myProject, myEditor, markAction);
}
}
}
use of com.intellij.usageView.UsageInfo in project intellij-community by JetBrains.
the class AutomaticRenamer method findUsagesForElement.
private boolean findUsagesForElement(PsiNamedElement element, List<UsageInfo> result, final boolean searchInStringsAndComments, final boolean searchInNonJavaFiles, List<UnresolvableCollisionUsageInfo> unresolvedUsages, Map<PsiElement, String> allRenames) {
final String newName = getNewName(element);
if (newName != null) {
final LinkedHashMap<PsiNamedElement, String> renames = new LinkedHashMap<>();
renames.putAll(myRenames);
if (allRenames != null) {
for (PsiElement psiElement : allRenames.keySet()) {
if (psiElement instanceof PsiNamedElement) {
renames.put((PsiNamedElement) psiElement, allRenames.get(psiElement));
}
}
}
final UsageInfo[] usages = RenameUtil.findUsages(element, newName, searchInStringsAndComments, searchInNonJavaFiles, renames);
for (final UsageInfo usage : usages) {
if (usage instanceof UnresolvableCollisionUsageInfo) {
if (unresolvedUsages != null) {
unresolvedUsages.add((UnresolvableCollisionUsageInfo) usage);
}
return false;
}
}
ContainerUtil.addAll(result, usages);
}
return true;
}
Aggregations