View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule.design;
5   
6   import java.util.List;
7   import java.util.Map;
8   
9   import net.sourceforge.pmd.lang.ast.Node;
10  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
11  import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
12  import net.sourceforge.pmd.lang.java.ast.AccessNode;
13  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
14  import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
15  import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
16  import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
17  
18  
19  /**
20   * @author Eric Olander
21   * @since Created on October 24, 2004, 8:56 AM
22   */
23  public class AssignmentToNonFinalStaticRule extends AbstractJavaRule {
24  
25      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
26          Map<VariableNameDeclaration, List<NameOccurrence>> vars = node.getScope().getDeclarations(VariableNameDeclaration.class);
27          for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry: vars.entrySet()) {
28              VariableNameDeclaration decl = entry.getKey();
29              AccessNode accessNodeParent = (AccessNode)decl.getAccessNodeParent();
30              if (!accessNodeParent.isStatic() || accessNodeParent.isFinal()) {
31                  continue;
32              }
33  
34              if (initializedInConstructor(entry.getValue())) {
35                  addViolation(data, decl.getNode(), decl.getImage());
36              }
37          }
38          return super.visit(node, data);
39      }
40  
41      private boolean initializedInConstructor(List<NameOccurrence> usages) {
42          boolean initInConstructor = false;
43  
44          for (NameOccurrence occ: usages) {
45              if (((JavaNameOccurrence)occ).isOnLeftHandSide()) { // specifically omitting prefix and postfix operators as there are legitimate usages of these with static fields, e.g. typesafe enum pattern.
46          	Node node = occ.getLocation();
47          	Node constructor = node.getFirstParentOfType(ASTConstructorDeclaration.class);
48                  if (constructor != null) {
49                      initInConstructor = true;
50                  }
51              }
52          }
53  
54          return initInConstructor;
55      }
56  
57  }