Find all PsiClasses in Project?

Answered

How to find all PsiClasses in the currently opened project? Currently I am using

Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance()
.getContainingFiles(
FileTypeIndex.NAME,
JavaFileType.INSTANCE,
GlobalSearchScope.projectScope(myProject));

to retrive all the files in the project, then iterate over the files to get PsiFile from them and after that extract the PsiClasses. This works but is extremely slow. Is there a straightforward way to do this?

0
6 comments
Avatar
Permanently deleted user

Hey Jakub,

 

I tried like this:

List<String> classes = new ArrayList<>();
PsiShortNamesCache.getInstance(myProject).processAllClassNames(s -> {
classes.add(s);
return true;
}, GlobalSearchScope.projectScope(myProject), IdFilter.getProjectIdFilter(myProject, false));

but it returns 22k classes while my project only has 10 classes. And a lot of classes have really strange names, I think not even my dependencies contain such classes.

 

Update: I even tried with

AllClassesSearch.search(GlobalSearchScope.projectScope(myProject), myProject).allowParallelProcessing().forEach(psiClass -> {
patterns.add(psiClass.getQualifiedName());
return true;
});

but it is even slower(tried it with allowParallelProcessing() and without it)

0

Norbi - sorry for that. Please try with your initial solution but pass a custom scope, like:

class MyGlobalSearchScope extends GlobalSearchScope {
private ProjectFileIndex index;

public MyGlobalSearchScope(@Nullable Project project) {
super(project);
this.index = ProjectRootManager.getInstance(project).getFileIndex();
}

@Override
public boolean isSearchInModuleContent(@NotNull Module aModule) {
return false;
}

@Override
public boolean isSearchInLibraries() {
return false;
}

@Override
public boolean contains(@NotNull VirtualFile file) {
return index.isInSourceContent(file);
}
}

 

0
Avatar
Permanently deleted user

Thank you! Unfortunately I am still seeing the same 22k classes returned. What is strange is that if I put a breakpoint in the isSearchInModuleContent(), isSearchInLibraries() and contains() methods, none of them is called.
These strange class names are included like: Newline, ExplicitCallForClosureParameter_after, testFilterInit, All, NewExpression, FromStringWithGenericPlaceholderFromClass, InferClassParameter8 etc. 

All these classes seem to come from Intellij itself.

My complete code:

List<String> classes = new ArrayList<>();
PsiShortNamesCache.getInstance(myProject).processAllClassNames(s -> {
classes.add(s);
return true;
}, new OnlyProjectSearchScope(myProject), IdFilter.getProjectIdFilter(myProject, false));
class OnlyProjectSearchScope extends GlobalSearchScope {
private ProjectFileIndex index;

public OnlyProjectSearchScope(Project project) {
super(project);
this.index = ProjectRootManager.getInstance(project).getFileIndex();
}

@Override
public boolean isSearchInModuleContent(Module aModule) {
return false;
}

@Override
public boolean isSearchInLibraries() {
return false;
}

@Override
public boolean contains(@NotNull VirtualFile file) {
return index.isInSourceContent(file);
}
}

 

Update: or are you referring to my initial solution in the question itself:

Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance()
.getContainingFiles(
FileTypeIndex.NAME,
JavaFileType.INSTANCE,
GlobalSearchScope.projectScope(myProject));

?
I measured the execution time and what I found is that this call is not the culprit for the slowness. The slowness comes from extracting PsiClasses from the PsiFile(the call to psiJavaFile.getClasses() takes 7 seconds in my project while everything else takes only 2 seconds)

for (VirtualFile virtualFile : containingFiles) {
PsiFile psiFile = PsiManager.getInstance(myProject).findFile(virtualFile);
if (psiFile instanceof PsiJavaFile) {
PsiJavaFile psiJavaFile = (PsiJavaFile) psiFile;
PsiClass[] javaFileClasses = psiJavaFile.getClasses();

for (PsiClass javaFileClass : javaFileClasses) {
classes.add(javaFileClass.getQualifiedName());
}
}
}
0

But did you swap

GlobalSearchScope.projectScope(myProject)

with MyGlobalSearchScope instance I've posted above? The point is to limit the search results to the Java files that satisfy isInSourceContent condition.

0
Avatar
Permanently deleted user

Oh, you're right, sorry. It reduced the time from 8.5s to 1.5s which is excellent. Thank you very much for your help!

0

Keep in mind that you still can enhance your contains filter for better results.

1

Please sign in to leave a comment.