1
2
3
4 package net.sourceforge.pmd;
5
6 import java.io.File;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.logging.Level;
12 import java.util.logging.Logger;
13
14 import net.sourceforge.pmd.benchmark.Benchmark;
15 import net.sourceforge.pmd.benchmark.Benchmarker;
16 import net.sourceforge.pmd.lang.Language;
17 import net.sourceforge.pmd.lang.LanguageVersion;
18 import net.sourceforge.pmd.lang.ast.Node;
19 import net.sourceforge.pmd.lang.rule.RuleReference;
20 import net.sourceforge.pmd.util.CollectionUtil;
21 import net.sourceforge.pmd.util.StringUtil;
22 import net.sourceforge.pmd.util.filter.Filter;
23 import net.sourceforge.pmd.util.filter.Filters;
24
25
26
27
28
29
30
31
32 public class RuleSet {
33
34 private static final Logger LOG = Logger.getLogger(RuleSet.class.getName());
35
36 private List<Rule> rules = new ArrayList<Rule>();
37 private String fileName;
38 private String name = "";
39 private String description = "";
40
41
42 private List<String> excludePatterns = new ArrayList<String>(0);
43 private List<String> includePatterns = new ArrayList<String>(0);
44
45 private Filter<File> filter;
46
47
48
49
50
51
52
53
54 public static RuleSet createFor(String name, Rule... theRules) {
55
56 RuleSet rs = new RuleSet();
57 rs.setName(name);
58 for (Rule rule : theRules) {
59 rs.addRule(rule);
60 }
61 return rs;
62 }
63
64
65
66
67
68
69 public int size() {
70 return rules.size();
71 }
72
73
74
75
76
77
78 public void addRule(Rule rule) {
79 if (rule == null) {
80 throw new IllegalArgumentException("Missing rule");
81 }
82 rules.add(rule);
83 }
84
85
86
87
88
89
90
91 public void addRuleByReference(String ruleSetFileName, Rule rule) {
92 if (StringUtil.isEmpty(ruleSetFileName)) {
93 throw new RuntimeException("Adding a rule by reference is not allowed with an empty rule set file name.");
94 }
95 if (rule == null) {
96 throw new IllegalArgumentException("Cannot add a null rule reference to a RuleSet");
97 }
98 if (!(rule instanceof RuleReference)) {
99 RuleSetReference ruleSetReference = new RuleSetReference();
100 ruleSetReference.setRuleSetFileName(ruleSetFileName);
101 RuleReference ruleReference = new RuleReference();
102 ruleReference.setRule(rule);
103 ruleReference.setRuleSetReference(ruleSetReference);
104 rule = ruleReference;
105 }
106 rules.add(rule);
107 }
108
109
110
111
112
113
114 public Collection<Rule> getRules() {
115 return rules;
116 }
117
118
119
120
121
122
123
124 public boolean usesDFA(Language language) {
125 for (Rule r : rules) {
126 if (r.getLanguage().equals(language)) {
127 if (r.usesDFA()) {
128 return true;
129 }
130 }
131 }
132 return false;
133 }
134
135
136
137
138
139
140
141
142
143
144
145 public Rule getRuleByName(String ruleName) {
146
147 for (Iterator<Rule> i = rules.iterator(); i.hasNext();) {
148 Rule r = i.next();
149 if (r.getName().equals(ruleName)) {
150 return r;
151 }
152 }
153 return null;
154 }
155
156
157
158
159
160
161 public void addRuleSet(RuleSet ruleSet) {
162 rules.addAll(rules.size(), ruleSet.getRules());
163 }
164
165
166
167
168
169
170
171
172
173 public void addRuleSetByReference(RuleSet ruleSet, boolean allRules) {
174 if (StringUtil.isEmpty(ruleSet.getFileName())) {
175 throw new RuntimeException("Adding a rule by reference is not allowed with an empty rule set file name.");
176 }
177 RuleSetReference ruleSetReference = new RuleSetReference(ruleSet.getFileName());
178 ruleSetReference.setAllRules(allRules);
179 for (Rule rule : ruleSet.getRules()) {
180 RuleReference ruleReference = new RuleReference(rule, ruleSetReference);
181 rules.add(ruleReference);
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194
195 public boolean applies(File file) {
196
197 if (filter == null) {
198 Filter<String> regexFilter = Filters.buildRegexFilterIncludeOverExclude(includePatterns, excludePatterns);
199 filter = Filters.toNormalizedFileFilter(regexFilter);
200 }
201
202 return file != null ? filter.filter(file) : true;
203 }
204
205 public void start(RuleContext ctx) {
206 for (Rule rule : rules) {
207 rule.start(ctx);
208 }
209 }
210
211 public void apply(List<? extends Node> acuList, RuleContext ctx) {
212 long start = System.nanoTime();
213 for (Rule rule : rules) {
214 try {
215 if (!rule.usesRuleChain() && applies(rule, ctx.getLanguageVersion())) {
216 rule.apply(acuList, ctx);
217 long end = System.nanoTime();
218 Benchmarker.mark(Benchmark.Rule, rule.getName(), end - start, 1);
219 start = end;
220 }
221 } catch (ThreadDeath td) {
222 throw td;
223 } catch (Throwable t) {
224 LOG.log(Level.WARNING, "Exception applying rule " + rule.getName() + ", continuing with next rule", t);
225 }
226 }
227 }
228
229
230
231
232
233
234
235
236
237 public static boolean applies(Rule rule, LanguageVersion languageVersion) {
238 final LanguageVersion min = rule.getMinimumLanguageVersion();
239 final LanguageVersion max = rule.getMinimumLanguageVersion();
240 return rule.getLanguage().equals(languageVersion.getLanguage())
241 && (min == null || min.compareTo(languageVersion) <= 0)
242 && (max == null || max.compareTo(languageVersion) >= 0);
243 }
244
245 public void end(RuleContext ctx) {
246 for (Rule rule : rules) {
247 rule.end(ctx);
248 }
249 }
250
251
252
253
254 @Override
255 public boolean equals(Object o) {
256 if (!(o instanceof RuleSet)) {
257 return false;
258 }
259
260 if (this == o) {
261 return true;
262 }
263
264 RuleSet ruleSet = (RuleSet) o;
265 return getName().equals(ruleSet.getName()) && getRules().equals(ruleSet.getRules());
266 }
267
268
269
270
271 @Override
272 public int hashCode() {
273 return getName().hashCode() + 13 * getRules().hashCode();
274 }
275
276 public String getFileName() {
277 return fileName;
278 }
279
280 public void setFileName(String fileName) {
281 this.fileName = fileName;
282 }
283
284 public String getName() {
285 return name;
286 }
287
288 public void setName(String name) {
289 this.name = name;
290 }
291
292 public String getDescription() {
293 return description;
294 }
295
296 public void setDescription(String description) {
297 this.description = description;
298 }
299
300 public List<String> getExcludePatterns() {
301 return excludePatterns;
302 }
303
304 public void addExcludePattern(String aPattern) {
305
306 if (excludePatterns.contains(aPattern)) return;
307
308 excludePatterns.add(aPattern);
309 patternsChanged();
310 }
311
312 public void addExcludePatterns(Collection<String> someExcludePatterns) {
313
314 int added = CollectionUtil.addWithoutDuplicates(someExcludePatterns, excludePatterns);
315 if (added > 0) patternsChanged();
316 }
317
318 public void setExcludePatterns(Collection<String> theExcludePatterns) {
319
320 if (excludePatterns.equals(theExcludePatterns)) return;
321
322 excludePatterns.clear();
323 CollectionUtil.addWithoutDuplicates(theExcludePatterns, excludePatterns);
324 patternsChanged();
325 }
326
327 public List<String> getIncludePatterns() {
328 return includePatterns;
329 }
330
331 public void addIncludePattern(String aPattern) {
332
333 if (includePatterns.contains(aPattern)) return;
334
335 includePatterns.add(aPattern);
336 patternsChanged();
337 }
338
339 public void addIncludePatterns(Collection<String> someIncludePatterns) {
340
341 int added = CollectionUtil.addWithoutDuplicates(someIncludePatterns, includePatterns);
342 if (added > 0) patternsChanged();
343 }
344
345 public void setIncludePatterns(Collection<String> theIncludePatterns) {
346
347 if (includePatterns.equals(theIncludePatterns)) return;
348
349 includePatterns.clear();
350 CollectionUtil.addWithoutDuplicates(theIncludePatterns, includePatterns);
351 patternsChanged();
352 }
353
354 private void patternsChanged() {
355 filter = null;
356 }
357
358
359
360
361
362
363
364 public boolean usesTypeResolution(Language language) {
365 for (Rule r : rules) {
366 if (r.getLanguage().equals(language)) {
367 if (r.usesTypeResolution()) {
368 return true;
369 }
370 }
371 }
372 return false;
373 }
374
375
376
377
378
379
380 public void removeDysfunctionalRules(Collection<Rule> collector) {
381
382 Iterator<Rule> iter = rules.iterator();
383
384 while (iter.hasNext()) {
385 Rule rule = iter.next();
386 if (rule.dysfunctionReason() != null) {
387 iter.remove();
388 collector.add(rule);
389 }
390 }
391 }
392
393 }