172: Revert "Line Markers: Respect subclass module when filtering out duplicates"
This reverts commit 8df0a58586abf42572aff15d4bdd70e51e5cad29.
This commit is contained in:
+421
@@ -0,0 +1,421 @@
|
|||||||
|
/*
|
||||||
|
* 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/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.highlighter.markers
|
||||||
|
|
||||||
|
import com.intellij.codeHighlighting.Pass
|
||||||
|
import com.intellij.codeInsight.daemon.*
|
||||||
|
import com.intellij.codeInsight.daemon.impl.LineMarkerNavigator
|
||||||
|
import com.intellij.codeInsight.daemon.impl.MarkerType
|
||||||
|
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
|
||||||
|
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask
|
||||||
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.openapi.actionSystem.IdeActions
|
||||||
|
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||||
|
import com.intellij.openapi.editor.colors.EditorColorsManager
|
||||||
|
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
||||||
|
import com.intellij.openapi.editor.markup.SeparatorPlacement
|
||||||
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
|
import com.intellij.openapi.project.DumbService
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.NavigatablePsiElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiNameIdentifierOwner
|
||||||
|
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
|
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightClass
|
||||||
|
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightMethod
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.core.isInheritable
|
||||||
|
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||||
|
import org.jetbrains.kotlin.idea.core.toDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMethods
|
||||||
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import java.util.*
|
||||||
|
import javax.swing.Icon
|
||||||
|
import javax.swing.ListCellRenderer
|
||||||
|
|
||||||
|
class KotlinLineMarkerProvider : LineMarkerProvider {
|
||||||
|
override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<PsiElement>? {
|
||||||
|
if (DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS) {
|
||||||
|
if (element.canHaveSeparator()) {
|
||||||
|
val prevSibling = element.getPrevSiblingIgnoringWhitespaceAndComments()
|
||||||
|
if (prevSibling.canHaveSeparator() &&
|
||||||
|
(element.wantsSeparator() || prevSibling?.wantsSeparator() == true)) {
|
||||||
|
return createLineSeparatorByElement(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement?.canHaveSeparator() =
|
||||||
|
this is KtFunction || this is KtClassInitializer || (this is KtProperty && !isLocal)
|
||||||
|
|
||||||
|
private fun PsiElement.wantsSeparator() = StringUtil.getLineBreakCount(text) > 0
|
||||||
|
|
||||||
|
private fun createLineSeparatorByElement(element: PsiElement): LineMarkerInfo<PsiElement> {
|
||||||
|
val anchor = PsiTreeUtil.getDeepestFirst(element)
|
||||||
|
|
||||||
|
val info = LineMarkerInfo(anchor, anchor.textRange, null, Pass.LINE_MARKERS, null, null, GutterIconRenderer.Alignment.RIGHT)
|
||||||
|
info.separatorColor = EditorColorsManager.getInstance().globalScheme.getColor(CodeInsightColors.METHOD_SEPARATORS_COLOR)
|
||||||
|
info.separatorPlacement = SeparatorPlacement.TOP
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun collectSlowLineMarkers(elements: List<PsiElement>, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
if (elements.isEmpty()) return
|
||||||
|
|
||||||
|
val first = elements.first()
|
||||||
|
if (DumbService.getInstance(first.project).isDumb || !ProjectRootsUtil.isInProjectOrLibSource(first)) return
|
||||||
|
|
||||||
|
val functions = HashSet<KtNamedFunction>()
|
||||||
|
val properties = HashSet<KtNamedDeclaration>()
|
||||||
|
|
||||||
|
for (element in elements) {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
|
||||||
|
when (element) {
|
||||||
|
is KtClass -> {
|
||||||
|
collectInheritedClassMarker(element, result)
|
||||||
|
collectHighlightingColorsMarkers(element, result)
|
||||||
|
}
|
||||||
|
is KtNamedFunction -> {
|
||||||
|
functions.add(element)
|
||||||
|
collectSuperDeclarationMarkers(element, result)
|
||||||
|
}
|
||||||
|
is KtProperty -> {
|
||||||
|
properties.add(element)
|
||||||
|
collectSuperDeclarationMarkers(element, result)
|
||||||
|
}
|
||||||
|
is KtParameter -> {
|
||||||
|
if (element.hasValOrVar()) {
|
||||||
|
properties.add(element)
|
||||||
|
collectSuperDeclarationMarkers(element, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collectOverriddenFunctions(functions, result)
|
||||||
|
collectOverriddenPropertyAccessors(properties, result)
|
||||||
|
|
||||||
|
for (element in elements) {
|
||||||
|
if (element !is KtNamedDeclaration) continue
|
||||||
|
|
||||||
|
if (element.isExpectDeclaration()) {
|
||||||
|
collectActualMarkers(element, result)
|
||||||
|
}
|
||||||
|
else if (element.isEffectivelyActual()) {
|
||||||
|
collectExpectedMarkers(element, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val OVERRIDING_MARK: Icon = AllIcons.Gutter.OverridingMethod
|
||||||
|
private val IMPLEMENTING_MARK: Icon = AllIcons.Gutter.ImplementingMethod
|
||||||
|
private val OVERRIDDEN_MARK: Icon = AllIcons.Gutter.OverridenMethod
|
||||||
|
private val IMPLEMENTED_MARK: Icon = AllIcons.Gutter.ImplementedMethod
|
||||||
|
|
||||||
|
data class NavigationPopupDescriptor(
|
||||||
|
val targets: Collection<NavigatablePsiElement>,
|
||||||
|
val title: String,
|
||||||
|
val findUsagesTitle: String,
|
||||||
|
val renderer: ListCellRenderer<*>,
|
||||||
|
val updater: ListBackgroundUpdaterTask? = null
|
||||||
|
) {
|
||||||
|
fun showPopup(e: MouseEvent?) {
|
||||||
|
PsiElementListNavigator.openTargets(e, targets.toTypedArray(), title, findUsagesTitle, renderer, updater)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestableLineMarkerNavigator {
|
||||||
|
fun getTargetsPopupDescriptor(element: PsiElement?): NavigationPopupDescriptor?
|
||||||
|
}
|
||||||
|
|
||||||
|
private val SUBCLASSED_CLASS = MarkerType(
|
||||||
|
"SUBCLASSED_CLASS",
|
||||||
|
{ getPsiClass(it)?.let { MarkerType.getSubclassedClassTooltip(it) } },
|
||||||
|
object : LineMarkerNavigator() {
|
||||||
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
|
getPsiClass(element)?.let { MarkerType.navigateToSubclassedClass(e, it) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
private val OVERRIDDEN_FUNCTION = object : MarkerType(
|
||||||
|
"OVERRIDDEN_FUNCTION",
|
||||||
|
{ getPsiMethod(it)?.let(::getOverriddenMethodTooltip) },
|
||||||
|
object : LineMarkerNavigator() {
|
||||||
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
|
buildNavigateToOverriddenMethodPopup(e, element)?.showPopup(e)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
|
||||||
|
override fun getNavigationHandler(): GutterIconNavigationHandler<PsiElement> {
|
||||||
|
val superHandler = super.getNavigationHandler()
|
||||||
|
return object : GutterIconNavigationHandler<PsiElement>, TestableLineMarkerNavigator {
|
||||||
|
override fun navigate(e: MouseEvent?, elt: PsiElement?) {
|
||||||
|
superHandler.navigate(e, elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTargetsPopupDescriptor(element: PsiElement?) = buildNavigateToOverriddenMethodPopup(null, element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val OVERRIDDEN_PROPERTY = object : MarkerType(
|
||||||
|
"OVERRIDDEN_PROPERTY",
|
||||||
|
{ it?.let { getOverriddenPropertyTooltip(it.parent as KtNamedDeclaration) } },
|
||||||
|
object : LineMarkerNavigator() {
|
||||||
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
|
buildNavigateToPropertyOverriddenDeclarationsPopup(e, element)?.showPopup(e)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
|
||||||
|
override fun getNavigationHandler(): GutterIconNavigationHandler<PsiElement> {
|
||||||
|
val superHandler = super.getNavigationHandler()
|
||||||
|
return object : GutterIconNavigationHandler<PsiElement>, TestableLineMarkerNavigator {
|
||||||
|
override fun navigate(e: MouseEvent?, elt: PsiElement?) {
|
||||||
|
superHandler.navigate(e, elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTargetsPopupDescriptor(element: PsiElement?) = buildNavigateToPropertyOverriddenDeclarationsPopup(null, element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PsiElement.markerDeclaration
|
||||||
|
get() = (this as? KtDeclaration) ?: (parent as? KtDeclaration)
|
||||||
|
|
||||||
|
private val PLATFORM_ACTUAL = MarkerType(
|
||||||
|
"PLATFORM_ACTUAL",
|
||||||
|
{ it?.let { getPlatformActualTooltip(it.markerDeclaration) } },
|
||||||
|
object : LineMarkerNavigator() {
|
||||||
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
|
element?.let { navigateToPlatformActual(e, it.markerDeclaration) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private val EXPECTED_DECLARATION = MarkerType(
|
||||||
|
"EXPECTED_DECLARATION",
|
||||||
|
{ it?.let { getExpectedDeclarationTooltip(it.markerDeclaration) } },
|
||||||
|
object : LineMarkerNavigator() {
|
||||||
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
|
element?.let { navigateToExpectedDeclaration(it.markerDeclaration) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun isImplementsAndNotOverrides(descriptor: CallableMemberDescriptor, overriddenMembers: Collection<CallableMemberDescriptor>): Boolean {
|
||||||
|
return descriptor.modality != Modality.ABSTRACT && overriddenMembers.all { it.modality == Modality.ABSTRACT }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectSuperDeclarationMarkers(declaration: KtDeclaration, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
assert(declaration is KtNamedFunction || declaration is KtProperty || declaration is KtParameter)
|
||||||
|
|
||||||
|
if (!declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return
|
||||||
|
|
||||||
|
val resolveWithParents = resolveDeclarationWithParents(declaration)
|
||||||
|
if (resolveWithParents.overriddenDescriptors.isEmpty()) return
|
||||||
|
|
||||||
|
val implements = isImplementsAndNotOverrides(resolveWithParents.descriptor!!, resolveWithParents.overriddenDescriptors)
|
||||||
|
|
||||||
|
val anchor = (declaration as? KtNamedDeclaration)?.nameIdentifier ?: declaration
|
||||||
|
|
||||||
|
// NOTE: Don't store descriptors in line markers because line markers are not deleted while editing other files and this can prevent
|
||||||
|
// clearing the whole BindingTrace.
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
if (implements) IMPLEMENTING_MARK else OVERRIDING_MARK,
|
||||||
|
Pass.LINE_MARKERS,
|
||||||
|
SuperDeclarationMarkerTooltip,
|
||||||
|
SuperDeclarationMarkerNavigationHandler(),
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
if (declaration is KtNamedFunction) "Go to super method" else "Go to super property",
|
||||||
|
IdeActions.ACTION_GOTO_SUPER
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectInheritedClassMarker(element: KtClass, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
if (!element.isInheritable()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val lightClass = element.toLightClass() ?: KtFakeLightClass(element)
|
||||||
|
|
||||||
|
if (ClassInheritorsSearch.search(lightClass, false).findFirst() == null) return
|
||||||
|
|
||||||
|
val anchor = element.nameIdentifier ?: element
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
if (element.isInterface()) IMPLEMENTED_MARK else OVERRIDDEN_MARK,
|
||||||
|
Pass.LINE_MARKERS,
|
||||||
|
SUBCLASSED_CLASS.tooltip,
|
||||||
|
SUBCLASSED_CLASS.navigationHandler,
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
if (element.isInterface()) "Go to implementations" else "Go to subclasses",
|
||||||
|
IdeActions.ACTION_GOTO_IMPLEMENTATION
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectOverriddenPropertyAccessors(properties: Collection<KtNamedDeclaration>,
|
||||||
|
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
val mappingToJava = HashMap<PsiElement, KtNamedDeclaration>()
|
||||||
|
for (property in properties) {
|
||||||
|
if (property.isOverridable()) {
|
||||||
|
property.toPossiblyFakeLightMethods().forEach { mappingToJava.put(it, property) }
|
||||||
|
mappingToJava[property] = property
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val classes = collectContainingClasses(mappingToJava.keys.filterIsInstance<PsiMethod>())
|
||||||
|
|
||||||
|
for (property in getOverriddenDeclarations(mappingToJava, classes)) {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
|
||||||
|
val anchor = (property as? PsiNameIdentifierOwner)?.nameIdentifier ?: property
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
if (isImplemented(property)) IMPLEMENTED_MARK else OVERRIDDEN_MARK,
|
||||||
|
Pass.LINE_MARKERS,
|
||||||
|
OVERRIDDEN_PROPERTY.tooltip,
|
||||||
|
OVERRIDDEN_PROPERTY.navigationHandler,
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
"Go to overridden properties",
|
||||||
|
IdeActions.ACTION_GOTO_IMPLEMENTATION
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KtNamedDeclaration.expectOrActualAnchor
|
||||||
|
get() =
|
||||||
|
nameIdentifier
|
||||||
|
?: (this as? KtConstructor<*>)?.let {
|
||||||
|
it.getConstructorKeyword() ?: it.getValueParameterList()?.leftParenthesis
|
||||||
|
}
|
||||||
|
?: this
|
||||||
|
|
||||||
|
private fun collectActualMarkers(declaration: KtNamedDeclaration,
|
||||||
|
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
|
||||||
|
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return
|
||||||
|
val commonModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||||
|
|
||||||
|
if (commonModuleDescriptor.implementingDescriptors.none { it.hasActualsFor(descriptor) }) return
|
||||||
|
|
||||||
|
val anchor = declaration.expectOrActualAnchor
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
KotlinIcons.ACTUAL,
|
||||||
|
Pass.LINE_MARKERS,
|
||||||
|
PLATFORM_ACTUAL.tooltip,
|
||||||
|
PLATFORM_ACTUAL.navigationHandler,
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
"Go to actual declarations",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectExpectedMarkers(declaration: KtNamedDeclaration,
|
||||||
|
result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
|
||||||
|
val descriptor = declaration.toDescriptor() as? MemberDescriptor ?: return
|
||||||
|
val platformModuleDescriptor = declaration.containingKtFile.findModuleDescriptor()
|
||||||
|
if (!platformModuleDescriptor.implementedDescriptors.any { it.hasDeclarationOf(descriptor) }) return
|
||||||
|
|
||||||
|
val anchor = declaration.expectOrActualAnchor
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
KotlinIcons.EXPECT,
|
||||||
|
Pass.LINE_MARKERS,
|
||||||
|
EXPECTED_DECLARATION.tooltip,
|
||||||
|
EXPECTED_DECLARATION.navigationHandler,
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
"Go to expected declaration",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectOverriddenFunctions(functions: Collection<KtNamedFunction>, result: MutableCollection<LineMarkerInfo<*>>) {
|
||||||
|
val mappingToJava = HashMap<PsiElement, KtNamedFunction>()
|
||||||
|
for (function in functions) {
|
||||||
|
if (function.isOverridable()) {
|
||||||
|
val method = LightClassUtil.getLightClassMethod(function) ?: KtFakeLightMethod.get(function)
|
||||||
|
if (method != null) {
|
||||||
|
mappingToJava.put(method, function)
|
||||||
|
}
|
||||||
|
mappingToJava.put(function, function)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val classes = collectContainingClasses(mappingToJava.keys.filterIsInstance<PsiMethod>())
|
||||||
|
|
||||||
|
for (function in getOverriddenDeclarations(mappingToJava, classes)) {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
|
||||||
|
val anchor = function.nameIdentifier ?: function
|
||||||
|
|
||||||
|
val lineMarkerInfo = LineMarkerInfo(
|
||||||
|
anchor,
|
||||||
|
anchor.textRange,
|
||||||
|
if (isImplemented(function)) IMPLEMENTED_MARK else OVERRIDDEN_MARK,
|
||||||
|
Pass.LINE_MARKERS, OVERRIDDEN_FUNCTION.tooltip,
|
||||||
|
OVERRIDDEN_FUNCTION.navigationHandler,
|
||||||
|
GutterIconRenderer.Alignment.RIGHT
|
||||||
|
)
|
||||||
|
NavigateAction.setNavigateAction(
|
||||||
|
lineMarkerInfo,
|
||||||
|
"Go to overridden methods",
|
||||||
|
IdeActions.ACTION_GOTO_IMPLEMENTATION
|
||||||
|
)
|
||||||
|
result.add(lineMarkerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user