|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| package net.sourceforge.pmd; |
|
5 |
| |
|
6 |
| import java.text.MessageFormat; |
|
7 |
| import java.util.Collections; |
|
8 |
| import java.util.HashMap; |
|
9 |
| import java.util.Iterator; |
|
10 |
| import java.util.List; |
|
11 |
| import java.util.Map; |
|
12 |
| import java.util.Properties; |
|
13 |
| |
|
14 |
| import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; |
|
15 |
| import net.sourceforge.pmd.ast.ASTCompilationUnit; |
|
16 |
| import net.sourceforge.pmd.ast.ASTImportDeclaration; |
|
17 |
| import net.sourceforge.pmd.ast.JavaParserVisitorAdapter; |
|
18 |
| import net.sourceforge.pmd.ast.Node; |
|
19 |
| import net.sourceforge.pmd.ast.SimpleNode; |
|
20 |
| |
|
21 |
| public abstract class AbstractRule extends JavaParserVisitorAdapter implements Rule { |
|
22 |
| |
|
23 |
| protected String name = getClass().getName(); |
|
24 |
| protected Properties properties = new Properties(); |
|
25 |
| protected String message; |
|
26 |
| protected String description; |
|
27 |
| protected String example; |
|
28 |
| protected String ruleSetName; |
|
29 |
| protected boolean include; |
|
30 |
| protected boolean usesDFA; |
|
31 |
| protected boolean usesTypeResolution; |
|
32 |
| protected int priority = LOWEST_PRIORITY; |
|
33 |
| protected String externalInfoUrl; |
|
34 |
| |
|
35 |
| private static final boolean inOldPropertyMode = true; |
|
36 |
| |
|
37 |
251
| protected static Map asFixedMap(PropertyDescriptor[] descriptors) {
|
|
38 |
| |
|
39 |
251
| Map descsById = new HashMap(descriptors.length);
|
|
40 |
| |
|
41 |
251
| for (int i=0; i<descriptors.length; i++) {
|
|
42 |
533
| descsById.put(descriptors[i].name(), descriptors[i]);
|
|
43 |
| } |
|
44 |
251
| return Collections.unmodifiableMap(descsById);
|
|
45 |
| } |
|
46 |
| |
|
47 |
72
| protected static Map asFixedMap(PropertyDescriptor descriptor) {
|
|
48 |
72
| return asFixedMap(new PropertyDescriptor[] {descriptor});
|
|
49 |
| } |
|
50 |
| |
|
51 |
12
| public String getRuleSetName() {
|
|
52 |
12
| return ruleSetName;
|
|
53 |
| } |
|
54 |
| |
|
55 |
4599
| public void setRuleSetName(String ruleSetName) {
|
|
56 |
4599
| this.ruleSetName = ruleSetName;
|
|
57 |
| } |
|
58 |
| |
|
59 |
2
| public String getDescription() {
|
|
60 |
2
| return description;
|
|
61 |
| } |
|
62 |
| |
|
63 |
4346
| public void setDescription(String description) {
|
|
64 |
4346
| this.description = description;
|
|
65 |
| } |
|
66 |
| |
|
67 |
1
| public String getExample() {
|
|
68 |
1
| return example;
|
|
69 |
| } |
|
70 |
| |
|
71 |
4434
| public void setExample(String example) {
|
|
72 |
4434
| this.example = example;
|
|
73 |
| } |
|
74 |
| |
|
75 |
| |
|
76 |
| |
|
77 |
| |
|
78 |
603
| public boolean hasProperty(String name) {
|
|
79 |
| |
|
80 |
603
| return inOldPropertyMode ?
|
|
81 |
| properties.containsKey(name) : |
|
82 |
| propertiesByName().containsKey(name); |
|
83 |
| } |
|
84 |
| |
|
85 |
| |
|
86 |
| |
|
87 |
| |
|
88 |
3455
| public void addProperty(String name, String value) {
|
|
89 |
3455
| properties.setProperty(name, value);
|
|
90 |
| } |
|
91 |
| |
|
92 |
| |
|
93 |
| |
|
94 |
| |
|
95 |
2
| public void addProperties(Properties properties) {
|
|
96 |
2
| this.properties.putAll(properties);
|
|
97 |
| } |
|
98 |
| |
|
99 |
0
| public double[] getDoubleProperties(PropertyDescriptor descriptor) {
|
|
100 |
| |
|
101 |
0
| Number[] values = (Number[])getProperties(descriptor);
|
|
102 |
| |
|
103 |
0
| double[] doubles = new double[values.length];
|
|
104 |
0
| for (int i=0; i<doubles.length; i++) doubles[i] = values[i].doubleValue();
|
|
105 |
0
| return doubles;
|
|
106 |
| } |
|
107 |
| |
|
108 |
| |
|
109 |
| |
|
110 |
| |
|
111 |
1
| public double getDoubleProperty(String name) {
|
|
112 |
| |
|
113 |
1
| return Double.parseDouble(properties.getProperty(name));
|
|
114 |
| } |
|
115 |
| |
|
116 |
253
| public double getDoubleProperty(PropertyDescriptor descriptor) {
|
|
117 |
| |
|
118 |
253
| return ((Number)getProperty(descriptor)).doubleValue();
|
|
119 |
| } |
|
120 |
| |
|
121 |
1
| public int[] getIntProperties(PropertyDescriptor descriptor) {
|
|
122 |
| |
|
123 |
1
| Number[] values = (Number[])getProperties(descriptor);
|
|
124 |
| |
|
125 |
1
| int[] ints = new int[values.length];
|
|
126 |
2
| for (int i=0; i<ints.length; i++) ints[i] = values[i].intValue();
|
|
127 |
1
| return ints;
|
|
128 |
| } |
|
129 |
| |
|
130 |
| |
|
131 |
| |
|
132 |
| |
|
133 |
8
| public int getIntProperty(String name) {
|
|
134 |
| |
|
135 |
8
| return Integer.parseInt(properties.getProperty(name));
|
|
136 |
| } |
|
137 |
| |
|
138 |
176
| public int getIntProperty(PropertyDescriptor descriptor) {
|
|
139 |
| |
|
140 |
176
| return ((Number)getProperty(descriptor)).intValue();
|
|
141 |
| } |
|
142 |
| |
|
143 |
0
| public Class[] getTypeProperties(PropertyDescriptor descriptor) {
|
|
144 |
| |
|
145 |
0
| return (Class[])getProperties(descriptor);
|
|
146 |
| } |
|
147 |
| |
|
148 |
0
| public Class getTypeProperty(PropertyDescriptor descriptor) {
|
|
149 |
| |
|
150 |
0
| return (Class)getProperty(descriptor);
|
|
151 |
| } |
|
152 |
| |
|
153 |
1
| public boolean[] getBooleanProperties(PropertyDescriptor descriptor) {
|
|
154 |
| |
|
155 |
1
| Boolean[] values = (Boolean[])getProperties(descriptor);
|
|
156 |
| |
|
157 |
1
| boolean[] bools = new boolean[values.length];
|
|
158 |
2
| for (int i=0; i<bools.length; i++) bools[i] = values[i].booleanValue();
|
|
159 |
1
| return bools;
|
|
160 |
| } |
|
161 |
| |
|
162 |
25
| public boolean getBooleanProperty(PropertyDescriptor descriptor) {
|
|
163 |
| |
|
164 |
25
| return ((Boolean)getProperty(descriptor)).booleanValue();
|
|
165 |
| } |
|
166 |
| |
|
167 |
| |
|
168 |
| |
|
169 |
| |
|
170 |
16
| public boolean getBooleanProperty(String name) {
|
|
171 |
| |
|
172 |
16
| return Boolean.valueOf(properties.getProperty(name)).booleanValue();
|
|
173 |
| } |
|
174 |
| |
|
175 |
| |
|
176 |
| |
|
177 |
| |
|
178 |
| |
|
179 |
| |
|
180 |
| |
|
181 |
0
| public void setBooleanProperty(String name, boolean flag) {
|
|
182 |
| |
|
183 |
0
| properties.setProperty(name, Boolean.toString(flag));
|
|
184 |
| } |
|
185 |
| |
|
186 |
41
| public String[] getStringProperties(PropertyDescriptor descriptor) {
|
|
187 |
| |
|
188 |
41
| return (String[])getProperties(descriptor);
|
|
189 |
| } |
|
190 |
| |
|
191 |
| |
|
192 |
| |
|
193 |
| |
|
194 |
| |
|
195 |
| |
|
196 |
109
| public String getStringProperty(String name) {
|
|
197 |
109
| return properties.getProperty(name);
|
|
198 |
| } |
|
199 |
| |
|
200 |
37
| public String getStringProperty(PropertyDescriptor descriptor) {
|
|
201 |
37
| return (String)getProperty(descriptor);
|
|
202 |
| } |
|
203 |
| |
|
204 |
491
| private Object getProperty(PropertyDescriptor descriptor) {
|
|
205 |
| |
|
206 |
0
| if (descriptor.maxValueCount() > 1) propertyGetError(descriptor, true);
|
|
207 |
| |
|
208 |
491
| String rawValue = properties.getProperty(descriptor.name());
|
|
209 |
| |
|
210 |
491
| return rawValue == null || rawValue.length() == 0 ?
|
|
211 |
| descriptor.defaultValue() : |
|
212 |
| descriptor.valueFrom(rawValue); |
|
213 |
| } |
|
214 |
| |
|
215 |
29
| public void setProperty(PropertyDescriptor descriptor, Object value) {
|
|
216 |
| |
|
217 |
3
| if (descriptor.maxValueCount() > 1) propertySetError(descriptor, true);
|
|
218 |
| |
|
219 |
26
| properties.setProperty(descriptor.name(), descriptor.asDelimitedString(value));
|
|
220 |
| } |
|
221 |
| |
|
222 |
43
| private Object[] getProperties(PropertyDescriptor descriptor) {
|
|
223 |
| |
|
224 |
0
| if (descriptor.maxValueCount() == 1) propertyGetError(descriptor, false);
|
|
225 |
| |
|
226 |
43
| String rawValue = properties.getProperty(descriptor.name());
|
|
227 |
| |
|
228 |
43
| return rawValue == null || rawValue.length() == 0 ?
|
|
229 |
| (Object[])descriptor.defaultValue() : |
|
230 |
| (Object[])descriptor.valueFrom(rawValue); |
|
231 |
| } |
|
232 |
| |
|
233 |
6
| public void setProperties(PropertyDescriptor descriptor, Object[] values) {
|
|
234 |
| |
|
235 |
3
| if (descriptor.maxValueCount() == 1) propertySetError(descriptor, false);
|
|
236 |
| |
|
237 |
3
| properties.setProperty(descriptor.name(), descriptor.asDelimitedString(values));
|
|
238 |
| } |
|
239 |
| |
|
240 |
0
| private void propertyGetError(PropertyDescriptor descriptor, boolean requestedSingleValue) {
|
|
241 |
| |
|
242 |
0
| if (requestedSingleValue) {
|
|
243 |
0
| throw new RuntimeException("Cannot retrieve a single value from a multi-value property field");
|
|
244 |
| } |
|
245 |
0
| throw new RuntimeException("Cannot retrieve multiple values from a single-value property field");
|
|
246 |
| } |
|
247 |
| |
|
248 |
6
| private void propertySetError(PropertyDescriptor descriptor, boolean setSingleValue) {
|
|
249 |
| |
|
250 |
6
| if (setSingleValue) {
|
|
251 |
3
| throw new RuntimeException("Cannot set a single value within a multi-value property field");
|
|
252 |
| } |
|
253 |
3
| throw new RuntimeException("Cannot set multiple values within a single-value property field");
|
|
254 |
| } |
|
255 |
| |
|
256 |
2846
| public String getName() {
|
|
257 |
2846
| return name;
|
|
258 |
| } |
|
259 |
| |
|
260 |
4413
| public void setName(String name) {
|
|
261 |
4413
| this.name = name;
|
|
262 |
| } |
|
263 |
| |
|
264 |
849
| public String getMessage() {
|
|
265 |
849
| return message;
|
|
266 |
| } |
|
267 |
| |
|
268 |
4417
| public void setMessage(String message) {
|
|
269 |
4417
| this.message = message;
|
|
270 |
| } |
|
271 |
| |
|
272 |
15
| public String getExternalInfoUrl() {
|
|
273 |
15
| return externalInfoUrl;
|
|
274 |
| } |
|
275 |
| |
|
276 |
4391
| public void setExternalInfoUrl(String url) {
|
|
277 |
4391
| this.externalInfoUrl = url;
|
|
278 |
| } |
|
279 |
| |
|
280 |
| |
|
281 |
| |
|
282 |
| |
|
283 |
| |
|
284 |
| |
|
285 |
| |
|
286 |
| |
|
287 |
16
| public boolean equals(Object o) {
|
|
288 |
16
| if (o == null) {
|
|
289 |
1
| return false;
|
|
290 |
| } |
|
291 |
| |
|
292 |
15
| if (this == o) {
|
|
293 |
5
| return true;
|
|
294 |
| } |
|
295 |
| |
|
296 |
10
| Rule rule = null;
|
|
297 |
10
| boolean equality = this.getClass().getName().equals(o.getClass().getName());
|
|
298 |
| |
|
299 |
10
| if (equality) {
|
|
300 |
8
| rule = (Rule) o;
|
|
301 |
8
| equality = this.getName().equals(rule.getName())
|
|
302 |
| && this.getPriority() == rule.getPriority() |
|
303 |
| && this.getProperties().equals(rule.getProperties()); |
|
304 |
| } |
|
305 |
| |
|
306 |
10
| return equality;
|
|
307 |
| } |
|
308 |
| |
|
309 |
| |
|
310 |
| |
|
311 |
| |
|
312 |
20
| public int hashCode() {
|
|
313 |
20
| String s = getClass().getName() + getName() + getPriority() + getProperties().toString();
|
|
314 |
20
| return s.hashCode();
|
|
315 |
| } |
|
316 |
| |
|
317 |
1189
| public void apply(List acus, RuleContext ctx) {
|
|
318 |
1189
| visitAll(acus, ctx);
|
|
319 |
| } |
|
320 |
| |
|
321 |
| |
|
322 |
| |
|
323 |
| |
|
324 |
1200
| public Properties getProperties() {
|
|
325 |
1200
| return properties;
|
|
326 |
| } |
|
327 |
| |
|
328 |
0
| public boolean include() {
|
|
329 |
0
| return include;
|
|
330 |
| } |
|
331 |
| |
|
332 |
0
| public void setInclude(boolean include) {
|
|
333 |
0
| this.include = include;
|
|
334 |
| } |
|
335 |
| |
|
336 |
4483
| public int getPriority() {
|
|
337 |
4483
| return priority;
|
|
338 |
| } |
|
339 |
| |
|
340 |
0
| public String getPriorityName() {
|
|
341 |
0
| return PRIORITIES[getPriority() - 1];
|
|
342 |
| } |
|
343 |
| |
|
344 |
4356
| public void setPriority(int priority) {
|
|
345 |
4356
| this.priority = priority;
|
|
346 |
| } |
|
347 |
| |
|
348 |
19
| public void setUsesDFA() {
|
|
349 |
19
| this.usesDFA = true;
|
|
350 |
| } |
|
351 |
| |
|
352 |
1229
| public boolean usesDFA() {
|
|
353 |
1229
| return this.usesDFA;
|
|
354 |
| } |
|
355 |
| |
|
356 |
4
| public void setUsesTypeResolution() {
|
|
357 |
4
| this.usesTypeResolution = true;
|
|
358 |
| } |
|
359 |
| |
|
360 |
1225
| public boolean usesTypeResolution() {
|
|
361 |
1225
| return this.usesTypeResolution;
|
|
362 |
| } |
|
363 |
| |
|
364 |
1383
| protected void visitAll(List acus, RuleContext ctx) {
|
|
365 |
1383
| for (Iterator i = acus.iterator(); i.hasNext();) {
|
|
366 |
1225
| ASTCompilationUnit node = (ASTCompilationUnit) i.next();
|
|
367 |
1225
| visit(node, ctx);
|
|
368 |
| } |
|
369 |
| } |
|
370 |
| |
|
371 |
| |
|
372 |
| |
|
373 |
| |
|
374 |
| |
|
375 |
| |
|
376 |
| |
|
377 |
224
| protected final void addViolation(Object data, SimpleNode node) {
|
|
378 |
224
| RuleContext ctx = (RuleContext) data;
|
|
379 |
224
| ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node));
|
|
380 |
| } |
|
381 |
| |
|
382 |
| |
|
383 |
| |
|
384 |
| |
|
385 |
| |
|
386 |
| |
|
387 |
| |
|
388 |
| |
|
389 |
2239
| protected final void addViolationWithMessage(Object data, SimpleNode node, String msg) {
|
|
390 |
2239
| RuleContext ctx = (RuleContext) data;
|
|
391 |
2239
| ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, msg));
|
|
392 |
| } |
|
393 |
| |
|
394 |
| |
|
395 |
| |
|
396 |
| |
|
397 |
| |
|
398 |
| |
|
399 |
| |
|
400 |
| |
|
401 |
326
| protected final void addViolation(Object data, SimpleNode node, String embed) {
|
|
402 |
326
| RuleContext ctx = (RuleContext) data;
|
|
403 |
326
| ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, MessageFormat.format(getMessage(), new Object[]{embed})));
|
|
404 |
| } |
|
405 |
| |
|
406 |
| |
|
407 |
| |
|
408 |
| |
|
409 |
| |
|
410 |
| |
|
411 |
| |
|
412 |
| |
|
413 |
62
| protected final void addViolation(Object data, Node node, Object[] args) {
|
|
414 |
62
| RuleContext ctx = (RuleContext) data;
|
|
415 |
62
| ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, (SimpleNode) node, MessageFormat.format(getMessage(), args)));
|
|
416 |
| } |
|
417 |
| |
|
418 |
| |
|
419 |
| |
|
420 |
| |
|
421 |
| |
|
422 |
| |
|
423 |
12
| protected final String getDeclaringType(SimpleNode node) {
|
|
424 |
12
| ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration) node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
|
425 |
12
| if (c != null)
|
|
426 |
12
| return c.getImage();
|
|
427 |
0
| return null;
|
|
428 |
| } |
|
429 |
| |
|
430 |
46
| public static boolean isQualifiedName(SimpleNode node) {
|
|
431 |
46
| return node.getImage().indexOf('.') != -1;
|
|
432 |
| } |
|
433 |
| |
|
434 |
0
| public static boolean importsPackage(ASTCompilationUnit node, String packageName) {
|
|
435 |
| |
|
436 |
0
| List nodes = node.findChildrenOfType(ASTImportDeclaration.class);
|
|
437 |
0
| for (Iterator i = nodes.iterator(); i.hasNext();) {
|
|
438 |
0
| ASTImportDeclaration n = (ASTImportDeclaration) i.next();
|
|
439 |
0
| if (n.getPackageName().startsWith(packageName)) {
|
|
440 |
0
| return true;
|
|
441 |
| } |
|
442 |
| } |
|
443 |
0
| return false;
|
|
444 |
| } |
|
445 |
| |
|
446 |
| |
|
447 |
| |
|
448 |
| |
|
449 |
| |
|
450 |
| |
|
451 |
| |
|
452 |
0
| protected Map propertiesByName() {
|
|
453 |
0
| return Collections.EMPTY_MAP;
|
|
454 |
| } |
|
455 |
| |
|
456 |
| |
|
457 |
| |
|
458 |
| |
|
459 |
| |
|
460 |
| |
|
461 |
| |
|
462 |
0
| public PropertyDescriptor propertyDescriptorFor(String propertyName) {
|
|
463 |
0
| PropertyDescriptor desc = (PropertyDescriptor)propertiesByName().get(propertyName);
|
|
464 |
0
| if (desc == null) throw new IllegalArgumentException("unknown property: " + propertyName);
|
|
465 |
0
| return desc;
|
|
466 |
| } |
|
467 |
| } |