diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/RefCountHolder.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/RefCountHolder.java index a12b62a69671..8c7c5b5033f2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/RefCountHolder.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/RefCountHolder.java @@ -34,8 +34,7 @@ import com.intellij.psi.util.PsiMatcherImpl; import com.intellij.psi.util.PsiMatchers; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtilRt; -import com.intellij.util.containers.MultiMap; -import com.intellij.util.containers.Predicate; +import com.intellij.util.containers.*; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -43,10 +42,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.Reference; import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; class RefCountHolder { @@ -119,25 +115,39 @@ class RefCountHolder { VirtualFile virtualFile = viewProvider.getVirtualFile(); boolean inLibrary = fileIndex.isInLibrary(virtualFile); - boolean myDeadCodeEnabled = deadCodeInspection != null && isUnusedToolEnabled && deadCodeInspection.isGlobalEnabledInEditor(); - Predicate myIsEntryPointPredicate = (@NotNull PsiElement member) -> !myDeadCodeEnabled || deadCodeInspection.isEntryPoint(member); + boolean isDeadCodeEnabled = deadCodeInspection != null && isUnusedToolEnabled && deadCodeInspection.isGlobalEnabledInEditor(); + if (isDeadCodeEnabled && !inLibrary) { + return new GlobalUsageHelperBase() { + Map myEntryPointCache; + { + myEntryPointCache = FactoryMap.create((PsiMember member) -> { + if (isEntryPoint(member)) return true; + if (member instanceof PsiClass) { + return !JBTreeTraverser + .from(m -> m instanceof PsiClass + ? JBIterable.from(PsiTreeUtil.getStubChildrenOfTypeAsList(m, PsiMember.class)) + : JBIterable.empty()) + .withRoot(member) + .traverse() + .skip(1) + .processEach(m -> !myEntryPointCache.get(m)); + } + return false; + }); + } - return new GlobalUsageHelper() { - @Override - public boolean shouldCheckUsages(@NotNull PsiMember member) { - return !inLibrary && !myIsEntryPointPredicate.apply(member); - } + @Override + public boolean shouldCheckUsages(@NotNull PsiMember member) { + return !myEntryPointCache.get(member); + } - @Override - public boolean isCurrentFileAlreadyChecked() { - return true; - } - - @Override - public boolean isLocallyUsed(@NotNull PsiNamedElement member) { - return isReferenced(member); - } - }; + private boolean isEntryPoint(@NotNull PsiElement element) { + return deadCodeInspection.isEntryPoint(element); + } + }; + } else { + return new GlobalUsageHelperBase(); + } } private void clear() { @@ -371,4 +381,21 @@ class RefCountHolder { private static void log(@NonNls @NotNull Object... info) { FileStatusMap.log(info); } + + private class GlobalUsageHelperBase extends GlobalUsageHelper { + @Override + public boolean shouldCheckUsages(@NotNull PsiMember member) { + return false; + } + + @Override + public boolean isCurrentFileAlreadyChecked() { + return true; + } + + @Override + public boolean isLocallyUsed(@NotNull PsiNamedElement member) { + return isReferenced(member); + } + } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index fe0369d1936a..ee04ea4fd307 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -125,8 +125,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { point.registerExtension(extension); infos = doHighlighting(HighlightSeverity.WARNING); - HighlightInfo info = assertOneElement(infos); - assertEquals("Class 'WithMain' is never used", info.getDescription()); + assertEmpty(infos); } finally { point.unregisterExtension(extension);