diff --git a/platform/editor-ui-api/api-dump.txt b/platform/editor-ui-api/api-dump.txt index b78ff1676c3d..9ecaa22feeb7 100644 --- a/platform/editor-ui-api/api-dump.txt +++ b/platform/editor-ui-api/api-dump.txt @@ -151,6 +151,7 @@ com.intellij.ide.projectView.TreeStructureProvider - com.intellij.openapi.project.PossiblyDumbAware - getData(java.util.Collection,java.lang.String):java.lang.Object - a:modify(com.intellij.ide.util.treeView.AbstractTreeNode,java.util.Collection,com.intellij.ide.projectView.ViewSettings):java.util.Collection +- uiDataSnapshot(com.intellij.openapi.actionSystem.DataSink,java.util.Collection):V com.intellij.ide.projectView.ViewSettings - com.intellij.ide.util.treeView.NodeOptions - sf:DEFAULT:com.intellij.ide.projectView.ViewSettings diff --git a/platform/editor-ui-api/src/com/intellij/ide/projectView/TreeStructureProvider.java b/platform/editor-ui-api/src/com/intellij/ide/projectView/TreeStructureProvider.java index b7f11f9c23f1..6d7e59339056 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/projectView/TreeStructureProvider.java +++ b/platform/editor-ui-api/src/com/intellij/ide/projectView/TreeStructureProvider.java @@ -2,6 +2,7 @@ package com.intellij.ide.projectView; import com.intellij.ide.util.treeView.AbstractTreeNode; +import com.intellij.openapi.actionSystem.DataSink; import com.intellij.openapi.extensions.ProjectExtensionPointName; import com.intellij.openapi.project.PossiblyDumbAware; import org.jetbrains.annotations.ApiStatus; @@ -35,6 +36,17 @@ public interface TreeStructureProvider extends PossiblyDumbAware { @NotNull Collection> children, ViewSettings settings); + /** + * Override to populate UI data snapshot for the selection. + * Or implement a {@link com.intellij.openapi.actionSystem.UiDataRule} instead. + * + * @see com.intellij.openapi.actionSystem.UiDataProvider + */ + default void uiDataSnapshot(@NotNull DataSink sink, + @NotNull Collection> selection) { + DataSink.uiDataSnapshot(sink, dataId -> getData(selection, dataId)); + } + /** * Returns a user data object of the specified type for the specified selection in the * project view. @@ -45,7 +57,7 @@ public interface TreeStructureProvider extends PossiblyDumbAware { * @return the data object, or null if no data object can be returned by this provider. * @see com.intellij.openapi.actionSystem.DataProvider * - * @deprecated Use {@link com.intellij.openapi.actionSystem.UiDataRule} instead. + * @deprecated Use {@link #uiDataSnapshot(DataSink, Collection)} instead. */ @Deprecated(forRemoval = true) default @Nullable Object getData(@NotNull Collection> selected, @NotNull String dataId) { diff --git a/platform/lang-impl/api-dump-unreviewed.txt b/platform/lang-impl/api-dump-unreviewed.txt index 3fdf2868069d..9f7a2f0f7344 100644 --- a/platform/lang-impl/api-dump-unreviewed.txt +++ b/platform/lang-impl/api-dump-unreviewed.txt @@ -16016,8 +16016,8 @@ f:com.intellij.ide.projectView.impl.CompoundProjectViewNodeDecorator f:com.intellij.ide.projectView.impl.CompoundTreeStructureProvider - com.intellij.ide.projectView.TreeStructureProvider - s:get(com.intellij.openapi.project.Project):com.intellij.ide.projectView.TreeStructureProvider -- getData(java.util.Collection,java.lang.String):java.lang.Object - modify(com.intellij.ide.util.treeView.AbstractTreeNode,java.util.Collection,com.intellij.ide.projectView.ViewSettings):java.util.Collection +- uiDataSnapshot(com.intellij.openapi.actionSystem.DataSink,java.util.Collection):V f:com.intellij.ide.projectView.impl.DirectoryUrl - com.intellij.ide.projectView.impl.AbstractUrl - (java.lang.String,java.lang.String):V diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java index 2441e067ff92..cd2e2196d985 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java @@ -337,10 +337,15 @@ public abstract class AbstractProjectViewPane implements UiCompatibleDataProvide navigatables.isEmpty() ? null : navigatables.toArray(Navigatable.EMPTY_NAVIGATABLE_ARRAY)); } if (myTreeStructure instanceof AbstractTreeStructureBase treeStructure) { - //noinspection unchecked - List> selection = (List)ContainerUtil.filterIsInstance( - selectedUserObjects, AbstractTreeNode.class); - DataSink.uiDataSnapshot(sink, o -> treeStructure.getDataFromProviders(selection, o)); + List providers = treeStructure.getProviders(); + if (providers != null && !providers.isEmpty()) { + //noinspection unchecked + List> selection = (List)ContainerUtil.filterIsInstance( + selectedUserObjects, AbstractTreeNode.class); + for (TreeStructureProvider provider : ContainerUtil.reverse(providers)) { + provider.uiDataSnapshot(sink, selection); + } + } } sink.set(CommonDataKeys.PROJECT, myProject); sink.set(PlatformCoreDataKeys.SELECTED_ITEMS, selectedUserObjects); 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 3ff81f23724b..9c17aae3779d 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 @@ -4,11 +4,13 @@ package com.intellij.ide.projectView.impl; import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.util.treeView.AbstractTreeNode; +import com.intellij.openapi.actionSystem.DataSink; 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.util.containers.ContainerUtil; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,7 +50,7 @@ public final class CompoundTreeStructureProvider implements TreeStructureProvide for (TreeStructureProvider provider : EP.getExtensions(myProject)) { try { children = provider.modify(parent, children, settings); - if (children.stream().anyMatch(Objects::isNull)) { + if (ContainerUtil.exists(children, Objects::isNull)) { LOG.warn("null child provided by " + provider); children = StreamEx.of(children).nonNull().toImmutableList(); } @@ -68,20 +70,17 @@ public final class CompoundTreeStructureProvider implements TreeStructureProvide } @Override - public @Nullable Object getData(@NotNull Collection> selection, @NotNull String dataId) { - if (!myProject.isDisposed() && !selection.isEmpty()) { - for (TreeStructureProvider provider : EP.getExtensions(myProject)) { - try { - Object data = provider.getData(selection, dataId); - if (data != null) return data; - } - catch (IndexNotReadyException | ProcessCanceledException ignore) { - } - catch (Exception exception) { - LOG.warn("unexpected error in " + provider, exception); - } + public void uiDataSnapshot(@NotNull DataSink sink, @NotNull Collection> selection) { + if (myProject.isDisposed() || selection.isEmpty()) return; + for (TreeStructureProvider provider : ContainerUtil.reverse(EP.getExtensions(myProject))) { + try { + provider.uiDataSnapshot(sink, selection); + } + catch (IndexNotReadyException | ProcessCanceledException ignore) { + } + catch (Exception exception) { + LOG.warn("unexpected error in " + provider, exception); } } - return null; } } diff --git a/platform/structure-view-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java b/platform/structure-view-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java index 50fcd4201d06..f65bc37a3cdf 100644 --- a/platform/structure-view-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java +++ b/platform/structure-view-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java @@ -4,9 +4,6 @@ package com.intellij.ide.util.treeView; import com.intellij.ide.projectView.SettingsProvider; import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; -import com.intellij.openapi.actionSystem.CompositeDataProvider; -import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.PlatformCoreDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; @@ -15,7 +12,6 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,20 +88,6 @@ public abstract class AbstractTreeStructureBase extends AbstractTreeStructure { @Deprecated(forRemoval = true) @ApiStatus.Internal public @Nullable Object getDataFromProviders(@NotNull List> selectedNodes, @NotNull String dataId) { - List providers = getProvidersDumbAware(); - if (providers.isEmpty()) { - return null; - } - if (PlatformCoreDataKeys.BGT_DATA_PROVIDER.is(dataId)) { - List bgtProviders = ContainerUtil.mapNotNull(providers, o -> (DataProvider)o.getData(selectedNodes, dataId)); - return CompositeDataProvider.compose(bgtProviders); - } - for (TreeStructureProvider treeStructureProvider : providers) { - Object fromProvider = treeStructureProvider.getData(selectedNodes, dataId); - if (fromProvider != null) { - return fromProvider; - } - } return null; } diff --git a/plugins/commander/src/com/intellij/ide/commander/CommanderPanel.java b/plugins/commander/src/com/intellij/ide/commander/CommanderPanel.java index 9ad28d9efbb9..0f0fcbadf18b 100644 --- a/plugins/commander/src/com/intellij/ide/commander/CommanderPanel.java +++ b/plugins/commander/src/com/intellij/ide/commander/CommanderPanel.java @@ -8,6 +8,7 @@ import com.intellij.ide.DeleteProvider; import com.intellij.ide.IdeBundle; import com.intellij.ide.IdeView; import com.intellij.ide.projectView.ProjectViewNode; +import com.intellij.ide.projectView.TreeStructureProvider; import com.intellij.ide.projectView.impl.ModuleGroup; import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase; import com.intellij.ide.projectView.impl.nodes.LibraryGroupElement; @@ -375,7 +376,12 @@ public class CommanderPanel extends JPanel { sink.set(PlatformDataKeys.DELETE_ELEMENT_PROVIDER, myDeleteElementProvider); if (myProjectTreeStructure != null) { - DataSink.uiDataSnapshot(sink, dataId -> myProjectTreeStructure.getDataFromProviders(selection, dataId)); + List providers = myProjectTreeStructure.getProviders(); + if (providers != null && !providers.isEmpty()) { + for (TreeStructureProvider provider : ContainerUtil.reverse(providers)) { + provider.uiDataSnapshot(sink, selection); + } + } } sink.lazy(CommonDataKeys.PSI_ELEMENT, () -> { return getNodeElement(ContainerUtil.getOnlyItem(selection)); diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java index e058266655c5..5b411ccaf9ca 100644 --- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java +++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java @@ -7,8 +7,7 @@ import com.intellij.ide.projectView.impl.nodes.PsiFileNode; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.lang.properties.*; import com.intellij.lang.properties.psi.PropertiesFile; -import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.PlatformCoreDataKeys; +import com.intellij.openapi.actionSystem.DataSink; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.project.DumbAware; @@ -101,32 +100,25 @@ public class ResourceBundleGrouper implements TreeStructureProvider, DumbAware { } @Override - public Object getData(@NotNull Collection> selected, @NotNull String dataId) { - if (PlatformCoreDataKeys.BGT_DATA_PROVIDER.is(dataId)) { - return (DataProvider)slowId -> getSlowData(selected, slowId); - } - return null; - } - - private static Object getSlowData(@NotNull Collection> selected, @NotNull String dataId) { - if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { - for (AbstractTreeNode selectedElement : selected) { + public void uiDataSnapshot(@NotNull DataSink sink, @NotNull Collection> selection) { + sink.lazy(PlatformDataKeys.DELETE_ELEMENT_PROVIDER, () -> { + for (AbstractTreeNode selectedElement : selection) { Object element = selectedElement.getValue(); if (element instanceof ResourceBundle) { return new ResourceBundleDeleteProvider(); } } - } - else if (ResourceBundle.ARRAY_DATA_KEY.is(dataId)) { + return null; + }); + sink.lazy(ResourceBundle.ARRAY_DATA_KEY, () -> { List selectedElements = new ArrayList<>(); - for (AbstractTreeNode node : selected) { - final Object value = node.getValue(); + for (AbstractTreeNode node : selection) { + Object value = node.getValue(); if (value instanceof ResourceBundle) { selectedElements.add((ResourceBundle)value); } } return selectedElements.isEmpty() ? null : selectedElements.toArray(new ResourceBundle[0]); - } - return null; + }); } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProvider.java index 70f2f977618c..12e9144c3718 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProvider.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProvider.java @@ -8,10 +8,7 @@ import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.nodes.BasePsiNode; import com.intellij.ide.util.DeleteHandler; import com.intellij.ide.util.treeView.AbstractTreeNode; -import com.intellij.openapi.actionSystem.ActionUpdateThread; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassOwner; @@ -85,26 +82,16 @@ public final class FormMergerTreeStructureProvider implements TreeStructureProvi } @Override - public Object getData(@NotNull Collection> selected, @NotNull String dataId) { - if (Form.DATA_KEY.is(dataId)) { - List
result = new ArrayList<>(); - for (AbstractTreeNode node : selected) { - if (node instanceof FormNode) { - result.add(((FormNode)node).getValue()); - } - } - if (!result.isEmpty()) { - return result.toArray(new Form[0]); - } - } - else if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { - for (AbstractTreeNode node : selected) { - if (node instanceof FormNode) { - return new MyDeleteProvider(selected); - } - } - } - return null; + public void uiDataSnapshot(@NotNull DataSink sink, + @NotNull Collection> selection) { + List nodes = ContainerUtil.filterIsInstance(selection, FormNode.class); + if (nodes.isEmpty()) return; + sink.lazy(Form.DATA_KEY, () -> { + return ContainerUtil.map2Array(nodes, Form.class, o -> o.getValue()); + }); + sink.lazy(PlatformDataKeys.DELETE_ELEMENT_PROVIDER, () -> { + return new MyDeleteProvider(selection); + }); } private static Collection convertToFiles(Collection> formNodes) {