From 765d5e4f016af743b40b6659c29b8085e98da62a Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 15 Jun 2011 13:59:23 +0400 Subject: [PATCH] do not highlight enum constants as unused when values are used (IDEA-65298 ) --- .../daemon/impl/PostHighlightingPass.java | 25 +++++++++++++++++-- .../reference/RefJavaElementImpl.java | 16 ++++++++++++ .../psi/impl/source/PsiClassImpl.java | 5 ++++ .../advHighlighting7/Unused.java | 22 ++++++++++++++++ .../deadCode/enumValues/expected.xml | 4 +++ .../deadCode/enumValues/src/Test.java | 22 ++++++++++++++++ .../daemon/LightAdvHighlightingJdk7Test.java | 11 ++++++++ .../codeInspection/UnusedDeclarationTest.java | 4 +++ 8 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/Unused.java create mode 100644 java/java-tests/testData/inspection/deadCode/enumValues/expected.xml create mode 100644 java/java-tests/testData/inspection/deadCode/enumValues/src/Test.java 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 af2d3dfd6798..92f29a352ce0 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 @@ -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 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) { diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java index 7c0ad3f80ebf..20f86e15521b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaElementImpl.java @@ -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); + } + } + } + } + } } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index e6be33250240..6484e9789a4f 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -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> implements return true; } + @Nullable + public PsiMethod getValuesMethod() { + return myValuesMethod; + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/Unused.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/Unused.java new file mode 100644 index 000000000000..a2cbf037333b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/Unused.java @@ -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 + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/deadCode/enumValues/expected.xml b/java/java-tests/testData/inspection/deadCode/enumValues/expected.xml new file mode 100644 index 000000000000..79e1a0fd0a57 --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/enumValues/expected.xml @@ -0,0 +1,4 @@ + + + + diff --git a/java/java-tests/testData/inspection/deadCode/enumValues/src/Test.java b/java/java-tests/testData/inspection/deadCode/enumValues/src/Test.java new file mode 100644 index 000000000000..c10bb52e2a30 --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/enumValues/src/Test.java @@ -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 + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index 75110e1e0ed8..a9d2caca6e80 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -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); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java index 3f75188f768e..77831f6bc580 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/UnusedDeclarationTest.java @@ -172,4 +172,8 @@ public class UnusedDeclarationTest extends InspectionTestCase { public void testenumInstantiation() throws Exception { doTest(); } + + public void testenumValues() throws Exception { + doTest(); + } }