Rule factory and builder

This commit is contained in:
Clément Fournier
2017-09-15 23:02:39 +02:00
parent aa3068fedd
commit 8a048fd18d
2 changed files with 546 additions and 0 deletions

View File

@ -0,0 +1,229 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.ruleset;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PropertyDescriptor;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
/**
* Builds a rule, validating its parameters throughout. The builder can define property descriptors, but not override
* them. For that, use RuleFactory.
*
* @author Clément Fournier
* @since 6.0.0
*/
class RuleBuilder {
private List<PropertyDescriptor<?>> definedProperties = new ArrayList<>();
private String name;
private String clazz;
private Language language;
private LanguageVersion minimumVersion;
private LanguageVersion maximumVersion;
private String since;
private String message;
private String rulesetName;
private String externalInfoUrl;
private String description;
private List<String> examples = new ArrayList<>(1);
private RulePriority priority;
private boolean isDeprecated;
private boolean isUsesDfa;
private boolean isUsesMetrics;
private boolean isUsesTyperesolution;
RuleBuilder(String name, String clazz, String language) {
this.name = name;
language(language);
className(clazz);
}
public void usesDFA(boolean usesDFA) {
isUsesDfa = usesDFA;
}
public void usesMetrics(boolean usesMetrics) {
isUsesMetrics = usesMetrics;
}
public void usesTyperesolution(boolean usesTyperesolution) {
isUsesTyperesolution = usesTyperesolution;
}
private RuleBuilder language(String languageName) {
if (StringUtils.isBlank(languageName)) {
throw new IllegalArgumentException("Blank language attribute");
}
Language lang = LanguageRegistry.findLanguageByTerseName(languageName);
if (lang == null) {
throw new IllegalArgumentException(
"Unknown Language '" + languageName + "' for rule" + name + ", supported Languages are "
+ LanguageRegistry.commaSeparatedTerseNamesForLanguage(LanguageRegistry.findWithRuleSupport()));
}
language = lang;
return this;
}
private RuleBuilder className(String className) {
if (StringUtils.isBlank(className)) {
throw new IllegalArgumentException("The 'class' field of rule can't be null, nor empty.");
}
this.clazz = className;
return this;
}
public RuleBuilder minimumLanguageVersion(String minimum) {
LanguageVersion minimumLanguageVersion = language.getVersion(minimum);
if (minimumLanguageVersion == null) {
throw new IllegalArgumentException("Unknown minimum Language Version '" + minimum
+ "' for Language '" + language.getTerseName() + "' for rule"
+ name
+ "; supported Language Versions are: "
+ LanguageRegistry.commaSeparatedTerseNamesForLanguageVersion(language.getVersions()));
}
minimumVersion = minimumLanguageVersion;
checkLanguageVersionsAreOrdered();
return this;
}
public RuleBuilder maximumLanguageVersion(String maximum) {
LanguageVersion maximumLanguageVersion = language.getVersion(maximum);
if (maximumLanguageVersion == null) {
throw new IllegalArgumentException("Unknown maximum Language Version '" + maximum
+ "' for Language '" + language.getTerseName()
+ "' for Rule " + name
+ "; supported Language Versions are: "
+ LanguageRegistry.commaSeparatedTerseNamesForLanguageVersion(language.getVersions()));
}
maximumVersion = maximumLanguageVersion;
checkLanguageVersionsAreOrdered();
return this;
}
private void checkLanguageVersionsAreOrdered() {
if (minimumVersion != null && maximumVersion != null
&& minimumVersion.compareTo(maximumVersion) > 0) {
throw new IllegalArgumentException(
"The minimum Language Version '" + minimumVersion.getTerseName()
+ "' must be prior to the maximum Language Version '"
+ maximumVersion.getTerseName() + "' for Rule '" + name
+ "'; perhaps swap them around?");
}
}
public RuleBuilder since(String sinceStr) {
if (StringUtils.isNotBlank(sinceStr)) {
since = sinceStr;
}
return this;
}
public void externalInfoUrl(String externalInfoUrl) {
this.externalInfoUrl = externalInfoUrl;
}
public void rulesetName(String rulesetName) {
this.rulesetName = rulesetName;
}
public void message(String message) {
this.message = message;
}
public void defineProperty(PropertyDescriptor<?> descriptor) {
definedProperties.add(descriptor);
}
public void setDeprecated(boolean deprecated) {
isDeprecated = deprecated;
}
public void description(String description) {
this.description = description;
}
public void addExample(String example) {
examples.add(example);
}
public void priority(int priority) {
this.priority = RulePriority.valueOf(priority);
}
public Rule build() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Rule rule = (Rule) RuledefFile.class.getClassLoader().loadClass(clazz).newInstance();
rule.setName(name);
rule.setRuleClass(clazz);
rule.setLanguage(language);
rule.setMinimumLanguageVersion(minimumVersion);
rule.setMaximumLanguageVersion(maximumVersion);
rule.setSince(since);
rule.setMessage(message);
rule.setExternalInfoUrl(externalInfoUrl);
rule.setDeprecated(isDeprecated);
rule.setDescription(description);
rule.setPriority(priority);
for (String example : examples) {
rule.addExample(example);
}
if (isUsesDfa) {
rule.setUsesDFA();
}
if (isUsesMetrics) {
rule.setUsesMetrics();
}
if (isUsesTyperesolution) {
rule.setUsesTypeResolution();
}
for (PropertyDescriptor<?> descriptor : definedProperties) {
rule.definePropertyDescriptor(descriptor);
}
return rule;
}
}

File diff suppressed because it is too large Load Diff