View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.lang.java.rule;
    5
    6   import net.sourceforge.pmd.Rule;
    7   import net.sourceforge.pmd.RuleContext;
    8   import net.sourceforge.pmd.lang.ast.Node;
    9   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
    10  import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
    11  import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
    12  import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
    13  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
    14  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
    15  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
    16  import net.sourceforge.pmd.lang.java.ast.CanSuppressWarnings;
    17  import net.sourceforge.pmd.lang.java.ast.JavaNode;
    18  import net.sourceforge.pmd.lang.java.symboltable.Scope;
    19  import net.sourceforge.pmd.lang.java.symboltable.SourceFileScope;
    20  import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
    21
    22  /**
    23   * This is a Java RuleViolation. It knows how to try to extract the following
    24   * extra information from the violation node:
    25   * <ul>
    26   * <li>Package name</li>
    27   * <li>Class name</li>
    28   * <li>Method name</li>
    29   * <li>Variable name</li>
    30   * <li>Suppression indicator</li>
    31   * </ul>
    32   */
    33  public class JavaRuleViolation extends ParametricRuleViolation<JavaNode> {
    34
    35  	public JavaRuleViolation(Rule rule, RuleContext ctx, JavaNode node, String message, int beginLine, int endLine) {
    36  		this(rule, ctx, node, message);
    37
    38  		setLines(beginLine, endLine);
    39  	}
    40
    41  	public JavaRuleViolation(Rule rule, RuleContext ctx, JavaNode node, String message) {
    42  		super(rule, ctx, node, message);
    43
    44  		if (node != null) {
    45  			final Scope scope = node.getScope();
    46  			final SourceFileScope sourceFileScope = scope.getEnclosingSourceFileScope();
    47
    48  			// Package name is on SourceFileScope
    49  			packageName = sourceFileScope.getPackageName() == null ? ""	: sourceFileScope.getPackageName();
    50
    51  			// Class name is built from enclosing ClassScopes
    52  			setClassNameFrom(node);
    53
    54  			// Method name comes from 1st enclosing MethodScope
    55  			if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) {
    56  				methodName = scope.getEnclosingMethodScope().getName();
    57  			}
    58  			// Variable name node specific
    59  			setVariableNameIfExists(node);
    60
    61  			// Check for suppression on this node, on parents, and on contained
    62  			// types for ASTCompilationUnit
    63  			if (!suppressed) {
    64  				suppressed = suppresses(node);
    65  			}
    66  			if (!suppressed && node instanceof ASTCompilationUnit) {
    67  				for (int i = 0; !suppressed && i < node.jjtGetNumChildren(); i++) {
    68  					suppressed = suppresses(node.jjtGetChild(i));
    69  				}
    70  			}
    71  			if (!suppressed) {
    72  				Node parent = node.jjtGetParent();
    73  				while (!suppressed && parent != null) {
    74  					suppressed = suppresses(parent);
    75  					parent = parent.jjtGetParent();
    76  				}
    77  			}
    78  		}
    79  	}
    80
    81  	private void setClassNameFrom(JavaNode node) {
    82
    83  		String qualifiedName = null;
    84  		for (ASTClassOrInterfaceDeclaration parent : node.getParentsOfType(ASTClassOrInterfaceDeclaration.class)) {
    85  			String clsName = parent.getScope().getEnclosingClassScope().getClassName();
    86  			if (qualifiedName == null) {
    87  				qualifiedName = clsName;
    88  			} else {
    89  				qualifiedName = clsName + '$' + qualifiedName;
    90  			}
    91  		}
    92  		if (qualifiedName != null) {
    93  			className = qualifiedName;
    94  		}
    95  	}
    96
    97  	private boolean suppresses(final Node node) {
    98  		return node instanceof CanSuppressWarnings
    99  				&& ((CanSuppressWarnings) node).hasSuppressWarningsAnnotationFor(getRule());
    100 	}
    101
    102 	private void setVariableNameIfExists(Node node) {
    103 		variableName = "";
    104 		if (node instanceof ASTFieldDeclaration) {
    105 			variableName = ((ASTFieldDeclaration) node).getVariableName();
    106 		} else if (node instanceof ASTLocalVariableDeclaration) {
    107 			variableName = ((ASTLocalVariableDeclaration) node)
    108 					.getVariableName();
    109 		} else if (node instanceof ASTVariableDeclarator) {
    110 			variableName = node.jjtGetChild(0).getImage();
    111 		} else if (node instanceof ASTVariableDeclaratorId) {
    112 			variableName = node.getImage();
    113 		}
    114 	}
    115 }