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