1 /**
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd;
5
6 import java.util.ArrayList;
7 import java.util.Comparator;
8 import java.util.List;
9
10 import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration;
11 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
12 import net.sourceforge.pmd.ast.ASTFieldDeclaration;
13 import net.sourceforge.pmd.ast.ASTFormalParameter;
14 import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
15 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
16 import net.sourceforge.pmd.ast.ASTTypeDeclaration;
17 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
18 import net.sourceforge.pmd.ast.CanSuppressWarnings;
19 import net.sourceforge.pmd.ast.SimpleNode;
20
21 public class RuleViolation implements IRuleViolation {
22
23 public static class RuleViolationComparator implements Comparator<IRuleViolation> {
24
25
26
27
28
29 public int compare(IRuleViolation r1, IRuleViolation r2) {
30 if (!r1.getFilename().equals(r2.getFilename())) {
31 return r1.getFilename().compareTo(r2.getFilename());
32 }
33
34 if (r1.getBeginLine() != r2.getBeginLine())
35 return r1.getBeginLine() - r2.getBeginLine();
36
37 if (r1.getDescription() != null && r2.getDescription() != null && !r1.getDescription().equals(r2.getDescription())) {
38 return r1.getDescription().compareTo(r2.getDescription());
39 }
40
41 if (r1.getBeginLine() == r2.getBeginLine()) {
42 return 1;
43 }
44
45
46 return r1.getBeginLine() - r2.getBeginLine();
47 }
48 }
49
50 private Rule rule;
51 private String description;
52 private String filename;
53
54 private String className;
55 private String methodName;
56 private String variableName;
57 private String packageName;
58 private int beginLine;
59 private int endLine;
60
61 private int beginColumn;
62 private int endColumn;
63 private boolean isSuppressed;
64
65 public RuleViolation(Rule rule, RuleContext ctx, SimpleNode node) {
66 this(rule, ctx, node, rule.getMessage());
67 }
68
69 public RuleViolation(Rule rule, RuleContext ctx, SimpleNode node, String specificMsg) {
70 this.rule = rule;
71 this.filename = ctx.getSourceCodeFilename();
72 this.description = specificMsg;
73
74 if (node != null) {
75 if (node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class) == null) {
76
77 className = "";
78 } else {
79
80 className = node.getScope().getEnclosingClassScope().getClassName() == null ? "" : node.getScope().getEnclosingClassScope().getClassName();
81 }
82
83 String qualifiedName = null;
84 List<ASTClassOrInterfaceDeclaration> parents = node.getParentsOfType(ASTClassOrInterfaceDeclaration.class);
85 for ( ASTClassOrInterfaceDeclaration parent : parents )
86 {
87 if (qualifiedName == null) {
88 qualifiedName = parent.getScope().getEnclosingClassScope().getClassName();
89 } else {
90 qualifiedName = parent.getScope().getEnclosingClassScope().getClassName() + "$" + qualifiedName;
91 }
92 }
93
94 if ( ! "net.sourceforge.pmd.symboltable.SourceFileScope".equals(node.getScope().getClass().getName() ) ) {
95 className = node.getScope().getEnclosingClassScope().getClassName() == null ? "" : qualifiedName;
96 }
97 setVariableNameIfExists(node);
98
99 methodName = node.getFirstParentOfType(ASTMethodDeclaration.class) == null ? "" : node.getScope().getEnclosingMethodScope().getName();
100
101 packageName = node.getScope().getEnclosingSourceFileScope().getPackageName() == null ? "" : node.getScope().getEnclosingSourceFileScope().getPackageName();
102
103 beginLine = node.getBeginLine();
104 endLine = node.getEndLine();
105 beginColumn = node.getBeginColumn();
106 endColumn = node.getEndColumn();
107
108
109
110 List<SimpleNode> parentTypes = new ArrayList<SimpleNode>(node.getParentsOfType(ASTTypeDeclaration.class));
111 if (node instanceof ASTTypeDeclaration) {
112 parentTypes.add(node);
113 }
114 parentTypes.addAll(node.getParentsOfType(ASTClassOrInterfaceBodyDeclaration.class));
115 if (node instanceof ASTClassOrInterfaceBodyDeclaration) {
116 parentTypes.add(node);
117 }
118 parentTypes.addAll(node.getParentsOfType(ASTFormalParameter.class));
119 if (node instanceof ASTFormalParameter) {
120 parentTypes.add(node);
121 }
122 parentTypes.addAll(node.getParentsOfType(ASTLocalVariableDeclaration.class));
123 if (node instanceof ASTLocalVariableDeclaration) {
124 parentTypes.add(node);
125 }
126 for (SimpleNode parentType : parentTypes) {
127 CanSuppressWarnings t = (CanSuppressWarnings) parentType;
128 if (t.hasSuppressWarningsAnnotationFor(getRule())) {
129 isSuppressed = true;
130 }
131 }
132 } else {
133 className = "";
134 methodName = "";
135 packageName = "";
136 filename = "";
137 }
138 }
139
140 private void setVariableNameIfExists(SimpleNode node) {
141 variableName = (node.getClass().equals(ASTFieldDeclaration.class))
142 ? ((ASTFieldDeclaration) node).getVariableName() : "";
143 if ("".equals(variableName)) {
144 variableName = (node.getClass().equals(ASTLocalVariableDeclaration.class))
145 ? ((ASTLocalVariableDeclaration) node).getVariableName() : "";
146 }
147 if ("".equals(variableName)) {
148 variableName = (node.getClass().equals(ASTVariableDeclaratorId.class))
149 ? node.getImage() : "";
150 }
151 }
152
153 public Rule getRule() {
154 return rule;
155 }
156
157 public boolean isSuppressed() {
158 return this.isSuppressed;
159 }
160
161 public int getBeginColumn() {
162 return beginColumn;
163 }
164
165 public int getEndColumn() {
166 return endColumn;
167 }
168
169 public String getDescription() {
170 return description;
171 }
172
173 public String getFilename() {
174 return filename;
175 }
176
177 public String getClassName() {
178 return className;
179 }
180
181 public String getMethodName() {
182 return methodName;
183 }
184
185 public String getPackageName() {
186 return packageName;
187 }
188
189 public int getBeginLine() {
190 return beginLine;
191 }
192
193 public int getEndLine() {
194 return endLine;
195 }
196
197 public String getVariableName() {
198 return variableName;
199 }
200
201 public String toString() {
202 return getFilename() + ":" + getRule() + ":" + getDescription() + ":" + beginLine;
203 }
204
205 }