01 /*
02 * AssignmentToNonFinalStaticRule.java
03 *
04 * Created on October 24, 2004, 8:56 AM
05 */
06
07 package net.sourceforge.pmd.lang.java.rule.design;
08
09 import java.util.List;
10 import java.util.Map;
11
12 import net.sourceforge.pmd.lang.ast.Node;
13 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
14 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
15 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
16 import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence;
17 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
18
19
20 /**
21 * @author Eric Olander
22 */
23 public class AssignmentToNonFinalStaticRule extends AbstractJavaRule {
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 Node node = occ.getLocation();
46 Node constructor = node.getFirstParentOfType(ASTConstructorDeclaration.class);
47 if (constructor != null) {
48 initInConstructor = true;
49 }
50 }
51 }
52
53 return initInConstructor;
54 }
55
56 }
|