From 2cc0e2fc763bd67a415b354e6ca43986a539bf11 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Wed, 5 Dec 2012 11:01:08 +0400 Subject: [PATCH] IDEA-94706 Groovy: unused var is not detected --- .../GroovyInspectionBundle.properties | 1 + .../unusedDef/UnusedDefInspection.java | 33 +++++++++++++++---- .../lang/highlighting/GrUnusedDefTest.groovy | 6 ++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties index 0d91c51a358e..2c8dd930b3e7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties @@ -34,6 +34,7 @@ groovy.dfa.issues=Data flow issues unused.assignment=Unused Assignment unused.assignment.tooltip=Assignment is not used +unused.variable=Variable is not used unused.inc.dec=Unused Incrementing or Decrementing diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java index 60f74b1b0d6e..3cf0b384a76f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java @@ -27,18 +27,21 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; import gnu.trove.TObjectProcedure; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.codeInspection.GroovyLocalInspectionBase; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; @@ -53,6 +56,7 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefin import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsSemilattice; import java.util.List; +import java.util.Set; /** & @author ven @@ -121,19 +125,36 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { } } + final Set checked = ContainerUtil.newHashSet(); + unusedDefs.forEach(new TIntProcedure() { public boolean execute(int num) { final ReadWriteVariableInstruction instruction = (ReadWriteVariableInstruction)flow[num]; final PsiElement element = instruction.getElement(); - if (element == null) return true; - if (isLocalAssignment(element) && isUsedInTopLevelFlowOnly(element) && !isIncOrDec(element)) { - PsiElement toHighlight = getHighlightElement(element); - problemsHolder.registerProblem(toHighlight, GroovyInspectionBundle.message("unused.assignment.tooltip"), - ProblemHighlightType.LIKE_UNUSED_SYMBOL); - } + process(element, checked, problemsHolder, GroovyInspectionBundle.message("unused.assignment.tooltip")); return true; } }); + + owner.accept(new GroovyRecursiveElementVisitor() { + @Override + public void visitVariable(GrVariable variable) { + if (checked.contains(variable) || variable.getInitializerGroovy() != null) return; + + if (ReferencesSearch.search(variable).findFirst() == null) { + process(variable, checked, problemsHolder, GroovyInspectionBundle.message("unused.variable")); + } + } + }); + } + + private static void process(@Nullable PsiElement element, Set checked, ProblemsHolder problemsHolder, final String message) { + if (element == null) return; + if (!checked.add(element)) return; + if (isLocalAssignment(element) && isUsedInTopLevelFlowOnly(element) && !isIncOrDec(element)) { + PsiElement toHighlight = getHighlightElement(element); + problemsHolder.registerProblem(toHighlight, message, ProblemHighlightType.LIKE_UNUSED_SYMBOL); + } } private static PsiElement getHighlightElement(PsiElement element) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrUnusedDefTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrUnusedDefTest.groovy index 8b32e98850d2..2af888b452ee 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrUnusedDefTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrUnusedDefTest.groovy @@ -126,6 +126,12 @@ def f2(String foo, int mode) { case 1: return 2 } } +''') + } + + void testUnusedUnassignedVar() { + testHighlighting('''\ +def abc ''') }