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 }