From 8ee289751b67df66ccd7283e0ea769bc3963d821 Mon Sep 17 00:00:00 2001 From: Sergei Tachenov Date: Fri, 13 Sep 2024 13:30:27 +0300 Subject: [PATCH] IJPL-158493 Introduce ProjectFileNodeUpdaterInvoker To reuse ProjectFileNodeUpdater for the new coroutine-based Project View, we need to remove its direct dependency on the legacy Invoker. Introduce a new abstraction layer, including only the methods that are really needed. Because the existing implementation relies on the invoker as the parent Disposable, we must implement it in the new interface as well, and ensure that our invoker is disposed along with the delegate. To remove the dependency in AsyncProjectViewSupport, remove the invoke() call around roots.forEach. It's a safe thing to do because the ProjectFileNodeUpdater itself only ever invokes updateStructure in the same invoker, so that wrapping was effectively a no-op. GitOrigin-RevId: dd239b1330a2d8ef84f09e1dc5e3a49d79d8414c --- .../impl/AsyncProjectViewSupport.java | 2 +- .../tree/project/ProjectFileNodeUpdater.java | 6 +++- .../ProjectFileNodeUpdaterInvoker.java | 13 +++++++++ .../ProjectFileNodeUpdaterLegacyInvoker.java | 29 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterInvoker.java create mode 100644 platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterLegacyInvoker.java diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java index 1b7dee06bb32..cffede59b015 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java @@ -73,7 +73,7 @@ public final class AsyncProjectViewSupport { } List roots = collector.get(); LOG.debug("found ", roots.size(), " roots in ", System.currentTimeMillis() - time, "ms"); - myStructureTreeModel.getInvoker().invoke(() -> roots.forEach(root -> updateByFile(root, true))); + roots.forEach(root -> updateByFile(root, true)); } } }; diff --git a/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdater.java b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdater.java index ca334eee064c..a62ae7cd067a 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdater.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdater.java @@ -29,12 +29,16 @@ import static com.intellij.psi.util.PsiUtilCore.getVirtualFile; public abstract class ProjectFileNodeUpdater { private static final Logger LOG = Logger.getInstance(ProjectFileNodeUpdater.class); private final Ref> reference = new Ref<>(); - private final Invoker invoker; + private final ProjectFileNodeUpdaterInvoker invoker; private volatile boolean root; private volatile long time; private volatile int size; public ProjectFileNodeUpdater(@NotNull Project project, @NotNull Invoker invoker) { + this(project, new ProjectFileNodeUpdaterLegacyInvoker(invoker)); + } + + private ProjectFileNodeUpdater(@NotNull Project project, @NotNull ProjectFileNodeUpdaterInvoker invoker) { this.invoker = invoker; MessageBusConnection connection = project.getMessageBus().connect(invoker); connection.subscribe(ModuleRootListener.TOPIC, new ModuleRootListener() { diff --git a/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterInvoker.java b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterInvoker.java new file mode 100644 index 000000000000..2e929e5fc12f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterInvoker.java @@ -0,0 +1,13 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ui.tree.project; + +import com.intellij.openapi.Disposable; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.concurrency.Promise; + +@ApiStatus.Internal +public interface ProjectFileNodeUpdaterInvoker extends Disposable { + Promise invoke(@NotNull Runnable runnable); + void invokeLater(@NotNull Runnable runnable, int delay); +} diff --git a/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterLegacyInvoker.java b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterLegacyInvoker.java new file mode 100644 index 000000000000..abe71e29c821 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/tree/project/ProjectFileNodeUpdaterLegacyInvoker.java @@ -0,0 +1,29 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ui.tree.project; + +import com.intellij.openapi.util.Disposer; +import com.intellij.util.concurrency.Invoker; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.concurrency.Promise; + +class ProjectFileNodeUpdaterLegacyInvoker implements ProjectFileNodeUpdaterInvoker { + private final @NotNull Invoker myInvoker; + + ProjectFileNodeUpdaterLegacyInvoker(@NotNull Invoker invoker) { + myInvoker = invoker; + Disposer.register(invoker, this); + } + + @Override + public Promise invoke(@NotNull Runnable runnable) { + return myInvoker.invoke(runnable); + } + + @Override + public void invokeLater(@NotNull Runnable runnable, int delay) { + myInvoker.invokeLater(runnable, delay); + } + + @Override + public void dispose() { } +}