mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-184924 Refactor NavigationService to Support Extension Points
GitOrigin-RevId: e5395b9482f2e694b5889cc57671453d1f17d25b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8ec55d96fa
commit
746dbffb69
@@ -5,12 +5,15 @@ import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VFileProperty;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions;
|
||||
import com.intellij.platform.ide.navigation.NavigationServiceKt;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.pom.PomTargetPsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -93,7 +96,8 @@ public final class EditSourceUtil {
|
||||
public static boolean navigateToPsiElement(@NotNull PsiElement element) {
|
||||
Navigatable descriptor = getDescriptor(element);
|
||||
if (descriptor != null && descriptor.canNavigate()) {
|
||||
descriptor.navigate(true);
|
||||
Project project = element.getProject();
|
||||
NavigationServiceKt.navigateBlocking(project, descriptor, NavigationOptions.requestFocus(), null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder;
|
||||
import com.intellij.openapi.util.NlsActions;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.platform.backend.presentation.TargetPresentation;
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
@@ -49,6 +52,8 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.intellij.platform.ide.navigation.NavigationServiceKt.navigateBlocking;
|
||||
|
||||
public abstract class GotoTargetHandler implements CodeInsightActionHandler {
|
||||
private static final Logger LOG = Logger.getInstance(GotoTargetHandler.class);
|
||||
private static final PsiElementListCellRenderer<?> ourDefaultTargetElementRenderer = new DefaultPsiElementListCellRenderer();
|
||||
@@ -156,7 +161,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
|
||||
((AdditionalAction)element.getItem()).execute();
|
||||
}
|
||||
else {
|
||||
navigate(project, element, navigatable -> navigateToElement(navigatable));
|
||||
navigate(project, element, navigatable -> navigateToElement(project, navigatable));
|
||||
}
|
||||
}
|
||||
}).
|
||||
@@ -275,12 +280,21 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
|
||||
try (AccessToken ignore = SlowOperations.knownIssue("IDEA-339117, EA-842843")) {
|
||||
if (!descriptor.canNavigate()) return false;
|
||||
}
|
||||
navigateToElement(descriptor);
|
||||
navigateToElement(target.getProject(), descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
protected void navigateToElement(@NotNull Navigatable descriptor) {
|
||||
descriptor.navigate(true);
|
||||
IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
|
||||
Project project = frame != null ? frame.getProject() : null;
|
||||
navigateToElement(project, descriptor);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected void navigateToElement(@Nullable Project project, @NotNull Navigatable descriptor) {
|
||||
if (project == null) return;
|
||||
navigateBlocking(project, descriptor, NavigationOptions.requestFocus(), null);
|
||||
}
|
||||
|
||||
protected boolean shouldSortTargets() {
|
||||
|
||||
+3
-3
@@ -46,7 +46,7 @@ internal class GotoDeclarationOnlyHandler2(private val reporter: GotoDeclaration
|
||||
actionResult.navigationProvider?.let {
|
||||
GTDUCollector.recordNavigated(eventData, it.javaClass)
|
||||
}
|
||||
navigateRequestLazy(project, actionResult.requestor)
|
||||
navigateRequestLazy(project, actionResult.requestor, editor)
|
||||
reporter?.reportNavigatedToDeclaration(GotoDeclarationReporter.NavigationType.AUTO, actionResult.navigationProvider)
|
||||
}
|
||||
is MultipleTargets -> {
|
||||
@@ -58,7 +58,7 @@ internal class GotoDeclarationOnlyHandler2(private val reporter: GotoDeclaration
|
||||
navigationProvider?.let {
|
||||
GTDUCollector.recordNavigated(eventData, navigationProvider.javaClass)
|
||||
}
|
||||
navigateRequestLazy(project, requestor)
|
||||
navigateRequestLazy(project, requestor, editor)
|
||||
reporter?.reportNavigatedToDeclaration(GotoDeclarationReporter.NavigationType.FROM_POPUP, navigationProvider)
|
||||
}
|
||||
popup.showInBestPositionFor(editor)
|
||||
@@ -71,7 +71,7 @@ internal class GotoDeclarationOnlyHandler2(private val reporter: GotoDeclaration
|
||||
override fun startInWriteAction(): Boolean = false
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||
if (navigateToLookupItem(project)) {
|
||||
if (navigateToLookupItem(project, editor)) {
|
||||
return
|
||||
}
|
||||
if (EditorUtil.isCaretInVirtualSpace(editor)) {
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ class GotoDeclarationOrUsageHandler2 internal constructor(private val reporter:
|
||||
override fun startInWriteAction(): Boolean = false
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||
if (navigateToLookupItem(project)) {
|
||||
if (navigateToLookupItem(project, editor)) {
|
||||
return
|
||||
}
|
||||
if (EditorUtil.isCaretInVirtualSpace(editor)) {
|
||||
|
||||
+2
-2
@@ -46,14 +46,14 @@ internal object GotoTypeDeclarationHandler2 : CodeInsightActionHandler {
|
||||
private fun gotoTypeDeclaration(project: Project, editor: Editor, actionResult: NavigationActionResult) {
|
||||
when (actionResult) {
|
||||
is SingleTarget -> {
|
||||
navigateRequestLazy(project, actionResult.requestor)
|
||||
navigateRequestLazy(project, actionResult.requestor, editor)
|
||||
}
|
||||
is MultipleTargets -> {
|
||||
val popup = createTargetPopup(
|
||||
CodeInsightBundle.message("choose.type.popup.title"),
|
||||
actionResult.targets, LazyTargetWithPresentation::presentation
|
||||
) { (requestor, _) ->
|
||||
navigateRequestLazy(project, requestor)
|
||||
navigateRequestLazy(project, requestor, editor)
|
||||
}
|
||||
popup.showInBestPositionFor(editor)
|
||||
}
|
||||
|
||||
@@ -6,90 +6,63 @@ import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.codeInsight.hint.HintManager
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.codeInsight.multiverse.isSharedSourceSupportEnabled
|
||||
import com.intellij.codeInsight.navigation.impl.NavigationRequestor
|
||||
import com.intellij.codeInsight.navigation.impl.gtdTargetNavigatable
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.ide.IdeEventQueue
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.ide.util.PsiNavigationSupport
|
||||
import com.intellij.idea.ActionsBundle
|
||||
import com.intellij.lang.LanguageNamesValidation
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil.underModalProgress
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.fileEditor.FileNavigator
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.backend.navigation.NavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.DirectoryNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.RawNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.SharedSourceNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.SourceNavigationRequest
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions
|
||||
import com.intellij.platform.ide.navigation.navigateBlocking
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import com.intellij.util.ui.EDT
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
internal fun navigateToLookupItem(project: Project): Boolean {
|
||||
internal fun navigateToLookupItem(project: Project, editor: Editor): Boolean {
|
||||
val activeLookup: Lookup? = LookupManager.getInstance(project).activeLookup
|
||||
if (activeLookup == null) {
|
||||
return false
|
||||
}
|
||||
val currentItem = activeLookup.currentItem
|
||||
navigateRequestLazy(project) {
|
||||
navigateRequestLazy(project, {
|
||||
TargetElementUtil.targetElementFromLookupElement(currentItem)
|
||||
?.gtdTargetNavigatable()
|
||||
?.navigationRequest()
|
||||
}
|
||||
}, editor)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a [NavigationRequest] instance from [requestor] on a background thread, and calls [navigateRequest].
|
||||
*/
|
||||
internal fun navigateRequestLazy(project: Project, requestor: NavigationRequestor) {
|
||||
internal fun navigateRequestLazy(project: Project, requestor: NavigationRequestor, editor: Editor) {
|
||||
EDT.assertIsEdt()
|
||||
@Suppress("DialogTitleCapitalization")
|
||||
val request = underModalProgress(project, ActionsBundle.actionText("GotoDeclarationOnly")) {
|
||||
requestor.navigationRequest()
|
||||
}
|
||||
if (request != null) {
|
||||
navigateRequest(project, request)
|
||||
val dataContext = editor.component.let { DataManager.getInstance().getDataContext(it) }
|
||||
navigateRequest(project, request, dataContext = dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
@RequiresEdt
|
||||
fun navigateRequest(project: Project, request: NavigationRequest) {
|
||||
@JvmOverloads
|
||||
fun navigateRequest(project: Project, request: NavigationRequest, dataContext: DataContext? = null) {
|
||||
EDT.assertIsEdt()
|
||||
IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation()
|
||||
when (request) {
|
||||
is SourceNavigationRequest -> {
|
||||
// TODO support pure source request without OpenFileDescriptor
|
||||
val offset = request.offsetMarker?.takeIf { it.isValid }?.startOffset ?: -1
|
||||
val openFileDescriptor = if (request is SharedSourceNavigationRequest && isSharedSourceSupportEnabled(project)) {
|
||||
OpenFileDescriptor(project, request.file, request.context, offset)
|
||||
}
|
||||
else {
|
||||
OpenFileDescriptor(project, request.file, offset)
|
||||
}
|
||||
if (UISettings.getInstance().openInPreviewTabIfPossible && Registry.`is`("editor.preview.tab.navigation")) {
|
||||
openFileDescriptor.isUsePreviewTab = true
|
||||
}
|
||||
FileNavigator.getInstance().navigate(openFileDescriptor, true)
|
||||
}
|
||||
is DirectoryNavigationRequest -> {
|
||||
PsiNavigationSupport.getInstance().navigateToDirectory(request.directory, true)
|
||||
}
|
||||
is RawNavigationRequest -> {
|
||||
request.navigatable.navigate(true)
|
||||
}
|
||||
else -> {
|
||||
error("unsupported request ${request.javaClass.name}")
|
||||
}
|
||||
}
|
||||
navigateBlocking(project, request, NavigationOptions.requestFocus(), dataContext)
|
||||
}
|
||||
|
||||
internal fun notifyNowhereToGo(project: Project, editor: Editor, file: PsiFile, offset: Int) {
|
||||
|
||||
@@ -35,6 +35,9 @@ import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorLocation;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
|
||||
import com.intellij.openapi.fileEditor.impl.text.AsyncEditorLoader;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
@@ -103,6 +106,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -110,8 +114,6 @@ import java.util.stream.Collectors;
|
||||
import static com.intellij.find.actions.ResolverKt.findShowUsages;
|
||||
import static com.intellij.find.actions.SearchOptionsService.SearchVariant.SHOW_USAGES;
|
||||
import static com.intellij.find.actions.ShowUsagesActionHandler.getSecondInvocationHint;
|
||||
import static com.intellij.find.actions.ShowUsagesUtilsKt.getEditorFor;
|
||||
import static com.intellij.find.actions.ShowUsagesUtilsKt.navigateAndHint;
|
||||
import static com.intellij.find.findUsages.FindUsagesHandlerFactory.OperationMode.USAGES_WITH_DEFAULT_OPTIONS;
|
||||
import static com.intellij.util.FindUsagesScopeKt.FindUsagesScope;
|
||||
import static com.intellij.util.ObjectUtils.doIfNotNull;
|
||||
@@ -529,6 +531,19 @@ public final class ShowUsagesAction extends AnAction implements PopupAction, Hin
|
||||
return ShowUsagesManager.getInstance(project).showElementUsagesWithResult(parameters, actionHandler, usageView);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
private static Editor getEditorFor(Usage usage) {
|
||||
FileEditorLocation location = usage.getLocation();
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
FileEditor newFileEditor = location.getEditor();
|
||||
if (newFileEditor instanceof TextEditor fileEditor) {
|
||||
return fileEditor.getEditor();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Future<Collection<Usage>> showElementUsagesWithResult(@NotNull ShowUsagesParameters parameters,
|
||||
@NotNull ShowUsagesActionHandler actionHandler,
|
||||
@NotNull UsageViewImpl usageView) {
|
||||
@@ -567,7 +582,7 @@ public final class ShowUsagesAction extends AnAction implements PopupAction, Hin
|
||||
Runnable itemChosenCallback = table.prepareTable(
|
||||
showMoreUsagesRunnable(parameters, actionHandler),
|
||||
showUsagesInMaximalScopeRunnable(parameters, actionHandler, showUsagesPopupData),
|
||||
actionHandler
|
||||
actionHandler, parameters
|
||||
);
|
||||
|
||||
Consumer<AbstractPopup> tableResizer = popup -> {
|
||||
@@ -740,6 +755,18 @@ public final class ShowUsagesAction extends AnAction implements PopupAction, Hin
|
||||
// else all usages filtered out
|
||||
}
|
||||
else if (visibleUsages.size() == 1 && actionHandler.navigateToSingleUsageImmediately()) {
|
||||
final BiConsumer<Usage, String> onReady = (Usage usage, @Nls String hint) -> {
|
||||
var newEditor = getEditorFor(usage);
|
||||
if (newEditor == null) {
|
||||
cancel(popup);
|
||||
return;
|
||||
}
|
||||
if (parameters.editor != null) {
|
||||
hint(false, hint, parameters.withEditor(parameters.editor), actionHandler);
|
||||
}
|
||||
cancel(popup);
|
||||
};
|
||||
|
||||
if (usages.size() == 1) {
|
||||
//the only usage
|
||||
Usage usage = visibleUsages.iterator().next();
|
||||
@@ -750,7 +777,8 @@ public final class ShowUsagesAction extends AnAction implements PopupAction, Hin
|
||||
}
|
||||
else {
|
||||
String hint = UsageViewBundle.message("show.usages.only.usage", searchScope.getDisplayName());
|
||||
navigateAndHint(project, usage, hint, parameters, actionHandler, () -> cancel(popup));
|
||||
UsageNavigation.getInstance(project).navigateAndHint(
|
||||
project, usage, () -> onReady.accept(usage, hint), parameters.editor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -759,7 +787,8 @@ public final class ShowUsagesAction extends AnAction implements PopupAction, Hin
|
||||
Usage visibleUsage = visibleUsages.iterator().next();
|
||||
if (areAllUsagesInOneLine(visibleUsage, usages)) {
|
||||
String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScope.getDisplayName());
|
||||
navigateAndHint(project, visibleUsage, hint, parameters, actionHandler, () -> cancel(popup));
|
||||
UsageNavigation.getInstance(project).navigateAndHint(
|
||||
project, visibleUsage, () -> onReady.accept(visibleUsage, hint), parameters.editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.find.actions;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.gotoByName.ModelDiff;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataSink;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.UiDataProvider;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.util.PopupUtil;
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.popup.HintUpdateSupply;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.usages.Usage;
|
||||
import com.intellij.usages.UsageInfo2UsageAdapter;
|
||||
import com.intellij.usages.UsageToPsiElementProvider;
|
||||
@@ -44,6 +42,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.intellij.platform.ide.navigation.NavigationServiceKt.navigateBlocking;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public final class ShowUsagesTable extends JBTable implements UiDataProvider {
|
||||
final Usage MORE_USAGES_SEPARATOR = new UsageAdapter();
|
||||
@@ -93,7 +93,7 @@ public final class ShowUsagesTable extends JBTable implements UiDataProvider {
|
||||
|
||||
@NotNull
|
||||
Runnable prepareTable(@NotNull Runnable appendMoreUsageRunnable, @NotNull Runnable showInMaximalScopeRunnable,
|
||||
@NotNull ShowUsagesActionHandler actionHandler) {
|
||||
@NotNull ShowUsagesActionHandler actionHandler, @NotNull ShowUsagesParameters parameters) {
|
||||
SpeedSearchBase<JTable> speedSearch = MySpeedSearch.installOn(this);
|
||||
speedSearch.setComparator(new SpeedSearchComparator(false));
|
||||
|
||||
@@ -175,6 +175,8 @@ public final class ShowUsagesTable extends JBTable implements UiDataProvider {
|
||||
List<Object> usages = selectedUsages.get();
|
||||
if (usages != null) {
|
||||
for (Object usage : usages) {
|
||||
DataContext dataContext = parameters.editor != null ?
|
||||
DataManager.getInstance().getDataContext(parameters.editor.getContentComponent()) : null;
|
||||
if (usage instanceof UsageInfo usageInfo) {
|
||||
PsiElement selectedElement = usageInfo.getElement();
|
||||
if (selectedElement != null) {
|
||||
@@ -190,10 +192,10 @@ public final class ShowUsagesTable extends JBTable implements UiDataProvider {
|
||||
numberOfLettersTyped,
|
||||
selectedElement.getLanguage(), false);
|
||||
}
|
||||
UsageViewUtil.navigateTo(usageInfo, true);
|
||||
UsageNavigation.getInstance(parameters.project).navigate(usageInfo, true, dataContext);
|
||||
}
|
||||
else if (usage instanceof Navigatable) {
|
||||
((Navigatable)usage).navigate(true);
|
||||
else if (usage instanceof Navigatable navigatable) {
|
||||
navigateBlocking(parameters.project, navigatable, NavigationOptions.requestFocus(), dataContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.find.actions
|
||||
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.writeIntentReadAction
|
||||
import com.intellij.openapi.components.ComponentManagerEx
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions
|
||||
import com.intellij.platform.ide.navigation.NavigationService
|
||||
import com.intellij.usages.Usage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.Nls
|
||||
|
||||
internal fun navigateAndHint(project: Project,
|
||||
usage: Usage,
|
||||
hint: @Nls(capitalization = Nls.Capitalization.Sentence) String,
|
||||
parameters: ShowUsagesParameters,
|
||||
actionHandler: ShowUsagesActionHandler,
|
||||
onReady: Runnable) {
|
||||
// Code below need EDT
|
||||
(project as ComponentManagerEx).getCoroutineScope().launch(Dispatchers.EDT) {
|
||||
NavigationService.getInstance(project).navigate(usage, NavigationOptions.defaultOptions().requestFocus(true))
|
||||
writeIntentReadAction {
|
||||
val newEditor = getEditorFor(usage)
|
||||
if (newEditor == null) {
|
||||
onReady.run()
|
||||
return@writeIntentReadAction
|
||||
}
|
||||
|
||||
ShowUsagesAction.hint(false, hint, parameters.withEditor(newEditor), actionHandler)
|
||||
onReady.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getEditorFor(usage: Usage): Editor? {
|
||||
val location = usage.location
|
||||
val newFileEditor = location?.editor
|
||||
return if (newFileEditor is TextEditor) newFileEditor.editor else null
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.find.actions
|
||||
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.application.readActionBlocking
|
||||
import com.intellij.openapi.application.writeIntentReadAction
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.backend.navigation.NavigationRequest
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions
|
||||
import com.intellij.platform.ide.navigation.NavigationService
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usages.Usage
|
||||
import com.intellij.usages.impl.UsageViewStatisticsCollector
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@ApiStatus.Internal
|
||||
class UsageNavigation(private val project: Project, private val cs: CoroutineScope) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): UsageNavigation = project.getService(UsageNavigation::class.java)
|
||||
}
|
||||
|
||||
fun navigateAndHint(
|
||||
project: Project,
|
||||
usage: Usage,
|
||||
onReady: Runnable,
|
||||
editor: Editor?,
|
||||
) {
|
||||
cs.launch(Dispatchers.EDT) {
|
||||
val dataContext = editor?.let {
|
||||
DataManager.getInstance().getDataContext(it.component)
|
||||
}
|
||||
NavigationService.getInstance(project).navigate(usage, NavigationOptions.requestFocus(), dataContext)
|
||||
writeIntentReadAction {
|
||||
onReady.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun navigate(@NotNull info: UsageInfo, requestFocus: Boolean, dataContext: DataContext?) {
|
||||
cs.launch {
|
||||
navigateUsageInfo(info, requestFocus, dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun navigateUsageInfo(
|
||||
info: UsageInfo,
|
||||
requestFocus: Boolean,
|
||||
dataContext: DataContext?,
|
||||
) {
|
||||
val request = readAction {
|
||||
val offset = info.navigationOffset
|
||||
val project = info.project
|
||||
val file = info.virtualFile
|
||||
?: return@readAction null
|
||||
NavigationRequest.sourceNavigationRequest(project, file, offset)
|
||||
}
|
||||
request?.let {
|
||||
readActionBlocking { UsageViewStatisticsCollector.logUsageNavigate(project, info) }
|
||||
NavigationService.getInstance(project).navigate(it, NavigationOptions.defaultOptions().requestFocus(requestFocus), dataContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
-30
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.ide.navigation.impl
|
||||
|
||||
import com.intellij.codeInsight.multiverse.isSharedSourceSupportEnabled
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.ide.util.PsiNavigationSupport
|
||||
import com.intellij.injected.editor.VirtualFileWindow
|
||||
@@ -11,8 +12,10 @@ import com.intellij.openapi.actionSystem.impl.Utils.isAsyncDataContext
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.application.writeIntentReadAction
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.*
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
|
||||
import com.intellij.openapi.fileEditor.impl.EditorComposite
|
||||
@@ -27,17 +30,20 @@ import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.platform.backend.navigation.NavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.DirectoryNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.RawNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.SharedSourceNavigationRequest
|
||||
import com.intellij.platform.backend.navigation.impl.SourceNavigationRequest
|
||||
import com.intellij.platform.ide.navigation.NavigationHandler
|
||||
import com.intellij.platform.ide.navigation.NavigationOptions
|
||||
import com.intellij.platform.ide.navigation.NavigationService
|
||||
import com.intellij.platform.util.coroutines.sync.OverflowSemaphore
|
||||
import com.intellij.platform.util.progress.mapWithProgress
|
||||
import com.intellij.pom.Navigatable
|
||||
import com.intellij.util.containers.sequenceOfNotNull
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
private class IdeNavigationService(private val project: Project) : NavigationService {
|
||||
/**
|
||||
* - `permits = 1` means at any given time only one request is being handled.
|
||||
@@ -64,9 +70,9 @@ private class IdeNavigationService(private val project: Project) : NavigationSer
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun navigate(navigatables: List<Navigatable>, options: NavigationOptions): Boolean {
|
||||
override suspend fun navigate(navigatables: List<Navigatable>, options: NavigationOptions, dataContext: DataContext?): Boolean {
|
||||
return semaphore.withPermit {
|
||||
doNavigate(navigatables, options, dataContext = null)
|
||||
doNavigate(navigatables, options, dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,21 +85,9 @@ private class IdeNavigationService(private val project: Project) : NavigationSer
|
||||
return navigate(project = project, requests = requests, options = options, dataContext = dataContext)
|
||||
}
|
||||
|
||||
override suspend fun navigate(navigatable: Navigatable, options: NavigationOptions): Boolean {
|
||||
return semaphore.withPermit {
|
||||
val request = readAction {
|
||||
navigatable.navigationRequest()
|
||||
} ?: return@withPermit false
|
||||
navigate(project = project, requests = listOf(request), options = options, dataContext = null)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun navigate(request: NavigationRequest, options: NavigationOptions) {
|
||||
if (request is SourceNavigationRequest) {
|
||||
navigateToSource(project = project, request = request, options = options as NavigationOptions.Impl, dataContext = null)
|
||||
}
|
||||
else {
|
||||
navigate(project = project, requests = listOf(request), options = options, dataContext = null)
|
||||
override suspend fun navigate(request: NavigationRequest, options: NavigationOptions, dataContext: DataContext?) {
|
||||
semaphore.withPermit {
|
||||
navigate(project = project, requests = listOf(request), options = options, dataContext = dataContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +107,7 @@ private suspend fun navigate(project: Project, requests: List<NavigationRequest>
|
||||
if (maxSourceRequests in 1..navigatedSourcesCounter) {
|
||||
break
|
||||
}
|
||||
if (navigateToSource(project = project, request = requestFromNavigatable, options = options, dataContext = dataContext)) {
|
||||
if (tryNavigateToSource(project = project, request = requestFromNavigatable, options = options, dataContext = dataContext)) {
|
||||
navigatedSourcesCounter++
|
||||
}
|
||||
else if (nonSourceRequest == null) {
|
||||
@@ -132,15 +126,19 @@ private suspend fun navigate(project: Project, requests: List<NavigationRequest>
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun navigateToSource(
|
||||
private suspend fun tryNavigateToSource(
|
||||
project: Project,
|
||||
request: NavigationRequest,
|
||||
options: NavigationOptions.Impl,
|
||||
dataContext: DataContext?,
|
||||
): Boolean {
|
||||
if (dataContext != null && executeRequestHandler(request, options, dataContext)) {
|
||||
return true
|
||||
}
|
||||
|
||||
when (request) {
|
||||
is SourceNavigationRequest -> {
|
||||
navigateToSource(
|
||||
navigateToSourceImpl(
|
||||
request = request,
|
||||
options = options,
|
||||
project = project,
|
||||
@@ -185,7 +183,26 @@ private suspend fun navigateNonSource(project: Project, request: NavigationReque
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun navigateToSource(
|
||||
private val EP_NAME = ExtensionPointName.create<NavigationHandler>("com.intellij.navigation.navigationHandler")
|
||||
|
||||
private fun executeRequestHandler(request: NavigationRequest, options: NavigationOptions, dataContext: DataContext): Boolean {
|
||||
for (handler in EP_NAME.extensionList) {
|
||||
try {
|
||||
if (handler.navigate(request, options, dataContext)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
catch (ce: CancellationException) {
|
||||
throw ce
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error("Failed to navigate with $handler", e)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private suspend fun navigateToSourceImpl(
|
||||
options: NavigationOptions.Impl,
|
||||
request: SourceNavigationRequest,
|
||||
project: Project,
|
||||
@@ -200,20 +217,31 @@ private suspend fun navigateToSource(
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dataContext != null) {
|
||||
val descriptor = OpenFileDescriptor(project, request.file, request.offsetMarker?.takeIf { it.isValid }?.startOffset ?: -1)
|
||||
descriptor.isUseCurrentWindow = true
|
||||
if (UISettings.getInstance().openInPreviewTabIfPossible && Registry.`is`("editor.preview.tab.navigation")) {
|
||||
descriptor.isUsePreviewTab = true
|
||||
}
|
||||
val offset = request.offsetMarker?.takeIf { it.isValid }?.startOffset ?: -1
|
||||
val inEditorDataContext = dataContext?.let(OpenFileDescriptor.NAVIGATE_IN_EDITOR::getData) != null
|
||||
val descriptor = if (!inEditorDataContext && request is SharedSourceNavigationRequest && isSharedSourceSupportEnabled(project)) {
|
||||
OpenFileDescriptor(project, request.file, request.context, offset)
|
||||
}
|
||||
else {
|
||||
OpenFileDescriptor(project, request.file, offset)
|
||||
}
|
||||
if (UISettings.getInstance().openInPreviewTabIfPossible && Registry.`is`("editor.preview.tab.navigation")) {
|
||||
descriptor.isUsePreviewTab = true
|
||||
}
|
||||
|
||||
if (inEditorDataContext) {
|
||||
descriptor.isUseCurrentWindow = true
|
||||
val fileNavigator = serviceAsync<FileNavigator>()
|
||||
if (fileNavigator is FileNavigatorImpl && fileNavigator.navigateInRequestedEditorAsync(descriptor, dataContext)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (openFile(request = request, project = project, options = options)) {
|
||||
// TODO: replace with openFile once IJPL-184882 is fixed
|
||||
if (FileNavigator.getInstance().canNavigate(descriptor)) {
|
||||
withContext(Dispatchers.EDT) {
|
||||
FileNavigator.getInstance().navigate(descriptor, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -149,7 +150,8 @@ public class GotoTestOrCodeHandler extends GotoTargetHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void navigateToElement(@NotNull Navigatable element) {
|
||||
@ApiStatus.Internal
|
||||
protected void navigateToElement(@Nullable Project project, @NotNull Navigatable element) {
|
||||
if (element instanceof PsiElement) {
|
||||
NavigationUtil.activateFileWithPsiElement((PsiElement)element, true);
|
||||
}
|
||||
@@ -157,4 +159,10 @@ public class GotoTestOrCodeHandler extends GotoTargetHandler {
|
||||
element.navigate(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ApiStatus.Obsolete
|
||||
protected void navigateToElement(@NotNull Navigatable element) {
|
||||
navigateToElement(null, element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,13 +304,17 @@ f:com.intellij.openapi.wm.PermissionsKt
|
||||
- createMainPanelToolbar(com.intellij.openapi.Disposable):javax.swing.JComponent
|
||||
- createQuickAccessActions(com.intellij.openapi.Disposable):java.util.List
|
||||
- createQuickAccessComponent(com.intellij.openapi.Disposable):java.awt.Component
|
||||
*:com.intellij.platform.ide.navigation.NavigationHandler
|
||||
- a:navigate(com.intellij.platform.backend.navigation.NavigationRequest,com.intellij.platform.ide.navigation.NavigationOptions,com.intellij.openapi.actionSystem.DataContext):Z
|
||||
*:com.intellij.platform.ide.navigation.NavigationOptions
|
||||
- *sf:Companion:com.intellij.platform.ide.navigation.NavigationOptions$Companion
|
||||
- s:defaultOptions():com.intellij.platform.ide.navigation.NavigationOptions
|
||||
- a:preserveCaret(Z):com.intellij.platform.ide.navigation.NavigationOptions
|
||||
- s:requestFocus():com.intellij.platform.ide.navigation.NavigationOptions
|
||||
- a:requestFocus(Z):com.intellij.platform.ide.navigation.NavigationOptions
|
||||
*f:com.intellij.platform.ide.navigation.NavigationOptions$Companion
|
||||
- f:defaultOptions():com.intellij.platform.ide.navigation.NavigationOptions
|
||||
- f:requestFocus():com.intellij.platform.ide.navigation.NavigationOptions
|
||||
*:com.intellij.platform.ide.navigation.NavigationService
|
||||
- *sf:Companion:com.intellij.platform.ide.navigation.NavigationService$Companion
|
||||
- s:getInstance(com.intellij.openapi.project.Project):com.intellij.platform.ide.navigation.NavigationService
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.ide.navigation
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.platform.backend.navigation.NavigationRequest
|
||||
import org.jetbrains.annotations.ApiStatus.Experimental
|
||||
|
||||
/**
|
||||
* Handles navigation requests in the IDE.
|
||||
*
|
||||
* Implementations of this interface can be registered via the "com.intellij.navigation.navigationHandler" extension point
|
||||
* to provide custom navigation behavior for specific types of [com.intellij.platform.backend.navigation.NavigationRequest]s.
|
||||
*
|
||||
* The navigation system iterates through all registered handlers and calls their [navigate] method until one of them
|
||||
* returns true, indicating that the navigation request has been handled.
|
||||
*/
|
||||
@Experimental
|
||||
interface NavigationHandler {
|
||||
|
||||
/**
|
||||
* Attempts to handle the given navigation request.
|
||||
*
|
||||
* @param request The navigation request to handle. This can be a source navigation request (to navigate to a specific
|
||||
* location in a file), a directory navigation request, or a custom implementation.
|
||||
* @param options Options that control the navigation behavior, such as whether to request focus, preserve caret position, etc.
|
||||
* @param dataContext The data context from which the navigation was initiated, which may contain additional information
|
||||
* needed for navigation.
|
||||
* @return true if the navigation request was handled by this handler, false otherwise.
|
||||
*/
|
||||
fun navigate(request: NavigationRequest, options: NavigationOptions, dataContext: DataContext): Boolean
|
||||
}
|
||||
@@ -51,6 +51,11 @@ interface NavigationOptions {
|
||||
@JvmStatic
|
||||
fun defaultOptions(): NavigationOptions = defaultOptions
|
||||
|
||||
@JvmStatic
|
||||
fun requestFocus(): NavigationOptions {
|
||||
return defaultOptions().requestFocus(true)
|
||||
}
|
||||
|
||||
private val defaultOptions = Impl(
|
||||
requestFocus = true,
|
||||
preserveCaret = false,
|
||||
|
||||
+54
-5
@@ -1,13 +1,18 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.ide.navigation
|
||||
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.wm.IdeFocusManager
|
||||
import com.intellij.platform.backend.navigation.NavigationRequest
|
||||
import com.intellij.platform.ide.progress.runWithModalProgressBlocking
|
||||
import com.intellij.pom.Navigatable
|
||||
import org.jetbrains.annotations.ApiStatus.Experimental
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import org.jetbrains.annotations.ApiStatus.*
|
||||
|
||||
@Experimental
|
||||
interface NavigationService {
|
||||
@@ -21,11 +26,55 @@ interface NavigationService {
|
||||
suspend fun navigate(dataContext: DataContext, options: NavigationOptions)
|
||||
|
||||
@Internal
|
||||
suspend fun navigate(request: NavigationRequest, options: NavigationOptions = NavigationOptions.defaultOptions())
|
||||
suspend fun navigate(
|
||||
request: NavigationRequest,
|
||||
options: NavigationOptions = NavigationOptions.defaultOptions(),
|
||||
dataContext: DataContext? = null,
|
||||
)
|
||||
|
||||
@Internal // compatibility function
|
||||
suspend fun navigate(navigatables: List<Navigatable>, options: NavigationOptions): Boolean
|
||||
suspend fun navigate(
|
||||
navigatables: List<Navigatable>,
|
||||
options: NavigationOptions = NavigationOptions.defaultOptions(),
|
||||
dataContext: DataContext? = null,
|
||||
): Boolean
|
||||
|
||||
@Internal // compatibility function
|
||||
suspend fun navigate(navigatable: Navigatable, options: NavigationOptions = NavigationOptions.defaultOptions()): Boolean
|
||||
suspend fun navigate(navigatable: Navigatable, options: NavigationOptions, dataContext: DataContext? = null): Boolean {
|
||||
return navigate(listOf(navigatable), options, dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the specified [navigatable] in a blocking manner, showing a modal progress dialog.
|
||||
* This is a blocking version of [NavigationService.navigate].
|
||||
*/
|
||||
@RequiresEdt
|
||||
@Obsolete
|
||||
@Internal
|
||||
fun navigateBlocking(project: Project, navigatable: Navigatable, options: NavigationOptions, dataContext: DataContext?) {
|
||||
val dataContext = dataContext ?: fetchDataContext(project)
|
||||
return runWithModalProgressBlocking(project, IdeBundle.message("progress.title.preparing.navigation")) {
|
||||
project.serviceAsync<NavigationService>().navigate(navigatable, options, dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the specified navigation [request] in a blocking manner, showing a modal progress dialog.
|
||||
* This is a blocking version of [NavigationService.navigate].
|
||||
*/
|
||||
@RequiresEdt
|
||||
@Obsolete
|
||||
@Internal
|
||||
fun navigateBlocking(project: Project, request: NavigationRequest, options: NavigationOptions, dataContext: DataContext?) {
|
||||
val dataContext = dataContext ?: fetchDataContext(project)
|
||||
return runWithModalProgressBlocking(project, IdeBundle.message("progress.title.preparing.navigation")) {
|
||||
project.serviceAsync<NavigationService>().navigate(request, options, dataContext)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
private fun fetchDataContext(project: Project): DataContext? {
|
||||
val component = IdeFocusManager.getInstance(project).getFocusOwner()
|
||||
return component?.let { DataManager.getInstance().getDataContext(it) }
|
||||
}
|
||||
|
||||
@@ -490,6 +490,8 @@
|
||||
|
||||
<extensionPoint name="codeInsight.surroundWithRangeAdjuster" interface="com.intellij.codeInsight.generation.surroundWith.SurroundWithRangeAdjuster" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="navigation.navigationHandler" interface="com.intellij.platform.ide.navigation.NavigationHandler" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="createFromTemplateActionReplacer" interface="com.intellij.ide.fileTemplates.CreateFromTemplateActionReplacer" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="filetype.stubBuilder" beanClass="com.intellij.openapi.fileTypes.FileTypeExtensionPoint" dynamic="true">
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.usages.UsageInfo2UsageAdapter;
|
||||
import com.intellij.usages.UsageView;
|
||||
import com.intellij.usages.impl.UsageViewStatisticsCollector;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
@@ -139,6 +140,7 @@ public final class UsageViewUtil {
|
||||
return ContainerUtil.map2Array(usageInfos, PsiElement.class, UsageInfo::getElement);
|
||||
}
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
public static void navigateTo(@NotNull UsageInfo info, boolean requestFocus) {
|
||||
int offset = info.getNavigationOffset();
|
||||
VirtualFile file = info.getVirtualFile();
|
||||
|
||||
Reference in New Issue
Block a user