From a95a5c1afec588a533c6e4d9979a44963b877421 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Jul 2016 19:28:28 +0200 Subject: [PATCH] "test stub hierarchy" action should find non-indexed classes in files reported as 'covered' --- .../impl/SingleClassHierarchy.java | 13 +++-- .../impl/test/TestStubHierarchyAction.java | 53 +++++++++++++++++-- .../psi/stubsHierarchy/ClassHierarchy.java | 4 ++ 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SingleClassHierarchy.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SingleClassHierarchy.java index e148321511fb..bffe473fee6c 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SingleClassHierarchy.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/SingleClassHierarchy.java @@ -26,6 +26,7 @@ import com.intellij.psi.stubsHierarchy.impl.Symbol.ClassSymbol; import com.intellij.util.containers.ContainerUtil; import org.apache.commons.lang.ArrayUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.BitSet; @@ -112,13 +113,17 @@ public class SingleClassHierarchy extends ClassHierarchy { @NotNull @Override public SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull PsiClass psiClass) { - VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); - if (!(vFile instanceof VirtualFileWithId)) return StubClassAnchor.EMPTY_ARRAY; - - SmartClassAnchor anchor = forPsiClass(((VirtualFileWithId)vFile).getId(), psiClass); + SmartClassAnchor anchor = findAnchor(psiClass); return anchor == null ? StubClassAnchor.EMPTY_ARRAY : getDirectSubtypeCandidates(anchor); } + @Override + @Nullable + public SmartClassAnchor findAnchor(@NotNull PsiClass psiClass) { + VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); + return vFile instanceof VirtualFileWithId ? forPsiClass(((VirtualFileWithId)vFile).getId(), psiClass) : null; + } + @NotNull @Override public SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull SmartClassAnchor anchor) { diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java index 2e6566479c91..d5af5482bd4f 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java @@ -23,13 +23,22 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.PsiFileWithStubSupport; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubTree; import com.intellij.psi.stubsHierarchy.ClassHierarchy; import com.intellij.psi.stubsHierarchy.HierarchyService; import com.intellij.psi.stubsHierarchy.SmartClassAnchor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.util.indexing.FileBasedIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,14 +81,48 @@ public class TestStubHierarchyAction extends InheritanceAction { } private void compareSupers(ProgressIndicator indicator, MultiMap supers, ClassHierarchy hierarchy) { - List anchors = hierarchy.getCoveredClasses(); - for (int i = 0; i < anchors.size(); i++) { - indicator.setFraction(i * 1.0 / anchors.size()); - SmartClassAnchor anchor = anchors.get(i); - compareSupers(anchor, supers.get(anchor)); + List covered = getCoveredFiles(indicator, hierarchy); + for (int i = 0; i < covered.size(); i++) { + indicator.setFraction(i * 1.0 / covered.size()); + checkFile(supers, hierarchy, covered.get(i)); } } + private void checkFile(MultiMap supers, ClassHierarchy hierarchy, VirtualFile vFile) { + for (StubElement element : getStubTree(vFile).getPlainListFromAllRoots()) { + Object psi = element.getPsi(); + if (psi instanceof PsiClass && !(psi instanceof PsiTypeParameter)) { + SmartClassAnchor anchor = hierarchy.findAnchor((PsiClass)psi); + if (anchor == null) { + throw new AssertionError("Class not indexed: " + psi + " in " + vFile); + } + compareSupers(anchor, supers.get(anchor)); + } + } + } + + @NotNull + private List getCoveredFiles(ProgressIndicator indicator, ClassHierarchy hierarchy) { + GlobalSearchScope allScope = GlobalSearchScope.allScope(myProject); + GlobalSearchScope uncovered = hierarchy.restrictToUncovered(allScope); + List covered = new ArrayList<>(); + FileBasedIndex.getInstance().iterateIndexableFiles(file -> { + if (!file.isDirectory() && allScope.contains(file) && !uncovered.contains(file)) { + covered.add(file); + } + return true; + }, myProject, indicator); + return covered; + } + + @NotNull + private StubTree getStubTree(VirtualFile vFile) { + PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport)PsiManager.getInstance(myProject).findFile(vFile); + assert psiFile != null : "No PSI for " + vFile; + StubTree stubTree = psiFile.getStubTree(); + return stubTree != null ? stubTree : ((PsiFileImpl)psiFile).calcStubTree(); + } + private void compareSupers(final SmartClassAnchor anchor, final Collection superAnchors) { PsiClass subClass = anchor.retrieveClass(myProject); List stubSuperList = ContainerUtil.map(superAnchors, (anchor1) -> anchor1.retrieveClass(myProject)); diff --git a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/ClassHierarchy.java b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/ClassHierarchy.java index 2a2cbcc6d110..00337e7d084e 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/ClassHierarchy.java +++ b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/ClassHierarchy.java @@ -18,6 +18,7 @@ package com.intellij.psi.stubsHierarchy; import com.intellij.psi.PsiClass; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -43,6 +44,9 @@ public abstract class ClassHierarchy { @NotNull public abstract SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull SmartClassAnchor anchor); + @Nullable + public abstract SmartClassAnchor findAnchor(@NotNull PsiClass psiClass); + /** * @return whether stub hierarchy resolver couldn't determine the super class exactly because there were several possible candidates */