01 /**
02 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03 */
04 package net.sourceforge.pmd.lang.java.rule;
05
06 import net.sourceforge.pmd.Rule;
07 import net.sourceforge.pmd.RuleContext;
08 import net.sourceforge.pmd.lang.ast.Node;
09 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.AbstractRuleViolation;
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 AbstractRuleViolation {
34 public JavaRuleViolation(Rule rule, RuleContext ctx, JavaNode node, String message) {
35 super(rule, ctx, node, message);
36
37 if (node != null) {
38 final Scope scope = node.getScope();
39 final SourceFileScope sourceFileScope = scope.getEnclosingSourceFileScope();
40
41 // Package name is on SourceFileScope
42 packageName = sourceFileScope.getPackageName() == null ? "" : sourceFileScope.getPackageName();
43
44 // Class name is built from enclosing ClassScopes
45 String qualifiedName = null;
46 for (ASTClassOrInterfaceDeclaration parent : node.getParentsOfType(ASTClassOrInterfaceDeclaration.class)) {
47 if (qualifiedName == null) {
48 qualifiedName = parent.getScope().getEnclosingClassScope().getClassName();
49 } else {
50 qualifiedName = parent.getScope().getEnclosingClassScope().getClassName() + "$" + qualifiedName;
51 }
52 }
53 if (qualifiedName != null) {
54 className = qualifiedName;
55 }
56 // Method name comes from 1st enclosing MethodScope
57 if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) {
58 methodName = scope.getEnclosingMethodScope().getName();
59 }
60 // Variable name node specific
61 setVariableNameIfExists(node);
62
63 // Check for suppression on this node, on parents, and on contained types for ASTCompilationUnit
64 if (!suppressed) {
65 suppressed = suppresses(node);
66 }
67 if (!suppressed && node instanceof ASTCompilationUnit) {
68 for (int i = 0; !suppressed && i < node.jjtGetNumChildren(); i++) {
69 suppressed = suppresses(node.jjtGetChild(i));
70 }
71 }
72 if (!suppressed) {
73 Node parent = node.jjtGetParent();
74 while (!suppressed && parent != null) {
75 suppressed = suppresses(parent);
76 parent = parent.jjtGetParent();
77 }
78 }
79 }
80 }
81
82 private boolean suppresses(final Node node) {
83 return node instanceof CanSuppressWarnings
84 && ((CanSuppressWarnings) node).hasSuppressWarningsAnnotationFor(getRule());
85 }
86
87 private void setVariableNameIfExists(Node node) {
88 variableName = "";
89 if (node instanceof ASTFieldDeclaration) {
90 variableName = ((ASTFieldDeclaration) node).getVariableName();
91 } else if (node instanceof ASTLocalVariableDeclaration) {
92 variableName = ((ASTLocalVariableDeclaration) node).getVariableName();
93 } else if (node instanceof ASTVariableDeclarator) {
94 variableName = node.jjtGetChild(0).getImage();
95 } else if (node instanceof ASTVariableDeclaratorId) {
96 variableName = node.getImage();
97 }
98 }
99 }
|