diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index 8c7ae863eb89..bb9aab62c8b4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -53,9 +53,13 @@ import java.util.Map; import java.util.Set; public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { - private final DaemonCodeAnalyzerSettings myDaemonSettings; - private final EditorColorsManager myColorsManager; + protected final DaemonCodeAnalyzerSettings myDaemonSettings; + protected final EditorColorsManager myColorsManager; private final Option myLambdaOption = new Option("java.lambda", "Lambda", AllIcons.Gutter.ImplementingFunctionalInterface); + private final Option myOverriddenOption = new Option("java.overridden", "Overridden method", AllIcons.Gutter.OverridenMethod); + private final Option myImplementedOption = new Option("java.implemented", "Implemented method", AllIcons.Gutter.ImplementedMethod); + private final Option myOverridingOption = new Option("java.overriding", "Overriding method", AllIcons.Gutter.OverridingMethod); + private final Option myImplementingOption = new Option("java.implementing", "Implementing method", AllIcons.Gutter.ImplementingMethod); public JavaLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) { myDaemonSettings = daemonSettings; @@ -67,20 +71,29 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) { PsiElement parent; if (element instanceof PsiIdentifier && (parent = element.getParent()) instanceof PsiMethod) { + if (!myOverridingOption.isEnabled() && !myImplementingOption.isEnabled()) return null; PsiMethod method = (PsiMethod)parent; MethodSignatureBackedByPsiMethod superSignature = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (superSignature != null) { boolean overrides = method.hasModifierProperty(PsiModifier.ABSTRACT) == superSignature.getMethod().hasModifierProperty(PsiModifier.ABSTRACT); - final Icon icon = overrides ? AllIcons.Gutter.OverridingMethod : AllIcons.Gutter.ImplementingMethod; + final Icon icon; + if (overrides) { + if (!myOverridingOption.isEnabled()) return null; + icon = AllIcons.Gutter.OverridingMethod; + } + else { + if (!myImplementingOption.isEnabled()) return null; + icon = AllIcons.Gutter.ImplementingMethod; + } return createSuperMethodLineMarkerInfo(element, icon, Pass.UPDATE_ALL); } } final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element); final PsiElement firstChild = element.getFirstChild(); - if (interfaceMethod != null && firstChild != null && LineMarkerSettings.getSettings().isEnabled(myLambdaOption)) { + if (interfaceMethod != null && firstChild != null && myLambdaOption.isEnabled()) { return createSuperMethodLineMarkerInfo(firstChild, AllIcons.Gutter.ImplementingFunctionalInterface, Pass.UPDATE_ALL); } @@ -216,7 +229,7 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { return range; } - public static void collectInheritingClasses(@NotNull PsiClass aClass, + protected void collectInheritingClasses(@NotNull PsiClass aClass, @NotNull Collection result, @NotNull Map subClassCache) { if (aClass.hasModifierProperty(PsiModifier.FINAL)) { @@ -226,7 +239,15 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { PsiClass subClass = subClassCache.get(aClass); if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) { - final Icon icon = aClass.isInterface() ? AllIcons.Gutter.ImplementedMethod : AllIcons.Gutter.OverridenMethod; + final Icon icon; + if (aClass.isInterface()) { + if (!myImplementedOption.isEnabled()) return; + icon = AllIcons.Gutter.ImplementedMethod; + } + else { + if (!myOverriddenOption.isEnabled()) return; + icon = AllIcons.Gutter.OverridenMethod; + } PsiElement range = aClass.getNameIdentifier(); if (range == null) { range = aClass; @@ -241,7 +262,8 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { } } - private static void collectOverridingMethods(@NotNull final Collection methods, @NotNull Collection result) { + private void collectOverridingMethods(@NotNull final Collection methods, @NotNull Collection result) { + if (!myOverriddenOption.isEnabled() && !myImplementedOption.isEnabled()) return; final Set overridden = new HashSet(); Set classes = new THashSet(); for (PsiMethod method : methods) { @@ -281,7 +303,12 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { for (PsiMethod method : overridden) { ProgressManager.checkCanceled(); boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT); - + if (overrides) { + if (!myOverriddenOption.isEnabled()) return; + } + else { + if (!myImplementedOption.isEnabled()) return; + } PsiElement range = getMethodRange(method); final MarkerType type = MarkerType.OVERRIDDEN_METHOD; final Icon icon = overrides ? AllIcons.Gutter.OverridenMethod : AllIcons.Gutter.ImplementedMethod; @@ -301,7 +328,7 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor { @Override public Option[] getOptions() { - return new Option[] {myLambdaOption}; + return new Option[] {myLambdaOption, myOverriddenOption, myImplementedOption, myOverridingOption, myImplementingOption}; } private static class ArrowUpLineMarkerInfo extends MergeableLineMarkerInfo { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/RunLineMarkerTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/navigation/RunLineMarkerTest.java index 11c8c6486cc7..885de50fdc49 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/RunLineMarkerTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/navigation/RunLineMarkerTest.java @@ -15,15 +15,19 @@ */ package com.intellij.codeInsight.navigation; +import com.intellij.application.options.editor.GutterIconsConfigurable; +import com.intellij.codeInsight.daemon.GutterIconDescriptor; import com.intellij.codeInsight.daemon.GutterMark; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.testFramework.TestActionEvent; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import java.util.List; +import java.util.Set; /** * @author Dmitry Avdeev @@ -68,4 +72,17 @@ public class RunLineMarkerTest extends LightCodeInsightFixtureTestCase { list.get(1).update(event); assertEquals("Run 'MainTest'", event.getPresentation().getText()); } + + public void testConfigurable() throws Exception { + GutterIconsConfigurable configurable = new GutterIconsConfigurable(); + configurable.createComponent(); + List descriptors = configurable.getDescriptors(); + Set strings = ContainerUtil.map2Set(descriptors, new Function() { + @Override + public String fun(GutterIconDescriptor descriptor) { + return descriptor.getId(); + } + }); + assertEquals(descriptors.size(), strings.size()); + } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/GutterIconDescriptor.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/GutterIconDescriptor.java index 8e5ad8cb46d0..db8e10de0890 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/GutterIconDescriptor.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/GutterIconDescriptor.java @@ -73,6 +73,10 @@ public abstract class GutterIconDescriptor { myIcon = icon; } + public boolean isEnabled() { + return LineMarkerSettings.getSettings().isEnabled(this); + } + @Nullable @Override public Icon getIcon() { diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java index 5c2cd0f75dea..8a79f9e86a42 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/GutterIconsConfigurable.java @@ -32,10 +32,12 @@ import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.hash.HashSet; import com.intellij.util.ui.EmptyIcon; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.awt.*; @@ -80,6 +82,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr }; MultiMap> map = ContainerUtil.groupBy(Arrays.asList(extensions), function); Map pluginDescriptorMap = ContainerUtil.newHashMap(); + Set ids = new HashSet<>(); myDescriptors = new ArrayList(); for (final PluginDescriptor descriptor : map.keySet()) { Collection> points = map.get(descriptor); @@ -87,16 +90,21 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr GutterIconDescriptor instance = (GutterIconDescriptor)extensionPoint.getInstance(); if (instance.getOptions().length > 0) { for (GutterIconDescriptor option : instance.getOptions()) { - myDescriptors.add(option); + if (ids.add(option.getId())) { + myDescriptors.add(option); + } pluginDescriptorMap.put(option, descriptor); } } else { - myDescriptors.add(instance); + if (ids.add(instance.getId())) { + myDescriptors.add(instance); + } pluginDescriptorMap.put(instance, descriptor); } } } + /* List options = new ArrayList(); for (Iterator iterator = myDescriptors.iterator(); iterator.hasNext(); ) { GutterIconDescriptor descriptor = iterator.next(); @@ -106,6 +114,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr } } myDescriptors.addAll(options); + */ myDescriptors.sort(new Comparator() { @Override public int compare(GutterIconDescriptor o1, GutterIconDescriptor o2) { @@ -203,4 +212,7 @@ public class GutterIconsConfigurable implements Configurable, Configurable.NoScr }; myList.setBorder(BorderFactory.createEmptyBorder()); } + + @TestOnly + public List getDescriptors() { return myDescriptors; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java index f5e1a04c79df..67be1dca51be 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyLineMarkerProvider.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.codeInsight; import com.intellij.codeHighlighting.Pass; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; import com.intellij.codeInsight.daemon.LineMarkerInfo; -import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.codeInsight.daemon.impl.JavaLineMarkerProvider; import com.intellij.codeInsight.daemon.impl.MarkerType; import com.intellij.icons.AllIcons; @@ -67,13 +66,10 @@ import java.util.*; * @author ilyas * Same logic as for Java LMP */ -public class GroovyLineMarkerProvider implements LineMarkerProvider { - private final DaemonCodeAnalyzerSettings myDaemonSettings; - private final EditorColorsManager myColorsManager; +public class GroovyLineMarkerProvider extends JavaLineMarkerProvider { public GroovyLineMarkerProvider(DaemonCodeAnalyzerSettings daemonSettings, EditorColorsManager colorsManager) { - myDaemonSettings = daemonSettings; - myColorsManager = colorsManager; + super(daemonSettings, colorsManager); } @Override @@ -207,7 +203,7 @@ public class GroovyLineMarkerProvider implements LineMarkerProvider { } } else if (element instanceof PsiClass && !(element instanceof PsiTypeParameter)) { - JavaLineMarkerProvider.collectInheritingClasses((PsiClass)element, result, subClassCache); + collectInheritingClasses((PsiClass)element, result, subClassCache); } } collectOverridingMethods(methods, result);