/**
* 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.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.symboltable.AbstractJavaScope;
import net.sourceforge.pmd.lang.java.symboltable.ClassNameDeclaration;
import net.sourceforge.pmd.lang.java.symboltable.ClassScope;
import net.sourceforge.pmd.lang.java.symboltable.MethodNameDeclaration;
import net.sourceforge.pmd.lang.java.symboltable.SourceFileScope;
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
public class AccessorMethodGenerationRule extends AbstractJavaRule {
public Object visit(final ASTCompilationUnit node, final Object data) {
final SourceFileScope file = node.getScope().getEnclosingScope(SourceFileScope.class);
analyzeScope(file, data);
return data; // Stop tree navigation
}
private void analyzeScope(final AbstractJavaScope file, final Object data) {
for (final ClassNameDeclaration classDecl : file.getDeclarations(ClassNameDeclaration.class).keySet()) {
final ClassScope classScope = (ClassScope) classDecl.getScope();
// Check fields
for (final Map.Entry<VariableNameDeclaration, List<NameOccurrence>> varDecl : classScope.getVariableDeclarations().entrySet()) {
final ASTFieldDeclaration field = varDecl.getKey().getNode().getFirstParentOfType(ASTFieldDeclaration.class);
analyzeMember(field, varDecl.getValue(), classScope, data);
}
// Check methods
for (final Map.Entry<MethodNameDeclaration, List<NameOccurrence>> methodDecl : classScope.getMethodDeclarations().entrySet()) {
final ASTMethodDeclaration method = methodDecl.getKey().getNode().getFirstParentOfType(ASTMethodDeclaration.class);
analyzeMember(method, methodDecl.getValue(), classScope, data);
}
// Check inner classes
analyzeScope(classScope, data);
}
}
public void analyzeMember(final AbstractJavaAccessNode node, final List<NameOccurrence> occurrences,
final ClassScope classScope, final Object data) {
if (!node.isPrivate()) {
return;
}
for (final NameOccurrence no : occurrences) {
ClassScope usedAtScope = no.getLocation().getScope().getEnclosingScope(ClassScope.class);
// Are we within the same class that defines the field / method?
if (!classScope.equals(usedAtScope)) {
addViolation(data, no.getLocation());
}
}
}
}