correctly report private methods' unusedness (IDEA-75803)

This commit is contained in:
peter
2012-01-31 18:30:25 +01:00
parent adf3dd0815
commit bd365c5cd6
4 changed files with 41 additions and 29 deletions
@@ -30,11 +30,6 @@ public abstract class GlobalUsageHelper {
final Map<PsiClass,Boolean> unusedClassCache = new HashMap<PsiClass, Boolean>();
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();
}
@@ -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;
@@ -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));
}
@@ -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 <warning descr="Method unusedPrivately is unused">unusedPrivately</warning>() {}
}
println new Bar().usedMethod().usedProperty