From c8284c96e9af0a90d2ebb7a07b8b34651e1093e2 Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Thu, 18 Jun 2020 10:56:17 +0200 Subject: [PATCH] speed up goto file don't calculate full path from root for each traversed directory, append the relative path from the closest known root instead don't check if the directory has been already visited: roots aren't nested by construction GitOrigin-RevId: 9ca231281cfef261e495bfddbccbae3db0e72450 --- .../ide/actions/DirectoryPathMatcher.java | 79 ++++++++----------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java b/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java index 65a6fcc67270..67a162508c2a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java @@ -20,7 +20,6 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.roots.*; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -46,11 +45,13 @@ class DirectoryPathMatcher { @NotNull private final GotoFileModel myModel; @Nullable private final List> myFiles; @NotNull final String dirPattern; + private final GlobalSearchScope myAllScope; private DirectoryPathMatcher(@NotNull GotoFileModel model, @Nullable List> files, @NotNull String pattern) { myModel = model; myFiles = files; dirPattern = pattern; + myAllScope = GlobalSearchScope.allScope(myModel.getProject()); } @Nullable @@ -72,27 +73,23 @@ class DirectoryPathMatcher { List> nextRoots = new ArrayList<>(); MinusculeMatcher matcher = GotoFileItemProvider.getQualifiedNameMatcher(nextPattern); - List nonMatchingRoots = new ArrayList<>(); for (Pair pair : files) { if (containsChar(pair.second, c) && matcher.matches(pair.second)) { nextRoots.add(pair); } else { - nonMatchingRoots.add(pair.first); + processProjectFilesUnder(pair.first, sub -> { + if (!sub.isDirectory()) return false; + if (!containsChar(sub.getNameSequence(), c)) return true; //go deeper + + String fullName = pair.second + '/' + VfsUtilCore.getRelativePath(sub, pair.first, '/'); + if (matcher.matches(fullName)) { + nextRoots.add(Pair.create(sub, fullName)); + return false; + } + return true; + }); } } - processProjectFilesUnder(nonMatchingRoots, sub -> { - if (!sub.isDirectory()) return false; - if (!containsChar(sub.getNameSequence(), c)) return true; //go deeper - - String fullName = myModel.getFullName(sub); - if (fullName == null) return true; - fullName = FileUtil.toSystemIndependentName(fullName); - if (matcher.matches(fullName)) { - nextRoots.add(Pair.create(sub, fullName)); - return false; - } - return true; - }); return nextRoots.isEmpty() ? null : new DirectoryPathMatcher(myModel, nextRoots, nextPattern); } @@ -104,24 +101,22 @@ class DirectoryPathMatcher { Set names = new HashSet<>(); AtomicInteger counter = new AtomicInteger(); BooleanSupplier tooMany = () -> counter.get() > 1000; - List nonMatchingRoots = new ArrayList<>(); for (Pair pair : files) { if (containsChar(pair.second, nextLetter) && matcher.matches(pair.second)) { names.add(pair.first.getName()); } else { - nonMatchingRoots.add(pair.first); + processProjectFilesUnder(pair.first, sub -> { + counter.incrementAndGet(); + if (tooMany.getAsBoolean()) return false; + + String name = sub.getName(); + if (containsChar(name, nextLetter) && matcher.matches(name)) { + names.add(name); + } + return true; + }); } } - processProjectFilesUnder(nonMatchingRoots, sub -> { - counter.incrementAndGet(); - if (tooMany.getAsBoolean()) return false; - - String name = sub.getName(); - if (containsChar(name, nextLetter) && matcher.matches(name)) { - names.add(name); - } - return true; - }); return tooMany.getAsBoolean() ? null : names; } @@ -139,24 +134,20 @@ class DirectoryPathMatcher { } - private void processProjectFilesUnder(List roots, Processor consumer) { - Set visited = new HashSet<>(roots.size()); - GlobalSearchScope scope = GlobalSearchScope.allScope(myModel.getProject()); - for (VirtualFile root : roots) { - VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() { + private void processProjectFilesUnder(VirtualFile root, Processor consumer) { + VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() { - @Override - public boolean visitFile(@NotNull VirtualFile file) { - return visited.add(file) && scope.contains(file) && consumer.process(file); - } + @Override + public boolean visitFile(@NotNull VirtualFile file) { + return myAllScope.contains(file) && consumer.process(file); + } - @Nullable - @Override - public Iterable getChildrenIterable(@NotNull VirtualFile file) { - return file instanceof NewVirtualFile ? ((NewVirtualFile)file).getCachedChildren() : null; - } - }); - } + @Nullable + @Override + public Iterable getChildrenIterable(@NotNull VirtualFile file) { + return file instanceof NewVirtualFile ? ((NewVirtualFile)file).getCachedChildren() : null; + } + }); } private static boolean containsChar(CharSequence name, char c) {