replace PsiPackage.getChildren(scope) API with PsiPackage.getFiles(scope); use it for coverage and package view

This commit is contained in:
Dmitry Jemerov
2014-12-24 15:31:10 +01:00
parent fc00e89d0e
commit 60b8e7041b
7 changed files with 92 additions and 87 deletions
@@ -28,7 +28,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,9 +95,12 @@ public class PackageElementNode extends ProjectViewNode<PackageElement> {
}
}
// process only files in package's directories
final PsiDirectory[] dirs = PackageUtil.getDirectories(aPackage, module, isLibraryElement());
for (final PsiDirectory dir : dirs) {
children.addAll(ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(dir, getSettings(), false));
final GlobalSearchScope scopeToShow = PackageUtil.getScopeToShow(aPackage.getProject(), module, isLibraryElement());
PsiFile[] packageChildren = aPackage.getFiles(scopeToShow);
for (PsiFile file : packageChildren) {
if (file.getVirtualFile() != null) {
children.add(new PsiFileNode(getProject(), file, getSettings()));
}
}
return children;
}
@@ -23,12 +23,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaDirectoryService;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,23 +35,17 @@ public class PackageUtil {
public static PsiPackage[] getSubpackages(@NotNull PsiPackage aPackage,
@Nullable Module module,
final boolean searchInLibraries) {
final PsiDirectory[] dirs = getDirectories(aPackage, module, searchInLibraries);
final Set<PsiPackage> subpackages = new HashSet<PsiPackage>();
for (PsiDirectory dir : dirs) {
final PsiDirectory[] subdirectories = dir.getSubdirectories();
for (PsiDirectory subdirectory : subdirectories) {
final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(subdirectory);
if (psiPackage != null) {
final String name = psiPackage.getName();
// skip "default" subpackages as they should be attributed to other modules
// this is the case when contents of one module is nested into contents of another
if (name != null && !name.isEmpty()) {
subpackages.add(psiPackage);
}
}
final GlobalSearchScope scopeToShow = getScopeToShow(aPackage.getProject(), module, searchInLibraries);
List<PsiPackage> result = new ArrayList<PsiPackage>();
for (PsiPackage psiPackage : aPackage.getSubPackages(scopeToShow)) {
// skip "default" subpackages as they should be attributed to other modules
// this is the case when contents of one module is nested into contents of another
final String name = psiPackage.getName();
if (name != null && !name.isEmpty()) {
result.add(psiPackage);
}
}
return subpackages.toArray(new PsiPackage[subpackages.size()]);
return result.toArray(new PsiPackage[result.size()]);
}
public static void addPackageAsChild(@NotNull Collection<AbstractTreeNode> children,
@@ -80,13 +70,17 @@ public class PackageUtil {
@Nullable Module module,
boolean strictlyEmpty,
final boolean inLibrary) {
final PsiDirectory[] dirs = getDirectories(aPackage, module, inLibrary);
for (final PsiDirectory dir : dirs) {
if (!TreeViewUtil.isEmptyMiddlePackage(dir, strictlyEmpty)) {
return false;
}
final Project project = aPackage.getProject();
final GlobalSearchScope scopeToShow = getScopeToShow(project, module, inLibrary);
PsiElement[] children = aPackage.getFiles(scopeToShow);
if (children.length > 0) {
return false;
}
return true;
PsiPackage[] subPackages = aPackage.getSubPackages(scopeToShow);
if (strictlyEmpty) {
return subPackages.length == 1;
}
return subPackages.length > 0;
}
@NotNull
@@ -98,7 +92,7 @@ public class PackageUtil {
}
@NotNull
private static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) {
public static GlobalSearchScope getScopeToShow(@NotNull Project project, @Nullable Module module, boolean forLibraries) {
if (module == null) {
if (forLibraries) {
return new ProjectLibrariesSearchScope(project);
@@ -239,7 +233,7 @@ public class PackageUtil {
@Override
public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
throw new IncorrectOperationException("not implemented");
return 0;
}
@Override
@@ -101,33 +101,31 @@ public abstract class PsiElementFinder {
}
/**
* Returns a list of children (classes, subpackages and possibly other elements) belonging to the specified package.
* Returns a list of files belonging to the specified package which are not located in any of the package directories.
*
* @param psiPackage the package to return the list of children for.
* @param scope the scope in which children are searched.
* @return the list of children.
* @param psiPackage the package to return the list of files for.
* @param scope the scope in which files are searched.
* @return the list of files.
* @since 14.1
*/
@NotNull
public PsiNamedElement[] getChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
Set<PsiNamedElement> children = new HashSet<PsiNamedElement>();
Collections.addAll(children, getSubPackages(psiPackage, scope));
Collections.addAll(children, getClasses(psiPackage, scope));
return children.toArray(new PsiNamedElement[children.size()]);
public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
return PsiFile.EMPTY_ARRAY;
}
/**
* Returns the filter to use for filtering the list of children for a given package produced by other PsiElementFinder
* implementations. (For example, the list of children for a Kotlin package includes files directly, rather than classes,
* so the classes located by the standard Java package children finder need to be excluded.)
* Returns the filter to use for filtering the list of files in the directories belonging to a package to exclude files
* that actually belong to a different package. (For example, in Kotlin the package of a file is determined by its
* package statement and not by its location in the directory structure, so the files which have a differring package
* statement need to be excluded.)
*
* @param psiPackage the package to return the list of children for.
* @param scope the scope in which children are searched.
* @param psiPackage the package for which the list of files is requested.
* @param scope the scope in which children are requested.
* @return the filter to use, or null if no additional filtering is necessary.
* @since 14.1
*/
@Nullable
public Predicate<PsiNamedElement> getPackageChildrenFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
public Predicate<PsiFile> getPackageFilesFilter(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
return null;
}
@@ -84,12 +84,13 @@ public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, Psi
PsiClass[] getClasses(@NotNull GlobalSearchScope scope);
/**
* Returns the list of all elements (classes, subpackages and potentially other elements) belonging to this package
* (non-recursively), restricted by the specified scope.
* Returns the list of all files in the package, restricted by the specified scope. (This is
* normally the list of all files in all directories corresponding to the package, but it can
* be modified by custom language plugins which have a different notion of packages.)
*
* @since 14.1
*/
PsiElement[] getChildren(@NotNull GlobalSearchScope scope);
PsiFile[] getFiles(@NotNull GlobalSearchScope scope);
/**
* Returns the list of package-level annotations for the package.
@@ -243,17 +243,17 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]);
}
private static class AndPredicate implements Predicate<PsiNamedElement> {
private final List<Predicate<PsiNamedElement>> myComponents = new SmartList<Predicate<PsiNamedElement>>();
private static class AndPredicate<T> implements Predicate<T> {
private final List<Predicate<T>> myComponents = new SmartList<Predicate<T>>();
public AndPredicate(Predicate<PsiNamedElement> filter1, Predicate<PsiNamedElement> filter2) {
public AndPredicate(Predicate<T> filter1, Predicate<T> filter2) {
myComponents.add(filter1);
myComponents.add(filter2);
}
@Override
public boolean apply(@Nullable PsiNamedElement input) {
for (Predicate<PsiNamedElement> component : myComponents) {
public boolean apply(@Nullable T input) {
for (Predicate<T> component : myComponents) {
if (!component.apply(input)) {
return false;
}
@@ -263,34 +263,38 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
}
@NotNull
public PsiElement[] getPackageChildren(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
Map<String, PsiNamedElement> result = new HashMap<String, PsiNamedElement>();
Predicate<PsiNamedElement> filter = null;
public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
Predicate<PsiFile> filter = null;
for (PsiElementFinder finder : filteredFinders()) {
Predicate<PsiNamedElement> finderFilter = finder.getPackageChildrenFilter(psiPackage, scope);
Predicate<PsiFile> finderFilter = finder.getPackageFilesFilter(psiPackage, scope);
if (finderFilter != null) {
if (filter == null) {
filter = finderFilter;
}
else if (filter instanceof AndPredicate) {
((AndPredicate) filter).myComponents.add(finderFilter);
((AndPredicate<PsiFile>) filter).myComponents.add(finderFilter);
}
else {
filter = new AndPredicate(filter, finderFilter);
filter = new AndPredicate<PsiFile>(filter, finderFilter);
}
}
}
Set<PsiFile> result = new HashSet<PsiFile>();
PsiDirectory[] directories = psiPackage.getDirectories(scope);
for (PsiDirectory directory : directories) {
for (PsiFile file : directory.getFiles()) {
if (filter == null || filter.apply(file)) {
result.add(file);
}
}
}
for (PsiElementFinder finder : filteredFinders()) {
PsiNamedElement[] children = finder.getChildren(psiPackage, scope);
for (PsiNamedElement child : children) {
if (!result.containsKey(child.getName()) && (filter == null || filter.apply(child))) {
result.put(child.getName(), child);
}
}
Collections.addAll(result, finder.getPackageFiles(psiPackage, scope));
}
return result.values().toArray(new PsiElement[result.size()]);
return result.toArray(new PsiFile[result.size()]);
}
public boolean processPackageDirectories(@NotNull PsiPackage psiPackage,
@@ -157,15 +157,9 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
return getFacade().getClasses(this, scope);
}
@NotNull
@Override
public PsiElement[] getChildren() {
return getChildren(allScope());
}
@Override
public PsiElement[] getChildren(@NotNull GlobalSearchScope scope) {
return getFacade().getPackageChildren(this, scope);
public PsiFile[] getFiles(@NotNull GlobalSearchScope scope) {
return getFacade().getPackageFiles(this, scope);
}
@Override
@@ -217,22 +217,31 @@ public class JavaCoverageViewExtension extends CoverageViewExtension {
return isInCoverageScope(psiPackage);
}
})) {
final PsiElement[] childElements = ApplicationManager.getApplication().runReadAction(new Computable<PsiElement[]>() {
public PsiElement[] compute() {
return psiPackage.getChildren(mySuitesBundle.getSearchScope(node.getProject()));
final PsiPackage[] subPackages = ApplicationManager.getApplication().runReadAction(new Computable<PsiPackage[]>() {
public PsiPackage[] compute() {
return psiPackage.getSubPackages(mySuitesBundle.getSearchScope(node.getProject()));
}
});
for (PsiElement element : childElements) {
if (element instanceof PsiClass) {
PsiClass aClass = (PsiClass) element;
if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue;
children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean));
for (PsiPackage subPackage: subPackages) {
processSubPackage(subPackage, children);
}
final PsiFile[] childFiles = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile[]>() {
public PsiFile[] compute() {
return psiPackage.getFiles(mySuitesBundle.getSearchScope(node.getProject()));
}
else if (element instanceof PsiPackage) {
processSubPackage((PsiPackage) element, children);
});
for (PsiFile file : childFiles) {
if (file instanceof PsiJavaFile) {
PsiClass[] classes = ((PsiJavaFile)file).getClasses();
if (classes.length > 0) {
PsiClass aClass = classes[0];
if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue;
children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean));
}
}
else if (element instanceof PsiNamedElement) {
children.add(new CoverageListNode(myProject, (PsiNamedElement) element, mySuitesBundle, myStateBean));
else {
children.add(new CoverageListNode(myProject, file, mySuitesBundle, myStateBean));
}
}
}