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.Iterator;
    10  import java.util.List;
    11
    12  import net.sourceforge.pmd.util.Benchmark;
    13  import net.sourceforge.pmd.util.filter.Filter;
    14  import net.sourceforge.pmd.util.filter.Filters;
    15
    16
    17  /**
    18   * This class represents a collection of rules.
    19   *
    20   * @see Rule
    21   */
    22  //FUTURE Implement Cloneable and clone()
    23  public class RuleSet {
    24
    25      private List<Rule> rules = new ArrayList<Rule>();
    26      private String fileName;
    27      private String name = "";
    28      private String description = "";
    29      private Language language;
    30      private List<String> excludePatterns = new ArrayList<String>(0);
    31      private List<String> includePatterns = new ArrayList<String>(0);
    32      private Filter<File> filter;
    33
    34      /**
    35       * Returns the number of rules in this ruleset
    36       *
    37       * @return an int representing the number of rules
    38       */
    39      public int size() {
    40          return rules.size();
    41      }
    42
    43      /**
    44       * Add a new rule to this ruleset
    45       *
    46       * @param rule the rule to be added
    47       */
    48      public void addRule(Rule rule) {
    49          if (rule == null) {
    50              throw new RuntimeException("Null Rule reference added to a RuleSet; that's a bug somewhere in PMD");
    51          }
    52          rules.add(rule);
    53      }
    54
    55      /**
    56       * Add a new rule by reference to this ruleset.
    57       *
    58       * @param ruleSetFileName the ruleset which contains the rule
    59       * @param rule the rule to be added
    60       */
    61      public void addRuleByReference(String ruleSetFileName, Rule rule) {
    62          if (ruleSetFileName == null) {
    63              throw new RuntimeException("Adding a rule by reference is not allowed with a null rule set file name.");
    64          }
    65          if (rule == null) {
    66              throw new RuntimeException("Null Rule reference added to a RuleSet; that's a bug somewhere in PMD");
    67          }
    68          if (!(rule instanceof RuleReference)) {
    69          	RuleSetReference ruleSetReference = new RuleSetReference();
    70          	ruleSetReference.setRuleSetFileName(ruleSetFileName);
    71  	        RuleReference ruleReference = new RuleReference();
    72  	        ruleReference.setRule(rule);
    73  	        ruleReference.setRuleSetReference(ruleSetReference);
    74  	        rule = ruleReference;
    75          }
    76          rules.add(rule);
    77      }
    78
    79      /**
    80       * Returns the actual Collection of rules in this ruleset
    81       *
    82       * @return a Collection with the rules. All objects are of type {@link Rule}
    83       */
    84      public Collection<Rule> getRules() {
    85          return rules;
    86      }
    87
    88      /**
    89       * @return true if any rule in the RuleSet needs the DFA layer
    90       */
    91      public boolean usesDFA() {
    92          for (Rule r: rules) {
    93              if (r.usesDFA()) {
    94                  return true;
    95              }
    96          }
    97          return false;
    98      }
    99
    100     /**
    101      * Returns the Rule with the given name
    102      *
    103      * @param ruleName the name of the rule to find
    104      * @return the rule or null if not found
    105      */
    106     public Rule getRuleByName(String ruleName) {
    107         Rule rule = null;
    108         for (Iterator<Rule> i = rules.iterator(); i.hasNext() && (rule == null);) {
    109             Rule r = i.next();
    110             if (r.getName().equals(ruleName)) {
    111                 rule = r;
    112             }
    113         }
    114         return rule;
    115     }
    116
    117     /**
    118      * Add a whole RuleSet to this RuleSet
    119      *
    120      * @param ruleSet the RuleSet to add
    121      */
    122     public void addRuleSet(RuleSet ruleSet) {
    123         rules.addAll(rules.size(), ruleSet.getRules());
    124     }
    125
    126     /**
    127      * Add all rules by reference from one RuleSet to this RuleSet.  The rules
    128      * can be added as individual references, or collectively as an all rule
    129      * reference.
    130      *
    131      * @param ruleSet the RuleSet to add
    132      * @param allRules
    133      */
    134     public void addRuleSetByReference(RuleSet ruleSet, boolean allRules) {
    135     	if (ruleSet.getFileName() == null) {
    136             throw new RuntimeException("Adding a rule by reference is not allowed with a null rule set file name.");
    137     	}
    138     	RuleSetReference ruleSetReference = new RuleSetReference();
    139     	ruleSetReference.setRuleSetFileName(ruleSet.getFileName());
    140     	ruleSetReference.setAllRules(allRules);
    141     	for(Rule rule: ruleSet.getRules()) {
    142     		RuleReference ruleReference = new RuleReference();
    143     		ruleReference.setRule(rule);
    144     		ruleReference.setRuleSetReference(ruleSetReference);
    145     		rules.add(ruleReference);
    146     	}
    147     }
    148
    149    /**
    150     * Check if a given source file should be checked by rules in this RuleSet.  A file
    151     * should not be checked if there is an <code>exclude</code> pattern which matches
    152     * the file, unless there is an <code>include</code> pattern which also matches
    153     * the file.  In other words, <code>include</code> patterns override <code>exclude</code>
    154     * patterns.
    155     *
    156     * @param file the source file to check
    157     * @return <code>true</code> if the file should be checked, <code>false</code> otherwise
    158     */
    159     public boolean applies(File file) {
    160     	// Initialize filter based on patterns
    161         if (filter == null) {
    162         	Filter<String> regexFilter = Filters.buildRegexFilterIncludeOverExclude(includePatterns, excludePatterns);
    163         	filter = Filters.toNormalizedFileFilter(regexFilter);
    164         }
    165
    166         return file != null ? filter.filter(file) : true;
    167     }
    168
    169     public void start(RuleContext ctx) {
    170         for (Rule rule: rules) {
    171             rule.start(ctx);
    172         }
    173     }
    174
    175     public void apply(List acuList, RuleContext ctx) {
    176         long start = System.nanoTime();
    177         for (Rule rule: rules) {
    178             if (!rule.usesRuleChain()) {
    179                 rule.apply(acuList, ctx);
    180                 long end = System.nanoTime();
    181                 Benchmark.mark(Benchmark.TYPE_RULE, rule.getName(), end - start, 1);
    182                 start = end;
    183             }
    184         }
    185     }
    186
    187     public void end(RuleContext ctx) {
    188         for (Rule rule: rules) {
    189             rule.end(ctx);
    190         }
    191     }
    192
    193     /**
    194      * @see java.lang.Object#equals(java.lang.Object)
    195      */
    196     public boolean equals(Object o) {
    197         if ((o == null) || !(o instanceof RuleSet)) {
    198             return false; // Trivial
    199         }
    200
    201         if (this == o) {
    202             return true; // Basic equality
    203         }
    204
    205         RuleSet ruleSet = (RuleSet) o;
    206         return this.getName().equals(ruleSet.getName()) && this.getRules().equals(ruleSet.getRules());
    207     }
    208
    209     /**
    210      * @see java.lang.Object#hashCode()
    211      */
    212     public int hashCode() {
    213         return this.getName().hashCode() + 13 * this.getRules().hashCode();
    214     }
    215
    216     public Language getLanguage() {
    217         return language;
    218     }
    219
    220     public void setLanguage(Language language) {
    221         this.language = language;
    222     }
    223
    224     public String getFileName() {
    225 		return fileName;
    226 	}
    227
    228 	public void setFileName(String fileName) {
    229 		this.fileName = fileName;
    230 	}
    231
    232 	public String getName() {
    233         return name;
    234     }
    235
    236     public void setName(String name) {
    237         this.name = name;
    238     }
    239
    240     public String getDescription() {
    241         return description;
    242     }
    243
    244     public void setDescription(String description) {
    245         this.description = description;
    246     }
    247
    248     public List<String> getExcludePatterns() {
    249         return this.excludePatterns;
    250     }
    251
    252     public void addExcludePattern(String excludePattern) {
    253         this.excludePatterns.add(excludePattern);
    254     }
    255
    256     public void addExcludePatterns(List<String> excludePatterns) {
    257         this.excludePatterns.addAll(excludePatterns);
    258     }
    259
    260     public void setExcludePatterns(List<String> excludePatterns) {
    261     	this.excludePatterns = excludePatterns;
    262     }
    263
    264     public List<String> getIncludePatterns() {
    265         return this.includePatterns;
    266     }
    267
    268     public void addIncludePattern(String includePattern) {
    269         this.includePatterns.add(includePattern);
    270     }
    271
    272     public void addIncludePatterns(List<String> includePatterns) {
    273         this.includePatterns.addAll(includePatterns);
    274     }
    275
    276     public void setIncludePatterns(List<String> includePatterns) {
    277     	this.includePatterns = includePatterns;
    278     }
    279
    280 	public boolean usesTypeResolution() {
    281         for (Rule r: rules) {
    282             if (r.usesTypeResolution()) {
    283                 return true;
    284             }
    285         }
    286         return false;
    287 	}
    288
    289 }