IJPL-158493 Extract a superclass from AsyncProjectViewSupport

To avoid duplicating a lot of logic in the new coroutine-based
implementation, extract the parts of AsyncProjectViewSupport
that don't depend on the models into a superclass.

Refactor the code around acceptAndUpdate a bit so
the only model-dependent part is now in this function
with a new signature, so it can be used in all places
where a similar logic was used.

Other than that, the code was mostly just moved.
The part about myNodeUpdater is a bit ugly,
as it's now initialized in the derived class and then
used in the base class in setupListeners.
It's OK, as it's an internal implementation class,
it won't have a lot of subclasses, so we're not forcing
anyone to figure out this ugliness before using it.

GitOrigin-RevId: a8d858c5c579a538a4c917cf830bc0704468f43d
This commit is contained in:
Sergei Tachenov
2024-09-13 13:50:38 +03:00
committed by intellij-monorepo-bot
parent 8ee289751b
commit b211b4adeb
7 changed files with 252 additions and 189 deletions

View File

@@ -30,6 +30,7 @@ import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformUtils;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,8 +51,9 @@ public class PackageViewPane extends AbstractProjectViewPaneWithAsyncSupport {
super(project);
}
@ApiStatus.Internal
@Override
protected void configureAsyncSupport(@NotNull AsyncProjectViewSupport support) {
protected void configureAsyncSupport(@NotNull ProjectViewPaneSupport support) {
support.setMultiSelectionEnabled(false);
}

View File

@@ -16329,7 +16329,6 @@ c:com.intellij.ide.projectView.impl.ProjectViewPane
- sf:ID:java.lang.String
- <init>(com.intellij.openapi.project.Project):V
- s:canBeSelectedInProjectView(com.intellij.openapi.project.Project,com.intellij.openapi.vfs.VirtualFile):Z
- configureAsyncSupport(com.intellij.ide.projectView.impl.AsyncProjectViewSupport):V
- createSelectInTarget():com.intellij.ide.SelectInTarget
- p:createStructure():com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase
- p:createTree(javax.swing.tree.DefaultTreeModel):com.intellij.ide.projectView.impl.ProjectViewTree

View File

@@ -222,11 +222,11 @@ public abstract class AbstractProjectViewPane implements UiCompatibleDataProvide
public void updateFrom(Object element, boolean forceResort, boolean updateStructure) {
if (element instanceof PsiElement) {
AsyncProjectViewSupport support = getAsyncSupport();
var support = getAsyncSupport();
if (support != null) support.updateByElement((PsiElement)element, updateStructure);
}
else if (element instanceof TreePath) {
AsyncProjectViewSupport support = getAsyncSupport();
var support = getAsyncSupport();
if (support != null) support.update((TreePath)element, updateStructure);
}
}
@@ -1116,7 +1116,7 @@ public abstract class AbstractProjectViewPane implements UiCompatibleDataProvide
return TreeUtil.getLastUserObject(AbstractTreeNode.class, path);
}
AsyncProjectViewSupport getAsyncSupport() {
@Nullable ProjectViewPaneSupport getAsyncSupport() {
return null;
}

View File

@@ -47,7 +47,7 @@ import java.util.Comparator;
import static com.intellij.ide.projectView.ProjectViewSelectionTopicKt.PROJECT_VIEW_SELECTION_TOPIC;
public abstract class AbstractProjectViewPaneWithAsyncSupport extends AbstractProjectViewPane {
private AsyncProjectViewSupport myAsyncSupport;
private ProjectViewPaneSupport myAsyncSupport;
private JComponent myComponent;
protected AbstractProjectViewPaneWithAsyncSupport(@NotNull Project project) {
@@ -118,7 +118,7 @@ public abstract class AbstractProjectViewPaneWithAsyncSupport extends AbstractPr
}
@ApiStatus.Internal
protected void configureAsyncSupport(@NotNull AsyncProjectViewSupport support) {
protected void configureAsyncSupport(@NotNull ProjectViewPaneSupport support) {
}
@Override
@@ -236,7 +236,7 @@ public abstract class AbstractProjectViewPaneWithAsyncSupport extends AbstractPr
}
@Override
AsyncProjectViewSupport getAsyncSupport() {
ProjectViewPaneSupport getAsyncSupport() {
return myAsyncSupport;
}

View File

@@ -1,39 +1,25 @@
// 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.ide.projectView.impl;
import com.intellij.ide.CopyPasteUtil;
import com.intellij.ide.bookmark.BookmarksListener;
import com.intellij.ide.bookmark.FileBookmarksListener;
import com.intellij.ide.projectView.ProjectViewPsiTreeChangeListener;
import com.intellij.ide.projectView.impl.ProjectViewPaneSelectionHelper.SelectionDescriptor;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.FileStatusListener;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.problems.ProblemListener;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.tree.*;
import com.intellij.ui.tree.project.ProjectFileNodeUpdater;
import com.intellij.util.SmartList;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.util.Comparator;
import java.util.List;
@@ -44,12 +30,10 @@ import static com.intellij.ide.util.treeView.TreeState.expand;
import static com.intellij.ui.tree.project.ProjectFileNode.findArea;
@ApiStatus.Internal
public final class AsyncProjectViewSupport {
public final class AsyncProjectViewSupport extends ProjectViewPaneSupport {
private static final Logger LOG = Logger.getInstance(AsyncProjectViewSupport.class);
private final ProjectFileNodeUpdater myNodeUpdater;
private final StructureTreeModel myStructureTreeModel;
private final AsyncTreeModel myAsyncTreeModel;
private boolean myMultiSelectionEnabled = true;
public AsyncProjectViewSupport(@NotNull Disposable parent,
@NotNull Project project,
@@ -77,84 +61,20 @@ public final class AsyncProjectViewSupport {
}
}
};
MessageBusConnection connection = project.getMessageBus().connect(parent);
connection.subscribe(BookmarksListener.TOPIC, new FileBookmarksListener(file -> updateByFile(file, !file.isDirectory())));
PsiManager.getInstance(project).addPsiTreeChangeListener(new ProjectViewPsiTreeChangeListener(project) {
@Override
protected boolean isFlattenPackages() {
return structure instanceof AbstractProjectTreeStructure && ((AbstractProjectTreeStructure)structure).isFlattenPackages();
}
@Override
protected DefaultMutableTreeNode getRootNode() {
return null;
}
@Override
protected void addSubtreeToUpdateByRoot() {
myNodeUpdater.updateFromRoot();
}
@Override
protected boolean addSubtreeToUpdateByElement(@NotNull PsiElement element) {
VirtualFile file = PsiUtilCore.getVirtualFile(element);
if (file != null) {
myNodeUpdater.updateFromFile(file);
}
else {
updateByElement(element, true);
}
return true;
}
}, parent);
FileStatusManager.getInstance(project).addFileStatusListener(new FileStatusListener() {
@Override
public void fileStatusesChanged() {
updateAllPresentations();
}
@Override
public void fileStatusChanged(@NotNull VirtualFile file) {
updateByFile(file, false);
}
}, parent);
CopyPasteUtil.addDefaultListener(parent, element -> updateByElement(element, false));
project.getMessageBus().connect(parent).subscribe(ProblemListener.TOPIC, new ProblemListener() {
@Override
public void problemsAppeared(@NotNull VirtualFile file) {
updatePresentationsFromRootTo(file);
}
@Override
public void problemsDisappeared(@NotNull VirtualFile file) {
updatePresentationsFromRootTo(file);
}
});
project.getMessageBus().connect(parent).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() {
// structure = true because files may have children too, e.g. if the Show Members option is selected, and children inherit file colors
@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
updateByFile(file, true);
}
@Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
updateByFile(file, true);
}
});
setupListeners(parent, project, structure);
}
public AsyncTreeModel getTreeModel() {
return myAsyncTreeModel;
}
public void setComparator(@NotNull Comparator<? super NodeDescriptor<?>> comparator) {
@Override
public void setComparator(@Nullable Comparator<? super NodeDescriptor<?>> comparator) {
myStructureTreeModel.setComparator(comparator);
}
public ActionCallback select(JTree tree, Object object, VirtualFile file) {
@Override
public @NotNull ActionCallback select(@NotNull JTree tree, @Nullable Object object, @Nullable VirtualFile file) {
if (SelectInProjectViewImplKt.getLOG().isDebugEnabled()) {
SelectInProjectViewImplKt.getLOG().debug(
"AsyncProjectViewSupport.select: " +
@@ -230,45 +150,7 @@ public final class AsyncProjectViewSupport {
myAsyncTreeModel.accept(visitor).onProcessed(path -> myAsyncTreeModel.onValidThread(task));
}
public void setMultiSelectionEnabled(boolean enabled) {
myMultiSelectionEnabled = enabled;
}
private boolean selectPaths(@NotNull JTree tree, @NotNull List<TreePath> paths, @NotNull TreeVisitor visitor) {
if (paths.isEmpty()) {
SelectInProjectViewImplKt.getLOG().debug("Nothing to select");
return false;
}
if (paths.size() > 1 && myMultiSelectionEnabled) {
if (visitor instanceof ProjectViewNodeVisitor nodeVisitor) {
return selectPaths(tree, new SelectionDescriptor(nodeVisitor.getElement(), nodeVisitor.getFile(), paths));
}
if (visitor instanceof ProjectViewFileVisitor fileVisitor) {
return selectPaths(tree, new SelectionDescriptor(null, fileVisitor.getElement(), paths));
}
}
if (!myMultiSelectionEnabled) {
SelectInProjectViewImplKt.getLOG().debug("Selecting only the first path because multi-selection is disabled");
}
TreePath path = paths.get(0);
tree.expandPath(path); // request to expand found path
TreeUtil.selectPaths(tree, path); // select and scroll to center
if (SelectInProjectViewImplKt.getLOG().isDebugEnabled()) {
SelectInProjectViewImplKt.getLOG().debug("Selected the only path: " + path);
}
return true;
}
private static boolean selectPaths(@NotNull JTree tree, @NotNull SelectionDescriptor selectionDescriptor) {
List<? extends TreePath> adjustedPaths = ProjectViewPaneSelectionHelper.getAdjustedPaths(selectionDescriptor);
adjustedPaths.forEach(it -> tree.expandPath(it));
TreeUtil.selectPaths(tree, adjustedPaths);
if (SelectInProjectViewImplKt.getLOG().isDebugEnabled()) {
SelectInProjectViewImplKt.getLOG().debug("Selected paths adjusted according to " + selectionDescriptor + ": " + adjustedPaths);
}
return true;
}
@Override
public void updateAll(Runnable onDone) {
LOG.debug(new RuntimeException("reload a whole tree"));
CompletableFuture<?> future = myStructureTreeModel.invalidateAsync();
@@ -277,67 +159,25 @@ public final class AsyncProjectViewSupport {
}
}
@Override
public void update(@NotNull TreePath path, boolean structure) {
myStructureTreeModel.invalidate(path, structure);
}
public void update(@NotNull List<? extends TreePath> list, boolean structure) {
for (TreePath path : list) update(path, structure);
}
public void updateByFile(@NotNull VirtualFile file, boolean structure) {
LOG.debug(structure ? "updateChildrenByFile: " : "updatePresentationByFile: ", file);
update(null, file, structure);
}
public void updateByElement(@NotNull PsiElement element, boolean structure) {
LOG.debug(structure ? "updateChildrenByElement: " : "updatePresentationByElement: ", element);
update(element, null, structure);
}
private void update(PsiElement element, VirtualFile file, boolean structure) {
SmartList<TreePath> list = new SmartList<>();
TreeVisitor visitor = AbstractProjectViewPane.createVisitor(element, file, list);
if (visitor != null) acceptAndUpdate(visitor, list, structure);
}
private void acceptAndUpdate(@NotNull TreeVisitor visitor, List<? extends TreePath> list, boolean structure) {
myAsyncTreeModel.accept(visitor, false).onSuccess(path -> update(list, structure));
}
private void updatePresentationsFromRootTo(@NotNull VirtualFile file) {
// find first valid parent for removed file
while (!file.isValid()) {
file = file.getParent();
if (file == null) return;
}
SmartList<TreePath> structures = new SmartList<>();
SmartList<TreePath> presentations = new SmartList<>();
myAsyncTreeModel.accept(new ProjectViewFileVisitor(file, structures::add) {
@Override
protected @NotNull Action visit(@NotNull TreePath path, @NotNull AbstractTreeNode node, @NotNull VirtualFile element) {
Action action = super.visit(path, node, element);
if (action == Action.CONTINUE) presentations.add(path);
return action;
}
}, false).onSuccess(path -> {
update(presentations, false);
update(structures, true);
@Override
protected void acceptAndUpdate(
@NotNull TreeVisitor visitor,
@Nullable List<? extends TreePath> presentations,
@Nullable List<? extends TreePath> structures
) {
myAsyncTreeModel.accept(visitor, false).onSuccess(path -> {
if (presentations != null) update(presentations, false);
if (structures != null) update(structures, true);
});
}
private void updateAllPresentations() {
SmartList<TreePath> list = new SmartList<>();
acceptAndUpdate(new TreeVisitor() {
@Override
public @NotNull Action visit(@NotNull TreePath path) {
list.add(path);
return Action.CONTINUE;
}
}, list, false);
}
void setModelTo(@NotNull JTree tree) {
@Override
public void setModelTo(@NotNull JTree tree) {
RestoreSelectionListener listener = new RestoreSelectionListener();
tree.addTreeSelectionListener(listener);
tree.setModel(myAsyncTreeModel);

View File

@@ -24,6 +24,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem;
import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -44,8 +45,9 @@ public class ProjectViewPane extends AbstractProjectViewPaneWithAsyncSupport {
super(project);
}
@ApiStatus.Internal
@Override
public void configureAsyncSupport(@NotNull AsyncProjectViewSupport support) {
public void configureAsyncSupport(@NotNull ProjectViewPaneSupport support) {
support.setMultiSelectionEnabled(false);
}

View File

@@ -0,0 +1,220 @@
// 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.ide.projectView.impl;
import com.intellij.ide.CopyPasteUtil;
import com.intellij.ide.bookmark.BookmarksListener;
import com.intellij.ide.bookmark.FileBookmarksListener;
import com.intellij.ide.projectView.ProjectViewPsiTreeChangeListener;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vcs.FileStatusListener;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.problems.ProblemListener;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.tree.TreeVisitor;
import com.intellij.ui.tree.project.ProjectFileNodeUpdater;
import com.intellij.util.SmartList;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.util.Comparator;
import java.util.List;
@ApiStatus.Internal
public abstract class ProjectViewPaneSupport {
private static final Logger LOG = Logger.getInstance(ProjectViewPaneSupport.class);
private boolean myMultiSelectionEnabled = true;
protected ProjectFileNodeUpdater myNodeUpdater;
protected void setupListeners(@NotNull Disposable parent, @NotNull Project project, @NotNull AbstractTreeStructure structure) {
MessageBusConnection connection = project.getMessageBus().connect(parent);
connection.subscribe(BookmarksListener.TOPIC, new FileBookmarksListener(file -> updateByFile(file, !file.isDirectory())));
PsiManager.getInstance(project).addPsiTreeChangeListener(new ProjectViewPsiTreeChangeListener(project) {
@Override
protected boolean isFlattenPackages() {
return structure instanceof AbstractProjectTreeStructure && ((AbstractProjectTreeStructure)structure).isFlattenPackages();
}
@Override
protected DefaultMutableTreeNode getRootNode() {
return null;
}
@Override
protected void addSubtreeToUpdateByRoot() {
myNodeUpdater.updateFromRoot();
}
@Override
protected boolean addSubtreeToUpdateByElement(@NotNull PsiElement element) {
VirtualFile file = PsiUtilCore.getVirtualFile(element);
if (file != null) {
myNodeUpdater.updateFromFile(file);
}
else {
updateByElement(element, true);
}
return true;
}
}, parent);
FileStatusManager.getInstance(project).addFileStatusListener(new FileStatusListener() {
@Override
public void fileStatusesChanged() {
updateAllPresentations();
}
@Override
public void fileStatusChanged(@NotNull VirtualFile file) {
updateByFile(file, false);
}
}, parent);
CopyPasteUtil.addDefaultListener(parent, element -> updateByElement(element, false));
project.getMessageBus().connect(parent).subscribe(ProblemListener.TOPIC, new ProblemListener() {
@Override
public void problemsAppeared(@NotNull VirtualFile file) {
updatePresentationsFromRootTo(file);
}
@Override
public void problemsDisappeared(@NotNull VirtualFile file) {
updatePresentationsFromRootTo(file);
}
});
project.getMessageBus().connect(parent).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() {
// structure = true because files may have children too, e.g. if the Show Members option is selected, and children inherit file colors
@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
updateByFile(file, true);
}
@Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
updateByFile(file, true);
}
});
}
public abstract void setModelTo(@NotNull JTree tree);
public abstract void setComparator(@Nullable Comparator<? super NodeDescriptor<?>> comparator);
public void setMultiSelectionEnabled(boolean enabled) {
myMultiSelectionEnabled = enabled;
}
public abstract void updateAll(Runnable onDone);
public void update(@NotNull List<? extends TreePath> list, boolean structure) {
for (TreePath path : list) update(path, structure);
}
public abstract void update(@NotNull TreePath path, boolean structure);
public void updateByFile(@NotNull VirtualFile file, boolean structure) {
LOG.debug(structure ? "updateChildrenByFile: " : "updatePresentationByFile: ", file);
update(null, file, structure);
}
public void updateByElement(@NotNull PsiElement element, boolean structure) {
LOG.debug(structure ? "updateChildrenByElement: " : "updatePresentationByElement: ", element);
update(element, null, structure);
}
protected void update(@Nullable PsiElement element, @Nullable VirtualFile file, boolean structure) {
SmartList<TreePath> list = new SmartList<>();
TreeVisitor visitor = AbstractProjectViewPane.createVisitor(element, file, list);
if (visitor != null) acceptAndUpdate(visitor, structure ? null : list, structure ? list : null);
}
protected void updateAllPresentations() {
SmartList<TreePath> list = new SmartList<>();
acceptAndUpdate(new TreeVisitor() {
@Override
public @NotNull Action visit(@NotNull TreePath path) {
list.add(path);
return Action.CONTINUE;
}
}, list, null);
}
protected void updatePresentationsFromRootTo(@NotNull VirtualFile file) {
// find first valid parent for removed file
while (!file.isValid()) {
file = file.getParent();
if (file == null) return;
}
SmartList<TreePath> structures = new SmartList<>();
SmartList<TreePath> presentations = new SmartList<>();
var visitor = new ProjectViewFileVisitor(file, structures::add) {
@Override
protected @NotNull Action visit(@NotNull TreePath path, @NotNull AbstractTreeNode node, @NotNull VirtualFile element) {
Action action = super.visit(path, node, element);
if (action == Action.CONTINUE) presentations.add(path);
return action;
}
};
acceptAndUpdate(visitor, presentations, structures);
}
protected abstract void acceptAndUpdate(
@NotNull TreeVisitor visitor,
@Nullable List<? extends TreePath> presentations,
@Nullable List<? extends TreePath> structures
);
public abstract @NotNull ActionCallback select(@NotNull JTree tree, @Nullable Object object, @Nullable VirtualFile file);
protected boolean selectPaths(@NotNull JTree tree, @NotNull List<TreePath> paths, @NotNull TreeVisitor visitor) {
if (paths.isEmpty()) {
SelectInProjectViewImplKt.getLOG().debug("Nothing to select");
return false;
}
if (paths.size() > 1 && myMultiSelectionEnabled) {
if (visitor instanceof ProjectViewNodeVisitor nodeVisitor) {
return selectPaths(tree, new ProjectViewPaneSelectionHelper.SelectionDescriptor(nodeVisitor.getElement(), nodeVisitor.getFile(), paths));
}
if (visitor instanceof ProjectViewFileVisitor fileVisitor) {
return selectPaths(tree, new ProjectViewPaneSelectionHelper.SelectionDescriptor(null, fileVisitor.getElement(), paths));
}
}
if (!myMultiSelectionEnabled) {
SelectInProjectViewImplKt.getLOG().debug("Selecting only the first path because multi-selection is disabled");
}
TreePath path = paths.get(0);
tree.expandPath(path); // request to expand found path
TreeUtil.selectPaths(tree, path); // select and scroll to center
if (SelectInProjectViewImplKt.getLOG().isDebugEnabled()) {
SelectInProjectViewImplKt.getLOG().debug("Selected the only path: " + path);
}
return true;
}
protected static boolean selectPaths(@NotNull JTree tree, @NotNull ProjectViewPaneSelectionHelper.SelectionDescriptor selectionDescriptor) {
List<? extends TreePath> adjustedPaths = ProjectViewPaneSelectionHelper.getAdjustedPaths(selectionDescriptor);
adjustedPaths.forEach(it -> tree.expandPath(it));
TreeUtil.selectPaths(tree, adjustedPaths);
if (SelectInProjectViewImplKt.getLOG().isDebugEnabled()) {
SelectInProjectViewImplKt.getLOG().debug("Selected paths adjusted according to " + selectionDescriptor + ": " + adjustedPaths);
}
return true;
}
}