Use VFS visitor in place of recursion (java)

This commit is contained in:
Roman Shevchenko
2012-08-20 22:34:43 +04:00
parent 3ad72015bf
commit 833d417894
3 changed files with 88 additions and 99 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,16 +20,20 @@ import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class JavaVfsSourceRootDetectionUtil {
private JavaVfsSourceRootDetectionUtil() {}
@@ -37,84 +41,51 @@ public class JavaVfsSourceRootDetectionUtil {
* Scan directory and detect java source roots within it. The source root is detected as the following:
* <ol>
* <li>It contains at least one Java file.</li>
* <li>Java file is located in the subfolder that matches package statement in the file.</li>
* <li>Java file is located in the sub-folder that matches package statement in the file.</li>
* </ol>
*
* @param dir a directory to scan
* @param progressIndicator
* @return a list of found source roots within directory. If no source roots are found, a empty list is returned.
*/
public static List<VirtualFile> suggestRoots(VirtualFile dir, ProgressIndicator progressIndicator) {
ArrayList<VirtualFile> foundDirectories = new ArrayList<VirtualFile>();
try{
suggestRootsImpl(dir, progressIndicator, foundDirectories);
}
catch(PathFoundException ignore){
}
return foundDirectories;
}
private static class PathFoundException extends Exception {
public VirtualFile myDirectory;
public PathFoundException(VirtualFile directory) {
myDirectory = directory;
}
}
private static void suggestRootsImpl(VirtualFile dir,
ProgressIndicator progressIndicator,
ArrayList<? super VirtualFile> foundDirectories) throws PathFoundException {
@NotNull
public static List<VirtualFile> suggestRoots(@NotNull VirtualFile dir, @NotNull final ProgressIndicator progressIndicator) {
if (!dir.isDirectory()) {
return;
}
FileTypeManager typeManager = FileTypeManager.getInstance();
final String dirName = dir.getName();
if (typeManager.isFileIgnored(dir) || StringUtil.startsWithIgnoreCase(dirName, "testdata")) {
return;
}
if (progressIndicator.isCanceled()) {
return;
}
progressIndicator.setText2(dir.getPath());
VirtualFile[] list = dir.getChildren();
if (list == null || list.length == 0) {
return;
return ContainerUtil.emptyList();
}
for (VirtualFile child : list) {
if (!child.isDirectory()) {
FileType type = typeManager.getFileTypeByFileName(child.getName());
if (StdFileTypes.JAVA == type) {
if (progressIndicator.isCanceled()) {
return;
}
final FileTypeManager typeManager = FileTypeManager.getInstance();
final ArrayList<VirtualFile> foundDirectories = new ArrayList<VirtualFile>();
try {
VfsUtilCore.visitChildrenRecursively(dir, new VirtualFileVisitor() {
@NotNull
@Override
public Result visitFileEx(@NotNull VirtualFile file) {
progressIndicator.checkCanceled();
VirtualFile root = suggestRootForJavaFile(child);
if (root != null) {
foundDirectories.add(root);
throw new PathFoundException(root);
if (file.isDirectory()) {
if (typeManager.isFileIgnored(file) || StringUtil.startsWithIgnoreCase(file.getName(), "testData")) {
return SKIP_CHILDREN;
}
}
else {
return;
FileType type = typeManager.getFileTypeByFileName(file.getName());
if (StdFileTypes.JAVA == type) {
VirtualFile root = suggestRootForJavaFile(file);
if (root != null) {
foundDirectories.add(root);
return skipTo(root);
}
}
}
}
}
}
for (VirtualFile child : list) {
if (child.isDirectory()) {
try {
suggestRootsImpl(child, progressIndicator, foundDirectories);
return CONTINUE;
}
catch (PathFoundException found) {
if (!found.myDirectory.equals(child)) {
throw found;
}
}
}
});
}
catch (ProcessCanceledException ignore) { }
return foundDirectories;
}
@Nullable

View File

@@ -1,9 +1,12 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,7 +27,9 @@ import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.*;
import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -75,17 +80,18 @@ public class DefaultLibraryRootsComponentDescriptor extends LibraryRootsComponen
return result;
}
private static void collectJavadocRoots(VirtualFile file, List<VirtualFile> result, ProgressIndicator progressIndicator) {
if (!file.isDirectory()) return;
if (file.findChild("allclasses-frame.html") != null && file.findChild("allclasses-noframe.html") != null) {
result.add(file);
return;
}
progressIndicator.checkCanceled();
for (VirtualFile child : file.getChildren()) {
collectJavadocRoots(child, result, progressIndicator);
}
private static void collectJavadocRoots(VirtualFile file, final List<VirtualFile> result, final ProgressIndicator progressIndicator) {
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
progressIndicator.checkCanceled();
if (file.isDirectory() && file.findChild("allclasses-frame.html") != null && file.findChild("allclasses-noframe.html") != null) {
result.add(file);
return false;
}
return true;
}
});
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,8 +29,11 @@ import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
@@ -182,7 +185,7 @@ public class TreeModelBuilder {
});
for (VirtualFile root : LibraryUtil.getLibraryRoots(project)) {
processFilesRecursively(root, null);
processFilesRecursively(root);
}
}
};
@@ -192,31 +195,39 @@ public class TreeModelBuilder {
return new TreeModel(myRoot, myTotalFileCount, myMarkedFileCount);
}
@Nullable
private PackageDependenciesNode processFilesRecursively(VirtualFile file, @Nullable PackageDependenciesNode parent) {
if (file.isDirectory()) {
VirtualFile[] children = file.getChildren();
PackageDependenciesNode dirNode = null;
for (VirtualFile aChildren : children) {
dirNode = processFilesRecursively(aChildren, dirNode);
private void processFilesRecursively(@NotNull VirtualFile file) {
final Ref<PackageDependenciesNode> parent = Ref.create();
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
if (file.isDirectory()) {
parent.set(null);
}
else {
parent.set(buildFileNode(file, parent.get()));
}
return true;
}
}
else {
return buildFileNode(file, parent);
}
return null;
@Override
public void afterChildrenVisited(@NotNull VirtualFile file) {
if (file.isDirectory()) {
parent.set(null);
}
}
});
}
private void countFilesRecursively(VirtualFile file) {
if (file.isDirectory()) {
VirtualFile[] children = file.getChildren();
for (VirtualFile aChildren : children) {
countFilesRecursively(aChildren);
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
if (!file.isDirectory()) {
counting();
}
return true;
}
}
else {
counting();
}
});
}
private void counting() {
@@ -243,7 +254,8 @@ public class TreeModelBuilder {
};
if (showProgress) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(buildingRunnable, AnalysisScopeBundle.message("package.dependencies.build.process.title"), false, myProject);
final String title = AnalysisScopeBundle.message("package.dependencies.build.process.title");
ProgressManager.getInstance().runProcessWithProgressSynchronously(buildingRunnable, title, false, myProject);
}
else {
buildingRunnable.run();