RuleChain xref
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.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 import net.sourceforge.pmd.lang.Language;
11 import net.sourceforge.pmd.lang.ast.Node;
12 import net.sourceforge.pmd.lang.rule.RuleChainVisitor;
13
14 /**
15 * The RuleChain is a means by which Rules can participate in a uniform
16 * visitation of the AST, and not need perform their own independent visitation.
17 * The RuleChain exists as a means to improve the speed of PMD when there are
18 * many Rules.
19 */
20 public class RuleChain {
21 // Mapping from Language to RuleChainVisitor
22 private final Map<Language, RuleChainVisitor> languageToRuleChainVisitor = new HashMap<Language, RuleChainVisitor>();
23
24 /**
25 * Add all Rules from the given RuleSet which want to participate in the
26 * RuleChain.
27 *
28 * @param ruleSet
29 * The RuleSet to add Rules from.
30 */
31 public void add(RuleSet ruleSet) {
32 for (Rule r : ruleSet.getRules()) {
33 add(ruleSet, r);
34 }
35 }
36
37 /**
38 * Add the given Rule if it wants to participate in the RuleChain.
39 *
40 * @param ruleSet
41 * The RuleSet to which the rule belongs.
42 * @param rule
43 * The Rule to add.
44 */
45 private void add(RuleSet ruleSet, Rule rule) {
46 RuleChainVisitor visitor = getRuleChainVisitor(rule.getLanguage());
47 if (visitor != null) {
48 visitor.add(ruleSet, rule);
49 }
50 }
51
52 /**
53 * Apply the RuleChain to the given Nodes using the given
54 * RuleContext, for those rules using the given Language.
55 *
56 * @param nodes
57 * The Nodes.
58 * @param ctx
59 * The RuleContext.
60 * @param language
61 * The Language.
62 */
63 public void apply(List<Node> nodes, RuleContext ctx, Language language) {
64 RuleChainVisitor visitor = getRuleChainVisitor(language);
65 if (visitor != null) {
66 visitor.visitAll(nodes, ctx);
67 }
68 }
69
70 // Get the RuleChainVisitor for the appropriate Language.
71 private RuleChainVisitor getRuleChainVisitor(Language language) {
72 RuleChainVisitor visitor = languageToRuleChainVisitor.get(language);
73 if (visitor == null) {
74 if (language.getRuleChainVisitorClass() != null) {
75 try {
76 visitor = (RuleChainVisitor) language.getRuleChainVisitorClass().newInstance();
77 } catch (InstantiationException e) {
78 throw new IllegalStateException("Failure to created RuleChainVisitor: "
79 + language.getRuleChainVisitorClass(), e);
80 } catch (IllegalAccessException e) {
81 throw new IllegalStateException("Failure to created RuleChainVisitor: "
82 + language.getRuleChainVisitorClass(), e);
83 }
84 languageToRuleChainVisitor.put(language, visitor);
85 } else {
86 throw new IllegalArgumentException("Language does not have a RuleChainVisitor: " + language);
87 }
88 }
89 return visitor;
90 }
91 }