From bd365c5cd68f5dd8bc96ee1cbf551235af7f5ae8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 31 Jan 2012 13:41:04 +0100 Subject: [PATCH] correctly report private methods' unusedness (IDEA-75803) --- .../daemon/impl/GlobalUsageHelper.java | 9 +--- .../daemon/impl/PostHighlightingPass.java | 41 +++++++++++-------- .../local/GroovyPostHighlightingPass.java | 15 ++++--- .../highlighting/GloballyUnusedSymbols.groovy | 5 ++- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java index 18a363133c01..4f4e3e87c356 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java @@ -30,11 +30,6 @@ public abstract class GlobalUsageHelper { final Map unusedClassCache = new HashMap(); public abstract boolean shouldCheckUsages(@NotNull PsiMember member); - public boolean isLocallyUsed(@NotNull PsiNamedElement member) { - return false; - } - - public boolean shouldIgnoreUsagesInCurrentFile() { - return false; - } + public abstract boolean isLocallyUsed(@NotNull PsiNamedElement member); + public abstract boolean shouldIgnoreUsagesInCurrentFile(); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 531bc286acfd..6ab7b118c92f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -260,9 +260,14 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { return true; } + @Override + public boolean shouldIgnoreUsagesInCurrentFile() { + return true; + } + @Override public boolean isLocallyUsed(@NotNull PsiNamedElement member) { - return myRefCountHolder.isReferenced(myFile); + return myRefCountHolder.isReferenced(member); } }; @@ -390,7 +395,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { return UnusedSymbolLocalInspection.isInjected(element); } - public static HighlightInfo createUnusedSymbolInfo(PsiElement element, String message, final HighlightInfoType highlightInfoType) { + public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @Nullable String message, @NotNull final HighlightInfoType highlightInfoType) { HighlightInfo info = HighlightInfo.createHighlightInfo(highlightInfoType, element, message); UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME); for (UnusedDeclarationFixProvider provider : fixProviders) { @@ -580,6 +585,9 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { if (isImplicitUsage(method, progress)) { return true; } + if (!helper.shouldIgnoreUsagesInCurrentFile()) { + return !weAreSureThereAreNoUsages(method, progress, helper); + } } else { //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too @@ -606,26 +614,27 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { String name = member.getName(); if (name == null) return false; SearchScope useScope = member.getUseScope(); - if (!(useScope instanceof GlobalSearchScope)) return false; - GlobalSearchScope scope = (GlobalSearchScope)useScope; - // some classes may have references from within XML outside dependent modules, e.g. our actions Project project = member.getProject(); - if (member instanceof PsiClass) scope = GlobalSearchScope.projectScope(project).uniteWith(scope); + if (useScope instanceof GlobalSearchScope) { + GlobalSearchScope scope = (GlobalSearchScope)useScope; + // some classes may have references from within XML outside dependent modules, e.g. our actions + if (member instanceof PsiClass) scope = GlobalSearchScope.projectScope(project).uniteWith(scope); - PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(project).isCheapEnoughToSearch(name, scope, - helper.shouldIgnoreUsagesInCurrentFile() ? member.getContainingFile() : null, - progress); - if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false; + PsiSearchHelper.SearchCostResult cheapEnough = PsiSearchHelper.SERVICE.getInstance(project).isCheapEnoughToSearch(name, scope, + helper.shouldIgnoreUsagesInCurrentFile() ? member.getContainingFile() : null, + progress); + if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false; - //search usages if it cheap - //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before - if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) { - if (!canBeReferencedViaWeirdNames(member)) return true; + //search usages if it cheap + //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before + if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) { + if (!canBeReferencedViaWeirdNames(member)) return true; + } } FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project)); FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions(); - findUsagesOptions.searchScope = scope; + findUsagesOptions.searchScope = useScope; return !findUsagesManager.isUsed(member, findUsagesOptions); } @@ -684,7 +693,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { if (aClass == null) return true; Boolean result = helper.unusedClassCache.get(aClass); if (result == null) { - result = !isReallyUsed(aClass, progress, helper); + result = isReallyUsed(aClass, progress, helper); helper.unusedClassCache.put(aClass, result); } return result; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java index 49c4c67fcec4..7476a4ed4648 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java @@ -39,10 +39,7 @@ import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiMember; -import com.intellij.psi.PsiRecursiveElementWalkingVisitor; +import com.intellij.psi.*; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; @@ -90,6 +87,14 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } final UnusedDeclarationInspection deadCodeInspection = (UnusedDeclarationInspection)profile.getInspectionTool(UnusedDeclarationInspection.SHORT_NAME, myFile); final GlobalUsageHelper usageHelper = new GlobalUsageHelper() { + public boolean shouldIgnoreUsagesInCurrentFile() { + return false; + } + + public boolean isLocallyUsed(@NotNull PsiNamedElement member) { + return false; + } + @Override public boolean shouldCheckUsages(@NotNull PsiMember member) { return deadCodeInspection == null || !deadCodeInspection.isEntryPoint(member); @@ -115,7 +120,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy(); if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) { String name = ((GrNamedElement)element).getName(); - if (element instanceof GrTypeDefinition && PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) { + if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) { unusedDeclarations.add( PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL)); } diff --git a/plugins/groovy/testdata/highlighting/GloballyUnusedSymbols.groovy b/plugins/groovy/testdata/highlighting/GloballyUnusedSymbols.groovy index 5ad85a2c8f6b..af47b7500098 100644 --- a/plugins/groovy/testdata/highlighting/GloballyUnusedSymbols.groovy +++ b/plugins/groovy/testdata/highlighting/GloballyUnusedSymbols.groovy @@ -10,7 +10,10 @@ class Bar { Bar getUsedPropertyGetter() {} - public static void main(String[] args) {} + public static void main(String[] args) { usedPrivately() } + + private static void usedPrivately() {} + private void unusedPrivately() {} } println new Bar().usedMethod().usedProperty