diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundProjectViewNodeDecorator.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundProjectViewNodeDecorator.java index 76cb9ca680ab..3229bd049299 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundProjectViewNodeDecorator.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundProjectViewNodeDecorator.java @@ -4,51 +4,68 @@ package com.intellij.ide.projectView.impl; import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.ProjectViewNode; import com.intellij.ide.projectView.ProjectViewNodeDecorator; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.packageDependencies.ui.PackageDependenciesNode; import com.intellij.ui.ColoredTreeCellRenderer; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + /** * This class is intended to combine all decorators for batch usages. * * @author Sergey Malenkov */ public final class CompoundProjectViewNodeDecorator implements ProjectViewNodeDecorator { + private static final ProjectViewNodeDecorator EMPTY = new CompoundProjectViewNodeDecorator(); private static final Key KEY = Key.create("ProjectViewNodeDecorator"); - private final Project project; + private static final Logger LOG = Logger.getInstance(CompoundProjectViewNodeDecorator.class); + private final ProjectViewNodeDecorator[] decorators; /** * @return a shared instance for the specified project */ @NotNull public static ProjectViewNodeDecorator get(@NotNull Project project) { + if (project.isDisposed()) return EMPTY; ProjectViewNodeDecorator provider = project.getUserData(KEY); if (provider != null) return provider; - provider = new CompoundProjectViewNodeDecorator(project); + provider = new CompoundProjectViewNodeDecorator(EP_NAME.getExtensions(project)); project.putUserData(KEY, provider); return provider; } - private CompoundProjectViewNodeDecorator(@NotNull Project project) { - this.project = project; + public CompoundProjectViewNodeDecorator(@NotNull ProjectViewNodeDecorator... decorators) { + this.decorators = decorators; } @Override public void decorate(ProjectViewNode node, PresentationData data) { - if (!project.isDisposed()) { - for (ProjectViewNodeDecorator decorator : EP_NAME.getExtensions(project)) { - decorator.decorate(node, data); - } - } + forEach(decorator -> decorator.decorate(node, data)); } @Override public void decorate(PackageDependenciesNode node, ColoredTreeCellRenderer cellRenderer) { - if (!project.isDisposed()) { - for (ProjectViewNodeDecorator decorator : EP_NAME.getExtensions(project)) { - decorator.decorate(node, cellRenderer); + forEach(decorator -> decorator.decorate(node, cellRenderer)); + } + + private void forEach(@NotNull Consumer consumer) { + for (ProjectViewNodeDecorator decorator : decorators) { + try { + consumer.accept(decorator); + } + catch (IndexNotReadyException exception) { + throw new ProcessCanceledException(exception); + } + catch (ProcessCanceledException exception) { + throw exception; + } + catch (Exception exception) { + LOG.warn("unexpected error in " + decorator, exception); } } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundTreeStructureProvider.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundTreeStructureProvider.java index 69f2091f70b1..5dfee625e6c0 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundTreeStructureProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/CompoundTreeStructureProvider.java @@ -6,7 +6,6 @@ import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -23,24 +22,26 @@ import java.util.Objects; * @author Sergey Malenkov */ public final class CompoundTreeStructureProvider implements TreeStructureProvider { + private static final TreeStructureProvider EMPTY = new CompoundTreeStructureProvider(); private static final Key KEY = Key.create("TreeStructureProvider"); private static final Logger LOG = Logger.getInstance(CompoundTreeStructureProvider.class); - private final Project project; + private final TreeStructureProvider[] providers; /** * @return a shared instance for the specified project */ @NotNull public static TreeStructureProvider get(@NotNull Project project) { + if (project.isDisposed()) return EMPTY; TreeStructureProvider provider = project.getUserData(KEY); if (provider != null) return provider; - provider = new CompoundTreeStructureProvider(project); + provider = new CompoundTreeStructureProvider(EP_NAME.getExtensions(project)); project.putUserData(KEY, provider); return provider; } - private CompoundTreeStructureProvider(@NotNull Project project) { - this.project = project; + public CompoundTreeStructureProvider(@NotNull TreeStructureProvider... providers) { + this.providers = providers; } @NotNull @@ -48,30 +49,25 @@ public final class CompoundTreeStructureProvider implements TreeStructureProvide public Collection modify(@NotNull AbstractTreeNode parent, @NotNull Collection children, ViewSettings settings) { - if (!children.isEmpty()) { - TreeStructureProvider[] providers = getProviders(); - if (providers != null && providers.length != 0) { - for (TreeStructureProvider provider : providers) { - try { - children = provider.modify(parent, children, settings); - if (children.stream().anyMatch(Objects::isNull)) { - LOG.warn("null child provided by " + provider); - children = StreamEx.of(children).nonNull().toImmutableList(); - } - } - catch (IndexNotReadyException exception) { - throw new ProcessCanceledException(exception); - } - catch (ProcessCanceledException exception) { - throw exception; - } - catch (Exception exception) { - LOG.warn("unexpected error in " + provider, exception); - } + for (TreeStructureProvider provider : providers) { + try { + children = provider.modify(parent, children, settings); + if (children.stream().anyMatch(Objects::isNull)) { + LOG.warn("null child provided by " + provider); + children = StreamEx.of(children).nonNull().toImmutableList(); } } - children.forEach(node -> node.setParent(parent)); + catch (IndexNotReadyException exception) { + throw new ProcessCanceledException(exception); + } + catch (ProcessCanceledException exception) { + throw exception; + } + catch (Exception exception) { + LOG.warn("unexpected error in " + provider, exception); + } } + children.forEach(node -> node.setParent(parent)); return children; } @@ -79,24 +75,20 @@ public final class CompoundTreeStructureProvider implements TreeStructureProvide @Override public Object getData(Collection selection, String id) { if (id != null && selection != null && !selection.isEmpty()) { - TreeStructureProvider[] providers = getProviders(); - if (providers != null && providers.length != 0) { - for (TreeStructureProvider provider : providers) { - if (isDumbMode(provider)) continue; + for (TreeStructureProvider provider : providers) { + try { Object data = provider.getData(selection, id); if (data != null) return data; } + catch (IndexNotReadyException ignore) { + } + catch (ProcessCanceledException ignore) { + } + catch (Exception exception) { + LOG.warn("unexpected error in " + provider, exception); + } } } return null; } - - @Nullable - private TreeStructureProvider[] getProviders() { - return project.isDisposed() ? null : EP_NAME.getExtensions(project); - } - - private boolean isDumbMode(TreeStructureProvider provider) { - return project.isDisposed() || DumbService.isDumb(project) && !DumbService.isDumbAware(provider); - } }