JComponent () { LanguageExtensionPoint<LineMarkerProvider>[] extensions = LineMarkerProviders.EP_NAME.getExtensions(); NullableFunction<LanguageExtensionPoint<LineMarkerProvider>, PluginDescriptor> function = point1 -> { LineMarkerProvider instance = point1.getInstance(); return instance instanceof LineMarkerProviderDescriptor && ((LineMarkerProviderDescriptor)instance).getName() != null ? point1.getPluginDescriptor() : null; }; MultiMap<PluginDescriptor, LanguageExtensionPoint<LineMarkerProvider>> map = ContainerUtil.groupBy(Arrays.asList(extensions), function); Map<GutterIconDescriptor, PluginDescriptor> pluginDescriptorMap = new HashMap<>(); Set<String> ids = new HashSet<>(); for (final PluginDescriptor descriptor : map.keySet()) { Collection<LanguageExtensionPoint<LineMarkerProvider>> points = map.get(descriptor); for (LanguageExtensionPoint<LineMarkerProvider> extensionPoint : points) { GutterIconDescriptor instance = (GutterIconDescriptor)extensionPoint.getInstance(); if (instance.getOptions().length > 0) { for (GutterIconDescriptor option : instance.getOptions()) { if (ids.add(option.getId())) { myDescriptors.add(option); pluginDescriptorMap.put(option, descriptor); } } } else { if (ids.add(instance.getId())) { myDescriptors.add(instance); } pluginDescriptorMap.put(instance, descriptor); } } } /* List<GutterIconDescriptor> options = new ArrayList<GutterIconDescriptor>(); for (Iterator<GutterIconDescriptor> iterator = myDescriptors.iterator(); iterator.hasNext(); ) { GutterIconDescriptor descriptor = iterator.next(); if (descriptor.getOptions().length > 0) { options.addAll(Arrays.asList(descriptor.getOptions())); iterator.remove(); } } myDescriptors.addAll(options); */ myDescriptors.sort((o1, o2) -> { int byPlugin = StringUtil.naturalCompare(getPluginDisplayName(pluginDescriptorMap.get(o1)), getPluginDisplayName(pluginDescriptorMap.get(o2))); return byPlugin != 0 ? byPlugin : StringUtil.naturalCompare(o1.getName(), o2.getName()); }); PluginId current = null; for (GutterIconDescriptor descriptor : myDescriptors) { PluginDescriptor pluginDescriptor = pluginDescriptorMap.get(descriptor); PluginId pluginId = pluginDescriptor != null ? pluginDescriptor.getPluginId() : null; // You get different plugin descriptors for `GutterIconDescriptor`s from the same plugin // if they are located in different plugin modules. // But there is no reason to put them into separate UI groups especially taking into account // we sort `myDescriptors` only by plugin name, so compare plugin descriptors by their id if (pluginId != null && !pluginId.equals(current)) { myFirstDescriptors.put(descriptor, pluginDescriptor); current = pluginId; } } myList.setItems(myDescriptors, GutterIconDescriptor::getName); myShowGutterIconsJBCheckBox.addChangeListener(e -> myList.setEnabled(myShowGutterIconsJBCheckBox.isSelected())); SwingUtilities.updateComponentTreeUI(myPanel); // TODO: create Swing components in this method (see javadoc) return myPanel; }