/** * 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()); } } } }