diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index b12ab5e29c81..392325af383f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import com.intellij.util.*; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; @@ -56,22 +57,7 @@ public class MarkerType { if (!(parent instanceof PsiMethod)) return null; PsiMethod method = (PsiMethod)parent; - PsiMethod[] superMethods = method.findSuperMethods(false); - if (superMethods.length == 0) return null; - - PsiMethod superMethod = superMethods[0]; - boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); - boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT); - - final boolean sameSignature = superMethod.getSignature(PsiSubstitutor.EMPTY).equals(method.getSignature(PsiSubstitutor.EMPTY)); - @NonNls final String key; - if (isSuperAbstract && !isAbstract){ - key = sameSignature ? "method.implements" : "method.implements.in"; - } - else{ - key = sameSignature ? "method.overrides" : "method.overrides.in"; - } - return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key)); + return calculateOverridingMethodTooltip(method); } }, new LineMarkerNavigator(){ @Override @@ -79,15 +65,40 @@ public class MarkerType { PsiElement parent = element.getParent(); if (!(parent instanceof PsiMethod)) return; PsiMethod method = (PsiMethod)parent; - PsiMethod[] superMethods = method.findSuperMethods(false); - if (superMethods.length == 0) return; - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); - PsiElementListNavigator.openTargets(e, superMethods, - DaemonBundle.message("navigation.title.super.method", method.getName()), - new MethodCellRenderer(showMethodNames)); + navigateToOverridingMethod(e, method); } }); + + @Nullable + public static String calculateOverridingMethodTooltip(PsiMethod method) { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) return null; + + PsiMethod superMethod = superMethods[0]; + boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); + boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT); + + final boolean sameSignature = superMethod.getSignature(PsiSubstitutor.EMPTY).equals(method.getSignature(PsiSubstitutor.EMPTY)); + @NonNls final String key; + if (isSuperAbstract && !isAbstract){ + key = sameSignature ? "method.implements" : "method.implements.in"; + } + else{ + key = sameSignature ? "method.overrides" : "method.overrides.in"; + } + return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key)); + } + + public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method) { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) return; + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); + PsiElementListNavigator.openTargets(e, superMethods, + DaemonBundle.message("navigation.title.super.method", method.getName()), + new MethodCellRenderer(showMethodNames)); + } + public static final String SEARCHING_FOR_OVERRIDING_METHODS = "Searching for overriding methods"; public static final MarkerType OVERRIDEN_METHOD = new MarkerType(new NullableFunction() { @Override @@ -96,57 +107,66 @@ public class MarkerType { if (!(parent instanceof PsiMethod)) return null; PsiMethod method = (PsiMethod)parent; - PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); - OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); - - boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); - - if (processor.isOverflow()){ - return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); - } - - PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]); - if (overridings.length == 0) return null; - - Comparator comparator = new MethodCellRenderer(false).getComparator(); - Arrays.sort(overridings, comparator); - - String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header"); - @NonNls String pattern = "    {1}"; - return GutterIconTooltipHelper.composeText(overridings, start, pattern); + return getOverriddenMethodTooltip(method); } }, new LineMarkerNavigator(){ @Override public void browse(MouseEvent e, PsiElement element) { PsiElement parent = element.getParent(); if (!(parent instanceof PsiMethod)) return; - if (DumbService.isDumb(element.getProject())) { - DumbService.getInstance(element.getProject()).showDumbModeNotification("Navigation to overriding classes is not possible during index update"); - return; - } - - final PsiMethod method = (PsiMethod)parent; - final PsiElementProcessor.CollectElementsWithLimit collectProcessor = - new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); - } - }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { - return; - } - - PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); - if (overridings.length == 0) return; - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings); - MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames); - Arrays.sort(overridings, renderer.getComparator()); - final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); - PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater); + navigateToOverriddenMethod(e, (PsiMethod)parent); } }); + + public static String getOverriddenMethodTooltip(PsiMethod method) { + PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); + OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); + + boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); + + if (processor.isOverflow()){ + return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); + } + + PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]); + if (overridings.length == 0) return null; + + Comparator comparator = new MethodCellRenderer(false).getComparator(); + Arrays.sort(overridings, comparator); + + String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header"); + @NonNls String pattern = "    {1}"; + return GutterIconTooltipHelper.composeText(overridings, start, pattern); + } + + public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) { + if (DumbService.isDumb(method.getProject())) { + DumbService.getInstance(method.getProject()).showDumbModeNotification( + "Navigation to overriding classes is not possible during index update"); + return; + } + + final PsiElementProcessor.CollectElementsWithLimit collectProcessor = + new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + } + }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { + return; + } + + PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); + if (overridings.length == 0) return; + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings); + MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames); + Arrays.sort(overridings, renderer.getComparator()); + final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); + PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater); + } + public static final String SEARCHING_FOR_OVERRIDDEN_METHODS = "Searching for overridden methods"; public static final MarkerType SUBCLASSED_CLASS = new MarkerType(new NullableFunction() { @Override @@ -154,58 +174,66 @@ public class MarkerType { PsiElement parent = element.getParent(); if (!(parent instanceof PsiClass)) return null; PsiClass aClass = (PsiClass)parent; - PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); - ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); - - if (processor.isOverflow()) { - return aClass.isInterface() - ? DaemonBundle.message("interface.is.implemented.too.many") - : DaemonBundle.message("class.is.subclassed.too.many"); - } - - PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]); - if (subclasses.length == 0) return null; - - Comparator comparator = new PsiClassListCellRenderer().getComparator(); - Arrays.sort(subclasses, comparator); - - String start = aClass.isInterface() - ? DaemonBundle.message("interface.is.implemented.by.header") - : DaemonBundle.message("class.is.subclassed.by.header"); - @NonNls String pattern = "    {0}"; - return GutterIconTooltipHelper.composeText(subclasses, start, pattern); + return getSubclassedClassTooltip(aClass); } }, new LineMarkerNavigator(){ @Override public void browse(MouseEvent e, PsiElement element) { final PsiElement parent = element.getParent(); if (!(parent instanceof PsiClass)) return; - - if (DumbService.isDumb(element.getProject())) { - DumbService.getInstance(element.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); - return; - } - final PsiClass aClass = (PsiClass)parent; - final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); - } - }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { - return; - } - PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY); - if (inheritors.length == 0) return; - final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer(); - final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); - Arrays.sort(inheritors, renderer.getComparator()); - PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), renderer, subclassUpdater); + navigateToSubclassedClass(e, aClass); } }); + public static String getSubclassedClassTooltip(PsiClass aClass) { + PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); + ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); + + if (processor.isOverflow()) { + return aClass.isInterface() + ? DaemonBundle.message("interface.is.implemented.too.many") + : DaemonBundle.message("class.is.subclassed.too.many"); + } + + PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]); + if (subclasses.length == 0) return null; + + Comparator comparator = new PsiClassListCellRenderer().getComparator(); + Arrays.sort(subclasses, comparator); + + String start = aClass.isInterface() + ? DaemonBundle.message("interface.is.implemented.by.header") + : DaemonBundle.message("class.is.subclassed.by.header"); + @NonNls String pattern = "    {0}"; + return GutterIconTooltipHelper.composeText(subclasses, start, pattern); + } + + public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) { + if (DumbService.isDumb(aClass.getProject())) { + DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); + return; + } + + final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + } + }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { + return; + } + + PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY); + if (inheritors.length == 0) return; + final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer(); + final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); + Arrays.sort(inheritors, renderer.getComparator()); + PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), renderer, subclassUpdater); + } + private final GutterIconNavigationHandler handler; private final Function myTooltip;