/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.design;
import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.AccessNode;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
/**
* @author Eric Olander
* @since Created on October 24, 2004, 8:56 AM
*/
public class AssignmentToNonFinalStaticRule extends AbstractJavaRule {
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
Map<VariableNameDeclaration, List<NameOccurrence>> vars = node.getScope()
.getDeclarations(VariableNameDeclaration.class);
for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : vars.entrySet()) {
VariableNameDeclaration decl = entry.getKey();
AccessNode accessNodeParent = (AccessNode) decl.getAccessNodeParent();
if (!accessNodeParent.isStatic() || accessNodeParent.isFinal()) {
continue;
}
if (initializedInConstructor(entry.getValue())) {
addViolation(data, decl.getNode(), decl.getImage());
}
}
return super.visit(node, data);
}
private boolean initializedInConstructor(List<NameOccurrence> usages) {
boolean initInConstructor = false;
for (NameOccurrence occ : usages) {
// specifically omitting prefix and postfix operators as there are
// legitimate usages of these with static fields, e.g. typesafe enum pattern.
if (((JavaNameOccurrence) occ).isOnLeftHandSide()) {
Node node = occ.getLocation();
Node constructor = node.getFirstParentOfType(ASTConstructorDeclaration.class);
if (constructor != null) {
initInConstructor = true;
}
}
}
return initInConstructor;
}
}