do not highlight enum constants as unused when values are used (IDEA-65298 )

This commit is contained in:
anna
2011-06-15 14:51:09 +04:00
parent dd59a46431
commit 765d5e4f01
8 changed files with 107 additions and 2 deletions
@@ -61,6 +61,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.jsp.JspSpiUtil;
@@ -542,12 +543,32 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
//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 && !canbeReferencedViaWeirdNames(member)) return true;
if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
if (member instanceof PsiEnumConstant) {
return checkEnumValuesUsages(member, progress);
}
if (!canbeReferencedViaWeirdNames(member)) return true;
}
Query<PsiReference> query = member instanceof PsiMethod
? MethodReferencesSearch.search((PsiMethod)member, scope, true)
: ReferencesSearch.search(member, scope, true);
return query.findFirst() == null;
final PsiReference first = query.findFirst();
if (first == null && member instanceof PsiEnumConstant) {
return checkEnumValuesUsages(member, progress);
}
return first == null;
}
private boolean checkEnumValuesUsages(PsiMember member, ProgressIndicator progress) {
final PsiClassImpl containingClass = (PsiClassImpl)member.getContainingClass();
if (containingClass != null) {
final PsiMethod valuesMethod = containingClass.getValuesMethod();
if (valuesMethod != null && weAreSureThereAreNoUsages(valuesMethod, progress)) {
return true;
}
}
return false;
}
private static boolean canbeReferencedViaWeirdNames(PsiMember member) {
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Iconable;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IconUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -231,6 +232,21 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa
}
addOutReference(refWhat);
((RefJavaElementImpl)refWhat).markReferenced(this, psiFrom, psiWhat, forWriting, forReading, expression);
} else {
if (psiWhat instanceof PsiMethod) {
final PsiClass containingClass = ((PsiMethod)psiWhat).getContainingClass();
if (containingClass != null && containingClass.isEnum() && "values".equals(((PsiMethod)psiWhat).getName())) {
for (PsiField enumConstant : containingClass.getFields()) {
if (enumConstant instanceof PsiEnumConstant) {
final RefJavaElementImpl enumConstantReference = (RefJavaElementImpl)getRefManager().getReference(enumConstant);
if (enumConstantReference != null) {
addOutReference(enumConstantReference);
enumConstantReference.markReferenced(this, psiFrom, enumConstant, false, true, expression);
}
}
}
}
}
}
}
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.source;
import com.intellij.extapi.psi.StubBasedPsiElementBase;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.OrderEntry;
@@ -661,4 +662,8 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
return true;
}
@Nullable
public PsiMethod getValuesMethod() {
return myValuesMethod;
}
}
@@ -0,0 +1,22 @@
class UnusedDeclBug {
public static enum Concern {
// These fields are used! Just because I don't mention them by name
// doesn't mean they aren't used!
// IDEA tells me I need: @SuppressWarnings({"UnusedDeclaration"})
LOW,
MEDIUM,
HIGH;
};
public static void main(String[] args) {
System.out.println("Concerns are:");
// Invoking Concern.values() should count as using all the fields in the
// enum.
for (Concern concern : Concern.values()) {
System.out.print("\t");
System.out.println(concern);
} // end for
}
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
</problems>
@@ -0,0 +1,22 @@
public class UnusedDeclBug {
public static enum Concern {
// These fields are used! Just because I don't mention them by name
// doesn't mean they aren't used!
// IDEA tells me I need: @SuppressWarnings({"UnusedDeclaration"})
LOW,
MEDIUM,
HIGH;
};
public static void main(String[] args) {
System.out.println("Concerns are:");
// Invoking Concern.values() should count as using all the fields in the
// enum.
for (Concern concern : Concern.values()) {
System.out.print("\t");
System.out.println(concern);
} // end for
}
}
@@ -47,6 +47,12 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, checkInfos);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{
@@ -275,4 +281,9 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
enableInspectionTool(new UnusedDeclarationInspection());
doTest(true, false);
}
public void testUnused() throws Exception {
enableInspectionTool(new UnusedDeclarationInspection());
doTest(true, false);
}
}
@@ -172,4 +172,8 @@ public class UnusedDeclarationTest extends InspectionTestCase {
public void testenumInstantiation() throws Exception {
doTest();
}
public void testenumValues() throws Exception {
doTest();
}
}