01: /*
02: * AssignmentToNonFinalStaticRule.java
03: *
04: * Created on October 24, 2004, 8:56 AM
05: */
06:
07: package net.sourceforge.pmd.rules.design;
08:
09: 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: * @author Eric Olander
21: */
22: public class AssignmentToNonFinalStatic extends AbstractRule {
23:
24: public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
25: Map<VariableNameDeclaration, List<NameOccurrence>> vars = node
26: .getScope().getVariableDeclarations();
27: for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : vars
28: .entrySet()) {
29: VariableNameDeclaration decl = entry.getKey();
30: if (!decl.getAccessNodeParent().isStatic()
31: || decl.getAccessNodeParent().isFinal()) {
32: continue;
33: }
34:
35: if (initializedInConstructor(entry.getValue())) {
36: addViolation(data, decl.getNode(), decl.getImage());
37: }
38: }
39: return super .visit(node, data);
40: }
41:
42: private boolean initializedInConstructor(List<NameOccurrence> usages) {
43: boolean initInConstructor = false;
44:
45: for (NameOccurrence occ : usages) {
46: if (occ.isOnLeftHandSide()) { // specifically omitting prefix and postfix operators as there are legitimate usages of these with static fields, e.g. typesafe enum pattern.
47: SimpleNode node = occ.getLocation();
48: SimpleNode constructor = node
49: .getFirstParentOfType(ASTConstructorDeclaration.class);
50: if (constructor != null) {
51: initInConstructor = true;
52: }
53: }
54: }
55:
56: return initInConstructor;
57: }
58:
59: }
|