View Javadoc

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