mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-217146: TreePathUtil.findCommonAncestor instead of TreeUtil.findCommonPath
GitOrigin-RevId: c6ac5856abca27ef400519a0fc2b93dbd0eb43e1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
626a7639b9
commit
0ccf179744
@@ -57,7 +57,6 @@ import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.intellij.codeInspection.CommonProblemDescriptor.DESCRIPTOR_COMPARATOR;
|
||||
import static com.intellij.ui.tree.TreePathUtil.toTreePathArray;
|
||||
|
||||
public class InspectionTree extends Tree {
|
||||
private static final Logger LOG = Logger.getInstance(InspectionTree.class);
|
||||
@@ -145,9 +144,8 @@ public class InspectionTree extends Tree {
|
||||
|
||||
@Nullable
|
||||
public String[] getSelectedGroupPath() {
|
||||
final TreePath[] paths = getSelectionPaths();
|
||||
if (paths == null) return null;
|
||||
final TreePath commonPath = TreeUtil.findCommonPath(paths);
|
||||
TreePath commonPath = TreePathUtil.findCommonAncestor(getSelectionPaths());
|
||||
if (commonPath == null) return null;
|
||||
for (Object n : commonPath.getPath()) {
|
||||
if (n instanceof InspectionGroupNode) {
|
||||
return getGroupPath((InspectionGroupNode)n);
|
||||
@@ -458,7 +456,8 @@ public class InspectionTree extends Tree {
|
||||
for (InspectionTreeNode parent : parents) {
|
||||
parent.dropProblemCountCaches();
|
||||
}
|
||||
TreeUtil.selectPath(this, TreeUtil.findCommonPath(toTreePathArray(pathsToSelect)));
|
||||
TreePath commonPath = TreePathUtil.findCommonAncestor(pathsToSelect);
|
||||
if (commonPath != null) TreeUtil.selectPath(this, commonPath);
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
|
||||
@@ -282,7 +282,12 @@ public final class TreeUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use TreePathUtil#findCommonAncestor(TreePath...) instead
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2020.2")
|
||||
public static TreePath findCommonPath(@NotNull final TreePath[] treePaths) {
|
||||
LOG.assertTrue(areComponentsEqual(treePaths, 0));
|
||||
TreePath result = new TreePath(treePaths[0].getPathComponent(0));
|
||||
|
||||
@@ -192,6 +192,7 @@ public class TreePathUtil {
|
||||
return object == null ? null : converter.apply(object);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TreePath[] toTreePathArray(@NotNull Collection<TreePath> collection) {
|
||||
return collection.isEmpty() ? EMPTY_TREE_PATH : collection.toArray(EMPTY_TREE_PATH);
|
||||
}
|
||||
@@ -213,4 +214,38 @@ public class TreePathUtil {
|
||||
public static TreePath[] toTreePaths(TreeNode... nodes) {
|
||||
return nodes == null ? null : Stream.of(nodes).map(TreePathUtil::toTreePath).filter(Objects::nonNull).toArray(TreePath[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param paths an array of tree paths to iterate through
|
||||
* @return a common ancestor for the given paths, or {@code null} if these paths do not have one
|
||||
*/
|
||||
public static TreePath findCommonAncestor(TreePath... paths) {
|
||||
if (ArrayUtil.isEmpty(paths)) return null;
|
||||
if (paths.length == 1) return paths[0];
|
||||
return findCommonAncestor(Arrays.asList(paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param paths a collection of tree paths to iterate through
|
||||
* @return a common ancestor for the given paths, or {@code null} if these paths do not have one
|
||||
*/
|
||||
public static TreePath findCommonAncestor(@NotNull Iterable<? extends TreePath> paths) {
|
||||
TreePath ancestor = null;
|
||||
for (int i = 0; i < Integer.MAX_VALUE; i++) {
|
||||
TreePath first = null;
|
||||
for (TreePath path : paths) {
|
||||
int count = path.getPathCount();
|
||||
if (count <= i) return ancestor; // a path is too short
|
||||
while (--count > i) path = path.getParentPath();
|
||||
if (path == null) throw new IllegalStateException("unexpected");
|
||||
if (first == null) first = path; // initialize with the first path in the given collection
|
||||
if (first != path && !Objects.equals(first.getLastPathComponent(), path.getLastPathComponent())) {
|
||||
return ancestor; // different components at the current index
|
||||
}
|
||||
}
|
||||
if (first == null) return ancestor; // nothing to iterate
|
||||
ancestor = createTreePath(ancestor, first.getLastPathComponent());
|
||||
}
|
||||
return ancestor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
package com.intellij.ui.tree;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -9,13 +11,10 @@ import javax.swing.tree.TreePath;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.intellij.util.TimeoutUtil.measureExecutionTime;
|
||||
import static com.intellij.util.TimeoutUtil.sleep;
|
||||
import static com.intellij.util.ui.tree.TreeUtil.selectMaximals;
|
||||
|
||||
public class TreeCollectorTest {
|
||||
private static final TreePath ROOT = new TreePath("root");
|
||||
private static final TreePath PARENT1 = ROOT.pathByAddingChild("parent1");
|
||||
@@ -170,18 +169,43 @@ public class TreeCollectorTest {
|
||||
public static final class Slow {
|
||||
private static final IntFunction<Object> SLOW = Slow::new;
|
||||
private static final IntFunction<Object> FAST = Integer::toString;
|
||||
private static final Consumer<TreePath[]> SELECT_MAXIMALS = paths -> {
|
||||
measureExecutionTime("selectMaximals", () -> TreeUtil.selectMaximals(paths));
|
||||
measureExecutionTime("collectRoots", () -> TreeCollector.TreePathRoots.collect(paths));
|
||||
measureExecutionTime("collectLeafs", () -> TreeCollector.TreePathLeafs.collect(paths));
|
||||
Assert.assertArrayEquals(TreeUtil.selectMaximals(paths), TreePathUtil.toTreePathArray(TreeCollector.TreePathRoots.collect(paths)));
|
||||
};
|
||||
private static final Consumer<TreePath[]> FIND_COMMON_PATH = paths -> {
|
||||
measureExecutionTime("findCommonPath", () -> TreeUtil.findCommonPath(paths));
|
||||
measureExecutionTime("findCommonAncestor", () -> TreePathUtil.findCommonAncestor(paths));
|
||||
Assert.assertEquals(TreePathUtil.findCommonAncestor(paths), TreePathUtil.findCommonAncestor(paths));
|
||||
};
|
||||
|
||||
// manual performance test
|
||||
public static void main(String[] args) {
|
||||
testPaths(FAST, 7, 7);
|
||||
testPaths(FAST, 1, 7);
|
||||
testPaths(SLOW, 1, 1);
|
||||
testPaths(SLOW, 1, 2);
|
||||
testPaths(SLOW, 1, 3);
|
||||
testPaths(SLOW, 1, 4);
|
||||
testPaths(SLOW, 2, 4);
|
||||
testPaths(SLOW, 3, 4);
|
||||
testPaths(SLOW, 4, 4);
|
||||
testPaths(FIND_COMMON_PATH, FAST, 10, 10);
|
||||
testPaths(FIND_COMMON_PATH, FAST, 1, 10);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 1);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 2);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 3);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 4);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 5);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 1, 6);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 2, 6);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 3, 6);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 4, 6);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 5, 6);
|
||||
testPaths(FIND_COMMON_PATH, SLOW, 6, 6);
|
||||
|
||||
testPaths(SELECT_MAXIMALS, FAST, 7, 7);
|
||||
testPaths(SELECT_MAXIMALS, FAST, 1, 7);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 1, 1);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 1, 2);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 1, 3);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 1, 4);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 2, 4);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 3, 4);
|
||||
testPaths(SELECT_MAXIMALS, SLOW, 4, 4);
|
||||
}
|
||||
|
||||
private static void addPaths(IntFunction<Object> function, int min, int max, List<TreePath> list, TreePath path) {
|
||||
@@ -194,25 +218,23 @@ public class TreeCollectorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static void testPaths(IntFunction<Object> function, int min, int max) {
|
||||
private static void testPaths(Consumer<TreePath[]> consumer, IntFunction<Object> function, int min, int max) {
|
||||
List<TreePath> list = new ArrayList<>();
|
||||
addPaths(function, min, max, list, null);
|
||||
System.err.println();
|
||||
System.err.println(list.size() + " paths with count from " + min + " to " + max);
|
||||
testPaths(list, "1. ordered");
|
||||
System.err.println("1. ordered list:");
|
||||
consumer.accept(TreePathUtil.toTreePathArray(list));
|
||||
Collections.reverse(list);
|
||||
testPaths(list, "2. reversed");
|
||||
System.err.println("2. reversed list:");
|
||||
consumer.accept(TreePathUtil.toTreePathArray(list));
|
||||
Collections.shuffle(list);
|
||||
testPaths(list, "3. shuffled");
|
||||
System.err.println("3. shuffled list:");
|
||||
consumer.accept(TreePathUtil.toTreePathArray(list));
|
||||
}
|
||||
|
||||
private static void testPaths(List<TreePath> list, String description) {
|
||||
TreePath[] paths = TreePathUtil.toTreePathArray(list);
|
||||
System.err.println(description + " list:");
|
||||
System.err.println(String.format("%,12d ms to selectMaximals", measureExecutionTime(() -> selectMaximals(paths))));
|
||||
System.err.println(String.format("%,12d ms to collectRoots", measureExecutionTime(() -> TreeCollector.TreePathRoots.collect(paths))));
|
||||
System.err.println(String.format("%,12d ms to collectLeafs", measureExecutionTime(() -> TreeCollector.TreePathLeafs.collect(paths))));
|
||||
Assert.assertArrayEquals(selectMaximals(paths), TreePathUtil.toTreePathArray(TreeCollector.TreePathRoots.collect(paths)));
|
||||
private static void measureExecutionTime(String method, Runnable runnable) {
|
||||
System.err.println(String.format("%,12d ms to " + method, TimeoutUtil.measureExecutionTime(runnable::run)));
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +256,7 @@ public class TreeCollectorTest {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
sleep(1); // simulate slow comparison
|
||||
TimeoutUtil.sleep(1); // simulate slow comparison
|
||||
return object instanceof Slow && ((Slow)object).id == id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,4 +210,42 @@ public class TreePathUtilTest {
|
||||
private static void makeDeepTreeFromNode(TreeNode node, int count) {
|
||||
while (1 < count) node = node(--count, node);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCommonAncestor() {
|
||||
TreePath path = TreePathUtil.convertArrayToTreePath("root", "parent");
|
||||
Assert.assertEquals(path, TreePathUtil.findCommonAncestor(
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "one", "child", "one"),
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "one", "child", "two"),
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "two", "child", "one"),
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "two", "child", "two")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCommonAncestorWithParent() {
|
||||
TreePath path = TreePathUtil.convertArrayToTreePath("root", "parent", "child");
|
||||
Assert.assertEquals(path, TreePathUtil.findCommonAncestor(
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "child", "one"),
|
||||
TreePathUtil.convertArrayToTreePath("root", "parent", "child", "two"),
|
||||
path));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCommonAncestorSingle() {
|
||||
TreePath path = TreePathUtil.convertArrayToTreePath("root", "parent", "child");
|
||||
Assert.assertEquals(path, TreePathUtil.findCommonAncestor(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCommonAncestorEmpty() {
|
||||
Assert.assertNull(TreePathUtil.findCommonAncestor());
|
||||
Assert.assertNull(TreePathUtil.findCommonAncestor((TreePath)null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCommonAncestorWrong() {
|
||||
Assert.assertNull(TreePathUtil.findCommonAncestor(
|
||||
TreePathUtil.convertArrayToTreePath("one", "root"),
|
||||
TreePathUtil.convertArrayToTreePath("two", "root")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user