View Javadoc

1   package net.sourceforge.pmd;
2   
3   import java.io.File;
4   import java.util.ArrayList;
5   import java.util.Collection;
6   import java.util.HashSet;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Set;
10  
11  import net.sourceforge.pmd.lang.Language;
12  import net.sourceforge.pmd.lang.ast.Node;
13  
14  /**
15   * Grouping of Rules per Language in a RuleSet.
16   *
17   * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
18   */
19  public class RuleSets {
20      /**
21       * Map of RuleLanguage on RuleSet.
22       */
23      private Collection<RuleSet> ruleSets = new ArrayList<RuleSet>();
24  
25      /**
26       * RuleChain for efficient AST visitation.
27       */
28      private RuleChain ruleChain = new RuleChain();
29  
30      /**
31       * Public constructor.
32       */
33      public RuleSets() {
34      }
35  
36      /**
37       * Public constructor. Add the given rule set.
38       *
39       * @param ruleSet the RuleSet
40       */
41      public RuleSets(RuleSet ruleSet) {
42  		this();
43  		addRuleSet(ruleSet);
44      }
45  
46      /**
47       * Add a ruleset for a language. Only one ruleset can be added for a specific
48       * language. If ruleSet.getLanguage() is null, it is assumed to be a RuleSet of java
49       * rules.
50       *
51       * @param ruleSet the RuleSet
52       */
53      public void addRuleSet(RuleSet ruleSet) {
54  		ruleSets.add(ruleSet);
55  		ruleChain.add(ruleSet);
56      }
57  
58      /**
59       * Get all the RuleSets.
60       *
61       * @return RuleSet[]
62       */
63      public RuleSet[] getAllRuleSets() {
64      	return ruleSets.toArray(new RuleSet[ruleSets.size()]);
65      }
66  
67      public Iterator<RuleSet> getRuleSetsIterator() {
68      	return ruleSets.iterator();
69      }
70  
71      /**
72       * Return all rules from all rulesets.
73       *
74       * @return Set
75       */
76      public Set<Rule> getAllRules() {
77  		Set<Rule> result = new HashSet<Rule>();
78  		for (RuleSet r : ruleSets) {
79  		    result.addAll(r.getRules());
80  		}
81  		return result;
82      }
83  
84      /**
85       * Check if a given source file should be checked by rules in this RuleSets.
86       * 
87       * @param file the source file to check
88       * @return <code>true</code> if the file should be checked, <code>false</code> otherwise
89       */
90      public boolean applies(File file) {
91  		for (RuleSet ruleSet : ruleSets) {
92  		    if (ruleSet.applies(file)) {
93  			return true;
94  		    }
95  		}
96  		return false;
97      }
98  
99      /**
100      * Notify all rules of the start of processing.
101      */
102     public void start(RuleContext ctx) {
103 		for (RuleSet ruleSet : ruleSets) {
104 		    ruleSet.start(ctx);
105 		}
106     }
107 
108     /**
109      * Apply all applicable rules to the compilation units.
110      * Applicable means the language of the rules must match the language
111      * of the source (@see applies).
112      *
113      * @param acuList  the List of compilation units; the type these must have,
114      *                 depends on the source language
115      * @param ctx      the RuleContext
116      * @param language the Language of the source
117      */
118     public void apply(List<Node> acuList, RuleContext ctx, Language language) {
119 		ruleChain.apply(acuList, ctx, language);
120 		for (RuleSet ruleSet : ruleSets) {
121 		    if (ruleSet.applies(ctx.getSourceCodeFile())) {
122 			ruleSet.apply(acuList, ctx);
123 		    }
124 		}
125     }
126 
127     /**
128      * Notify all rules of the end of processing.
129      */
130     public void end(RuleContext ctx) {
131 		for (RuleSet ruleSet : ruleSets) {
132 		    ruleSet.end(ctx);
133 		}
134     }
135 
136     /**
137      * Check if the rules that apply to a source of the given language
138      * use DFA.
139      *
140      * @param language the language of a source
141      * @return true if any rule in the RuleSet needs the DFA layer
142      */
143     public boolean usesDFA(Language language) {
144 		for (RuleSet ruleSet : ruleSets) {
145 		    if (ruleSet.usesDFA(language)) {
146 			return true;
147 		    }
148 		}
149 		return false;
150     }
151 
152     /**
153      * Returns the first Rule found with the given name.
154      *
155      * Note: Since we support multiple languages, rule names 
156 	 * are not expected to be unique within any specific
157 	 * ruleset.
158 	 * 
159      * @param ruleName the exact name of the rule to find
160      * @return the rule or null if not found
161      */
162     public Rule getRuleByName(String ruleName) {
163 		Rule rule = null;
164 		for (Iterator<RuleSet> i = ruleSets.iterator(); i.hasNext() && rule == null;) {
165 		    RuleSet ruleSet = i.next();
166 		    rule = ruleSet.getRuleByName(ruleName);
167 		}
168 		return rule;
169     }
170 
171     public boolean usesTypeResolution(Language language) {
172 		for (RuleSet ruleSet : ruleSets) {
173 		    if (ruleSet.usesTypeResolution(language)) {
174 			return true;
175 		    }
176 		}
177 		return false;
178     }
179     
180 	/**
181 	 * Remove and collect any rules that report problems.
182 	 * 
183 	 * @param collector
184 	 */
185 	public void removeDysfunctionalRules(Collection<Rule> collector) {
186 		
187 		for (RuleSet ruleSet : ruleSets) {
188 		   ruleSet.removeDysfunctionalRules(collector);
189 		}
190 	}
191 }