From 1a98569af920de7a77a176cf7cd5aba80765e3a2 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Mon, 4 Feb 2019 15:11:41 +0300 Subject: [PATCH] extract separate "Go To Declaration" action which knows nothing about "Show Usages" (IDEA-206322) --- .../actions/GotoDeclarationAction.java | 2 +- .../actions/GotoDeclarationOnlyAction.kt | 12 +++ .../actions/GotoDeclarationOnlyHandler.kt | 93 +++++++++++++++++++ .../src/messages/ActionsBundle.properties | 6 +- .../src/idea/LangActions.xml | 2 + 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyAction.kt create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyHandler.kt diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java index e34d7f847bc2..9768030bad63 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java @@ -178,7 +178,7 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code return false; } - private static void gotoTargetElement(@NotNull PsiElement element, @NotNull Editor currentEditor, @NotNull PsiFile currentFile) { + static void gotoTargetElement(@NotNull PsiElement element, @NotNull Editor currentEditor, @NotNull PsiFile currentFile) { if (navigateInCurrentEditor(element, currentFile, currentEditor)) return; Navigatable navigatable = element instanceof Navigatable ? (Navigatable)element : EditSourceUtil.getDescriptor(element); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyAction.kt b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyAction.kt new file mode 100644 index 000000000000..393d3f64e82e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyAction.kt @@ -0,0 +1,12 @@ +// Copyright 2000-2019 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.codeInsight.navigation.actions + +import com.intellij.codeInsight.CodeInsightActionHandler + +/** + * Go To Declaration which doesn't invoke Show Usages if there are no declarations to go + */ +class GotoDeclarationOnlyAction : GotoDeclarationAction() { + + override fun getHandler(): CodeInsightActionHandler = GotoDeclarationOnlyHandler +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyHandler.kt b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyHandler.kt new file mode 100644 index 000000000000..5e9bbc2747b7 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationOnlyHandler.kt @@ -0,0 +1,93 @@ +// Copyright 2000-2019 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.codeInsight.navigation.actions + +import com.intellij.codeInsight.CodeInsightActionHandler +import com.intellij.codeInsight.CodeInsightBundle +import com.intellij.codeInsight.TargetElementUtil +import com.intellij.codeInsight.hint.HintManager +import com.intellij.codeInsight.navigation.NavigationUtil +import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction.* +import com.intellij.featureStatistics.FeatureUsageTracker +import com.intellij.ide.util.DefaultPsiElementCellRenderer +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.DumbService +import com.intellij.openapi.project.IndexNotReadyException +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.search.PsiElementProcessor +import com.intellij.util.toArray + +object GotoDeclarationOnlyHandler : CodeInsightActionHandler { + + override fun startInWriteAction(): Boolean = false + + override fun invoke(project: Project, editor: Editor, file: PsiFile) { + FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration.only") + + val dumbService = DumbService.getInstance(project) + try { + dumbService.isAlternativeResolveEnabled = true + val offset = editor.caretModel.offset + val elements = underModalProgress(project, "Resolving Reference...") { + findAllTargetElements(project, editor, offset) + } + + if (elements.size == 1) { + // simplest case + val element = elements[0] + val navElement = TargetElementUtil.getInstance().getGotoDeclarationTarget(element, element.navigationElement) + if (navElement != null) { + gotoTargetElement(navElement, editor, file) + } + } + else if (elements.isEmpty()) { + // this means either there is really nowhere to go or weird TargetElementUtil didn't return anything + val reference = TargetElementUtil.findReference(editor, offset) + if (reference != null) { + val targets = underModalProgress(project, "Resolving Reference...") { + TargetElementUtil.getInstance().getTargetCandidates(reference) + } + if (targets.isNotEmpty()) { + chooseAmbiguousTarget(editor, file, targets.toArray(PsiElement.EMPTY_ARRAY)) + return + } + } + //disable 'no declaration found' notification for keywords + if (!isKeywordUnderCaret(project, file, offset)) { + HintManager.getInstance().showErrorHint(editor, "Cannot find declaration to go to") + } + } + else { + chooseAmbiguousTarget(editor, file, elements) + } + } + catch (e: IndexNotReadyException) { + dumbService.showDumbModeNotification("Navigation is not available here during index update") + } + finally { + dumbService.isAlternativeResolveEnabled = false + } + } + + private fun chooseAmbiguousTarget(editor: Editor, file: PsiFile, elements: Array) { + if (!editor.component.isShowing) return + chooseAmbiguousTarget(editor, CodeInsightBundle.message("declaration.navigation.title"), elements) { element -> + gotoTargetElement(element, editor, file) + } + } + + private fun chooseAmbiguousTarget(editor: Editor, title: String, elements: Array, processor: (PsiElement) -> Unit) { + require(elements.isNotEmpty()) + if (elements.size == 1) { + val element = elements[0] + processor(element) + return + } + val psiElementProcessor = PsiElementProcessor { + processor(it) + true + } + NavigationUtil.getPsiElementPopup(elements, DefaultPsiElementCellRenderer(), title, psiElementProcessor).showInBestPositionFor(editor) + } +} diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 7f61a7d8eeb4..010f987717f2 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -519,8 +519,10 @@ action.GotoAction.text=_Find Action... action.GotoAction.description=Quickly navigate to action by name action.GotoLine.text=_Line/Column... action.GotoLine.description=Navigate to a line (and/or column) in editor by its number -action.GotoDeclaration.text=_Declaration -action.GotoDeclaration.description=Navigate to the declaration of the symbol at caret +action.GotoDeclaration.text=Declaration or Usages +action.GotoDeclaration.description=Navigate to the declaration of the symbol at caret or show its usages +action.GotoDeclarationOnly.text=_Declaration +action.GotoDeclarationOnly.description=Navigate to the declaration of the symbol at caret action.GotoImplementation.text=I_mplementation(s) action.GotoImplementation.description=Navigate to the implementation(s) of the selected class or method action.GotoNextElementUnderCaretUsage.text=Go to next highlighted element usage diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index db293581cac2..99be30f44d98 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -139,6 +139,7 @@ + @@ -625,6 +626,7 @@ +