View Javadoc

1   /***
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.rules;
5   
6   import net.sourceforge.pmd.AbstractRule;
7   import net.sourceforge.pmd.RuleContext;
8   import net.sourceforge.pmd.RuleViolation;
9   import net.sourceforge.pmd.ast.ASTCompilationUnit;
10  import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
11  import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
12  import net.sourceforge.pmd.symboltable.NameOccurrence;
13  import net.sourceforge.pmd.symboltable.Scope;
14  import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
15  
16  import java.text.MessageFormat;
17  import java.util.HashSet;
18  import java.util.Iterator;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Set;
22  
23  public class UnusedLocalVariableRule extends AbstractRule {
24  
25      private Set visited = new HashSet();
26  
27      public Object visit(ASTCompilationUnit acu, Object data) {
28          visited.clear();
29          return super.visit(acu, data);
30      }
31  
32      public Object visit(ASTVariableDeclaratorId node, Object data) {
33          if (node.jjtGetParent().jjtGetParent() instanceof ASTLocalVariableDeclaration) {
34              Scope scope = node.getScope();
35              if (visited.contains(scope)) {
36                  return data;
37              } else {
38                  visited.add(scope);
39              }
40              Map locals = scope.getVariableDeclarations();
41              for (Iterator i = locals.keySet().iterator(); i.hasNext();) {
42                  VariableNameDeclaration decl = (VariableNameDeclaration) i.next();
43                  // TODO this misses some cases
44                  // need to add DFAish code to determine if an array
45                  // is initialized locally or gotten from somewhere else
46                  if (decl.isArray()) {
47                      continue;
48                  }
49                  List usages = (List) locals.get(decl);
50                  if (!actuallyUsed(usages)) {
51                      RuleContext ctx = ((RuleContext) data);
52                      RuleViolation ruleViolation = createRuleViolation(ctx, decl, MessageFormat.format(getMessage(), new Object[]{decl.getImage()}));
53                      ctx.getReport().addRuleViolation(ruleViolation);
54                  }
55              }
56          }
57          return data;
58      }
59  
60      private boolean actuallyUsed(List usages) {
61          for (Iterator j = usages.iterator(); j.hasNext();) {
62              NameOccurrence occ = (NameOccurrence) j.next();
63              if (occ.isOnLeftHandSide()) {
64                  continue;
65              } else {
66                  return true;
67              }
68          }
69          return false;
70      }
71  }