diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java new file mode 100644 index 000000000000..7e01b42b5219 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java @@ -0,0 +1,129 @@ +package com.intellij.psi; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.impl.PsiManagerEx; +import com.intellij.psi.impl.file.PsiPackageImpl; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author peter + */ +public abstract class NonClasspathClassFinder extends PsiElementFinder { + protected final Project myProject; + + public NonClasspathClassFinder(Project project) { + myProject = project; + } + + @Override + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + final List classRoots = getClassRoots(); + if (classRoots.isEmpty()) { + return null; + } + + for (final VirtualFile classRoot : classRoots) { + if (scope.contains(classRoot)) { + final VirtualFile classFile = classRoot.findFileByRelativePath(qualifiedName.replace('.', '/') + ".class"); + if (classFile != null) { + final PsiFile file = PsiManager.getInstance(myProject).findFile(classFile); + if (file instanceof PsiClassOwner) { + final PsiClass[] classes = ((PsiClassOwner)file).getClasses(); + if (classes.length == 1) { + return classes[0]; + } + } + } + } + } + return null; + } + + protected abstract List getClassRoots(); + + @NotNull + @Override + public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + final List classRoots = getClassRoots(); + if (classRoots.isEmpty()) { + return PsiClass.EMPTY_ARRAY; + } + + List result = new ArrayList(); + for (final VirtualFile classRoot : classRoots) { + if (scope.contains(classRoot)) { + final String pkgName = psiPackage.getName(); + final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot; + if (dir != null && dir.isDirectory()) { + for (final VirtualFile file : dir.getChildren()) { + if (!file.isDirectory()) { + final PsiFile psi = PsiManager.getInstance(myProject).findFile(file); + if (psi instanceof PsiClassOwner) { + result.addAll(Arrays.asList(((PsiClassOwner)psi).getClasses())); + } + } + } + } + } + } + return result.toArray(new PsiClass[result.size()]); + } + + @Override + public PsiPackage findPackage(@NotNull String qualifiedName) { + final List classRoots = getClassRoots(); + if (classRoots.isEmpty()) { + return null; + } + + for (final VirtualFile classRoot : classRoots) { + final VirtualFile dir = classRoot.findFileByRelativePath(qualifiedName.replace('.', '/')); + if (dir != null && dir.isDirectory()) { + return createPackage(qualifiedName); + } + } + return null; + } + + private PsiPackageImpl createPackage(String qualifiedName) { + return new PsiPackageImpl((PsiManagerEx)PsiManager.getInstance(myProject), qualifiedName); + } + + @NotNull + @Override + public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + final List classRoots = getClassRoots(); + if (classRoots.isEmpty()) { + return super.getSubPackages(psiPackage, scope); + } + + List result = new ArrayList(); + for (final VirtualFile classRoot : classRoots) { + if (scope.contains(classRoot)) { + final String pkgName = psiPackage.getName(); + final VirtualFile dir = pkgName != null ? classRoot.findFileByRelativePath(pkgName.replace('.', '/')) : classRoot; + if (dir != null && dir.isDirectory()) { + for (final VirtualFile file : dir.getChildren()) { + if (file.isDirectory()) { + result.add(createPackage(pkgName + "." + file.getName())); + } + } + } + } + } + return result.toArray(new PsiPackage[result.size()]); + } + + @NotNull + @Override + public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + final PsiClass psiClass = findClass(qualifiedName, scope); + return psiClass == null ? PsiClass.EMPTY_ARRAY : new PsiClass[]{psiClass}; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/search/NonClasspathDirectoryScope.java b/platform/lang-api/src/com/intellij/psi/search/NonClasspathDirectoryScope.java new file mode 100644 index 000000000000..14d6af432036 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/search/NonClasspathDirectoryScope.java @@ -0,0 +1,37 @@ +package com.intellij.psi.search; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class NonClasspathDirectoryScope extends GlobalSearchScope { + private final VirtualFile myRoot; + + public NonClasspathDirectoryScope(@NotNull VirtualFile root) { + myRoot = root; + } + + @Override + public boolean contains(VirtualFile file) { + return VfsUtil.isAncestor(myRoot, file, false); + } + + @Override + public int compare(VirtualFile file1, VirtualFile file2) { + return 0; + } + + @Override + public boolean isSearchInModuleContent(@NotNull Module aModule) { + return false; + } + + @Override + public boolean isSearchInLibraries() { + return false; + } +}