Modularized numeric and packaged properties
This commit is contained in:
@ -12,13 +12,10 @@ import static net.sourceforge.pmd.PropertyDescriptorField.MAX;
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MIN;
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.NAME;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser;
|
||||
import net.sourceforge.pmd.util.CollectionUtil;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
@ -91,23 +88,36 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final PropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById) {
|
||||
return createWith(valuesById, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a string into a list of values of type {@literal <U>}.
|
||||
* Creates a new property descriptor specifying whether the descriptor is externally defined or not. This is
|
||||
* meant to be implemented by subclasses.
|
||||
*
|
||||
* @param toParse The string to parse
|
||||
* @param delimiter The delimiter to use
|
||||
* @param extractor The function mapping a string to an instance of {@code <U>}
|
||||
* @param <U> The type of the values to parse
|
||||
* @param valuesById The map of values
|
||||
* @param isExternallyDefined Whether the descriptor is externally defined
|
||||
*
|
||||
* @return A list of values
|
||||
* @return A new and initialized {@link PropertyDescriptor}
|
||||
*/
|
||||
protected static <U> List<U> parsePrimitives(String toParse, char delimiter, ValueParser<U> extractor) {
|
||||
String[] values = StringUtil.substringsOf(toParse, delimiter);
|
||||
List<U> result = new ArrayList<>();
|
||||
for (String s : values) {
|
||||
result.add(extractor.valueOf(s));
|
||||
}
|
||||
return result;
|
||||
protected abstract PropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById, boolean isExternallyDefined);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new property descriptor which was defined externally.
|
||||
*
|
||||
* @param valuesById The map of values
|
||||
*
|
||||
* @return A new and initialized {@link PropertyDescriptor}
|
||||
*
|
||||
* @see PropertyDescriptor#isDefinedExternally()
|
||||
*/
|
||||
/* default */
|
||||
final PropertyDescriptor<T> createExternalWith(Map<PropertyDescriptorField, String> valuesById) {
|
||||
return createWith(valuesById, true);
|
||||
}
|
||||
|
||||
|
||||
@ -185,9 +195,11 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
|
||||
|
||||
|
||||
/**
|
||||
* Returns a map of mappings of property descriptor fields
|
||||
* Returns a map describing which fields are required to build an
|
||||
*
|
||||
* @param otherKeys
|
||||
* @param otherValues
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Map<PropertyDescriptorField, Boolean> expectedFieldTypesWith(PropertyDescriptorField[] otherKeys,
|
||||
@ -202,37 +214,4 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final PropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById) {
|
||||
return createWith(valuesById, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new property descriptor which was defined externally.
|
||||
*
|
||||
* @param valuesById The map of values
|
||||
*
|
||||
* @return A new and initialized {@link PropertyDescriptor}
|
||||
*
|
||||
* @see PropertyDescriptor#isDefinedExternally()
|
||||
*/
|
||||
/* default */
|
||||
final PropertyDescriptor<T> createExternalWith(Map<PropertyDescriptorField, String> valuesById) {
|
||||
return createWith(valuesById, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new property descriptor specifying whether the descriptor is externally defined or not. This is
|
||||
* meant to be implemented by subclasses.
|
||||
*
|
||||
* @param valuesById The map of values
|
||||
* @param isExternallyDefined Whether the descriptor is externally defined
|
||||
*
|
||||
* @return A new and initialized {@link PropertyDescriptor}
|
||||
*/
|
||||
protected abstract PropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById, boolean isExternallyDefined);
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MAX;
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MIN;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines a descriptor type whose instance values are required to lie within
|
||||
* specified upper and lower limits.
|
||||
@ -14,6 +19,11 @@ package net.sourceforge.pmd;
|
||||
*/
|
||||
public interface NumericPropertyDescriptor<T> extends PropertyDescriptor<T> {
|
||||
|
||||
Map<PropertyDescriptorField, Boolean> NUMBER_FIELD_TYPES_BY_KEY
|
||||
= AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX},
|
||||
new Boolean[] {true, true});
|
||||
|
||||
|
||||
/**
|
||||
* Returns the maximum value that instances of the property can have.
|
||||
*
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
package net.sourceforge.pmd;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines a property descriptor type whose values can be described by qualified names and thus restricted to only some
|
||||
* packages. These typically use values such as {@link Class} and {@link java.lang.reflect.Method}.
|
||||
@ -14,6 +18,17 @@ package net.sourceforge.pmd;
|
||||
*/
|
||||
public interface PackagedPropertyDescriptor<T> extends PropertyDescriptor<T> {
|
||||
|
||||
/** Required additional fields. */
|
||||
Map<PropertyDescriptorField, Boolean> PACKAGED_FIELD_TYPES_BY_KEY
|
||||
= AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES},
|
||||
new Boolean[] {false});
|
||||
|
||||
/** Delimiter used to separate package names. */
|
||||
char PACKAGE_NAME_DELIMITER = ' ';
|
||||
/** Delimiter used to separate multiple values if this descriptor is multi valued. */
|
||||
char MULTI_VALUE_DELIMITER = '|';
|
||||
|
||||
|
||||
/**
|
||||
* Returns the legal package names.
|
||||
*
|
||||
|
@ -4,14 +4,12 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MAX;
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MIN;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.NumericPropertyDescriptor;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.NumericPropertyModule;
|
||||
|
||||
/**
|
||||
* Base class for multi-valued numeric properties.
|
||||
@ -24,8 +22,7 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
/* default */ abstract class AbstractMultiNumericProperty<T extends Number> extends AbstractMultiValueProperty<T>
|
||||
implements NumericPropertyDescriptor<List<T>> {
|
||||
|
||||
private final T lowerLimit;
|
||||
private final T upperLimit;
|
||||
private final NumericPropertyModule<T> module;
|
||||
|
||||
|
||||
/**
|
||||
@ -39,65 +36,38 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
* @param theUIOrder UI order
|
||||
*
|
||||
* @throws IllegalArgumentException if lower > upper, or one of them is null, or one of the defaults is not between
|
||||
* the bounds
|
||||
* the bounds
|
||||
*/
|
||||
AbstractMultiNumericProperty(String theName, String theDescription, T lower, T upper, List<T> theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
|
||||
lowerLimit = lower;
|
||||
upperLimit = upper;
|
||||
|
||||
checkNumber(lower);
|
||||
checkNumber(upper);
|
||||
|
||||
if (lower.doubleValue() > upper.doubleValue()) {
|
||||
throw new IllegalArgumentException("Lower limit cannot be greater than the upper limit");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void checkNumber(T number) {
|
||||
String error = valueErrorFor(number);
|
||||
if (error != null) {
|
||||
throw new IllegalArgumentException(error);
|
||||
}
|
||||
module = new NumericPropertyModule<>(lower, upper);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String valueErrorFor(T value) {
|
||||
|
||||
double number = value.doubleValue();
|
||||
|
||||
if (number > upperLimit.doubleValue() || number < lowerLimit.doubleValue()) {
|
||||
return value + " is out of range " + AbstractNumericProperty.rangeString(lowerLimit, upperLimit);
|
||||
}
|
||||
|
||||
return null;
|
||||
return module.valueErrorFor(value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number lowerLimit() {
|
||||
return lowerLimit;
|
||||
return module.getLowerLimit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number upperLimit() {
|
||||
return upperLimit;
|
||||
return module.getUpperLimit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addAttributesTo(Map<PropertyDescriptorField, String> attributes) {
|
||||
super.addAttributesTo(attributes);
|
||||
attributes.put(MIN, lowerLimit.toString());
|
||||
attributes.put(MAX, upperLimit.toString());
|
||||
module.addAttributesTo(attributes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,17 +4,12 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.AbstractPropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PackagedPropertyDescriptor;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.PackagedPropertyModule;
|
||||
|
||||
/**
|
||||
* Multi-valued property restricting the type of its values to some packages.
|
||||
@ -25,116 +20,40 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
* @version Refactored June 2017 (6.0.0)
|
||||
*/
|
||||
/* default */ abstract class AbstractMultiPackagedProperty<T> extends AbstractMultiValueProperty<T>
|
||||
implements PackagedPropertyDescriptor<List<T>>{
|
||||
implements PackagedPropertyDescriptor<List<T>> {
|
||||
|
||||
/** Delimiter between values. */
|
||||
protected static final char DELIMITER = '|';
|
||||
/** Required keys in the map. */
|
||||
protected static final Map<PropertyDescriptorField, Boolean> PACKAGED_FIELD_TYPES_BY_KEY
|
||||
= AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES},
|
||||
new Boolean[] {false});
|
||||
private static final char PACKAGE_NAME_DELIMITER = ' ';
|
||||
private String[] legalPackageNames;
|
||||
|
||||
protected final PackagedPropertyModule<T> module;
|
||||
|
||||
|
||||
/**
|
||||
* Create a packaged property.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theLegalPackageNames Legal package names
|
||||
* @param theUIOrder UI order
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theUIOrder UI order
|
||||
* @param module
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
protected AbstractMultiPackagedProperty(String theName, String theDescription, List<T> theDefault,
|
||||
String[] theLegalPackageNames, float theUIOrder,
|
||||
boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
|
||||
checkValidPackages(theDefault, theLegalPackageNames);
|
||||
|
||||
legalPackageNames = theLegalPackageNames;
|
||||
float theUIOrder, boolean isDefinedExternally,
|
||||
PackagedPropertyModule<T> module) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, MULTI_VALUE_DELIMITER, isDefinedExternally);
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates the names of the items against the allowable name prefixes. If
|
||||
* one or more do not have valid prefixes then an exception will be thrown.
|
||||
*
|
||||
* @param items Items to check
|
||||
* @param legalNamePrefixes Legal name prefixes
|
||||
*
|
||||
* @throws IllegalArgumentException if some items are not allowed
|
||||
*/
|
||||
private void checkValidPackages(List<T> items, String[] legalNamePrefixes) {
|
||||
|
||||
Set<String> nameSet = new HashSet<>();
|
||||
|
||||
for (T item : items) {
|
||||
nameSet.add(packageNameOf(item));
|
||||
}
|
||||
|
||||
Set<String> notAllowed = new HashSet<>(nameSet);
|
||||
|
||||
|
||||
for (String name : nameSet) {
|
||||
for (String prefix : legalNamePrefixes) {
|
||||
if (name.startsWith(prefix)) {
|
||||
notAllowed.remove(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (notAllowed.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid items: " + notAllowed);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the package name of the item.
|
||||
*
|
||||
* @param item Item
|
||||
*
|
||||
* @return Package name of the item
|
||||
*/
|
||||
protected abstract String packageNameOf(T item);
|
||||
|
||||
|
||||
@Override
|
||||
protected void addAttributesTo(Map<PropertyDescriptorField, String> attributes) {
|
||||
super.addAttributesTo(attributes);
|
||||
|
||||
attributes.put(LEGAL_PACKAGES, delimitedPackageNames());
|
||||
}
|
||||
|
||||
|
||||
private String delimitedPackageNames() {
|
||||
|
||||
if (legalPackageNames == null || legalPackageNames.length == 0) {
|
||||
return "";
|
||||
}
|
||||
if (legalPackageNames.length == 1) {
|
||||
return legalPackageNames[0];
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(legalPackageNames[0]);
|
||||
for (int i = 1; i < legalPackageNames.length; i++) {
|
||||
sb.append(PACKAGE_NAME_DELIMITER).append(legalPackageNames[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
module.addAttributesTo(attributes);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String valueErrorFor(T value) {
|
||||
|
||||
if (value == null) {
|
||||
String err = super.valueErrorFor(null);
|
||||
if (err != null) {
|
||||
@ -142,38 +61,17 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
}
|
||||
}
|
||||
|
||||
if (legalPackageNames == null) {
|
||||
return null; // no restriction
|
||||
}
|
||||
|
||||
String name = packageNameOf(value);
|
||||
|
||||
for (int i = 0; i < legalPackageNames.length; i++) {
|
||||
if (name.startsWith(legalPackageNames[i])) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return "Disallowed " + itemTypeName() + ": " + name;
|
||||
return module.valueErrorFor(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the type of item.
|
||||
*
|
||||
* @return The name of the type of item
|
||||
*/
|
||||
protected abstract String itemTypeName();
|
||||
|
||||
|
||||
@Override
|
||||
public String[] legalPackageNames() {
|
||||
return Arrays.copyOf(legalPackageNames, legalPackageNames.length);
|
||||
return module.legalPackageNames();
|
||||
}
|
||||
|
||||
|
||||
protected static String[] packageNamesIn(Map<PropertyDescriptorField, String> params) {
|
||||
// TODO
|
||||
return null;
|
||||
protected String[] packageNamesIn(Map<PropertyDescriptorField, String> params) {
|
||||
return module.packageNamesIn(params);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
implements MultiValuePropertyDescriptor<V> {
|
||||
|
||||
|
||||
|
||||
/** The default value. */
|
||||
private final List<V> defaultValue;
|
||||
private final char multiValueDelimiter;
|
||||
|
@ -4,14 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MAX;
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.MIN;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.AbstractPropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.NumericPropertyDescriptor;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.NumericPropertyModule;
|
||||
|
||||
/**
|
||||
* Maintains a pair of boundary limit values between which all values managed by
|
||||
@ -25,12 +22,8 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
/* default */ abstract class AbstractNumericProperty<T extends Number> extends AbstractSingleValueProperty<T>
|
||||
implements NumericPropertyDescriptor<T> {
|
||||
|
||||
public static final Map<PropertyDescriptorField, Boolean> NUMBER_FIELD_TYPES_BY_KEY
|
||||
= AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX},
|
||||
new Boolean[] {true, true});
|
||||
|
||||
private T lowerLimit;
|
||||
private T upperLimit;
|
||||
private final NumericPropertyModule<T> module;
|
||||
|
||||
|
||||
/**
|
||||
@ -50,92 +43,34 @@ import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
|
||||
lowerLimit = lower;
|
||||
upperLimit = upper;
|
||||
|
||||
checkNumber(lower);
|
||||
checkNumber(upper);
|
||||
|
||||
if (lower.doubleValue() > upper.doubleValue()) {
|
||||
throw new IllegalArgumentException("Lower limit cannot be greater than the upper limit");
|
||||
}
|
||||
module = new NumericPropertyModule<>(lower, upper);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void checkNumber(T number) {
|
||||
if (valueErrorFor(number) != null) {
|
||||
throw new IllegalArgumentException(valueErrorFor(number));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string describing any error the value may have when
|
||||
* characterized by the receiver.
|
||||
*
|
||||
* @param value Object
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@Override
|
||||
protected String valueErrorFor(T value) {
|
||||
|
||||
if (value == null) {
|
||||
return "Missing value";
|
||||
}
|
||||
|
||||
double number = value.doubleValue();
|
||||
|
||||
if (number > upperLimit.doubleValue() || number < lowerLimit.doubleValue()) {
|
||||
return value + " is out of range " + rangeString(lowerLimit, upperLimit);
|
||||
}
|
||||
|
||||
return null;
|
||||
return module.valueErrorFor(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string representing the range defined by the two bounds.
|
||||
*
|
||||
* @param low Lower bound
|
||||
* @param up Upper bound
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
/* default */ static String rangeString(Number low, Number up) {
|
||||
return "(" + low + " -> " + up + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the minimum value that instances of the property can have
|
||||
*
|
||||
* @return The minimum value
|
||||
*/
|
||||
@Override
|
||||
public Number lowerLimit() {
|
||||
return lowerLimit;
|
||||
return module.getLowerLimit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the maximum value that instances of the property can have
|
||||
*
|
||||
* @return The maximum value.
|
||||
*/
|
||||
@Override
|
||||
public Number upperLimit() {
|
||||
return upperLimit;
|
||||
return module.getUpperLimit();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addAttributesTo(Map<PropertyDescriptorField, String> attributes) {
|
||||
super.addAttributesTo(attributes);
|
||||
attributes.put(MIN, lowerLimit.toString());
|
||||
attributes.put(MAX, upperLimit.toString());
|
||||
module.addAttributesTo(attributes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,16 +4,11 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pmd.AbstractPropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PackagedPropertyDescriptor;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.PackagedPropertyModule;
|
||||
|
||||
/**
|
||||
* Property which restricts the type of its values to some packages. If
|
||||
@ -27,151 +22,49 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
/* default */ abstract class AbstractPackagedProperty<T> extends AbstractSingleValueProperty<T>
|
||||
implements PackagedPropertyDescriptor<T> {
|
||||
|
||||
/** Required keys in the map. */
|
||||
protected static final Map<PropertyDescriptorField, Boolean> PACKAGED_FIELD_TYPES_BY_KEY
|
||||
= AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES},
|
||||
new Boolean[] {false});
|
||||
private static final char PACKAGE_NAME_DELIMITER = ' ';
|
||||
private static Pattern packageNamePattern = Pattern.compile("(\\w+)(\\.\\w+)*");
|
||||
|
||||
private String[] legalPackageNames;
|
||||
protected final PackagedPropertyModule<T> module;
|
||||
|
||||
|
||||
/**
|
||||
* Create a packaged property.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theLegalPackageNames Legal package names
|
||||
* @param theUIOrder UI order
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theUIOrder UI order
|
||||
* @param module
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
protected AbstractPackagedProperty(String theName, String theDescription, T theDefault,
|
||||
String[] theLegalPackageNames, float theUIOrder, boolean isDefinedExternally) {
|
||||
float theUIOrder, boolean isDefinedExternally,
|
||||
PackagedPropertyModule<T> module) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
|
||||
checkValidPackages(theDefault, theLegalPackageNames);
|
||||
|
||||
legalPackageNames = theLegalPackageNames;
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates the names of the items against the allowable name prefixes. If
|
||||
* one or more do not have valid prefixes then an exception will be thrown.
|
||||
*
|
||||
* @param item The item to check
|
||||
* @param legalNamePrefixes The legal name prefixes
|
||||
*
|
||||
* @throws IllegalArgumentException If the item's package is not whitelisted.
|
||||
*/
|
||||
private void checkValidPackages(T item, String[] legalNamePrefixes) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String name = packageNameOf(item);
|
||||
|
||||
for (String legalNamePrefixe : legalNamePrefixes) {
|
||||
if (name.startsWith(legalNamePrefixe)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Invalid item: " + item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the package name of the item.
|
||||
*
|
||||
* @param item Item
|
||||
*
|
||||
* @return Package name of the item
|
||||
*/
|
||||
protected abstract String packageNameOf(T item);
|
||||
|
||||
|
||||
@Override
|
||||
protected void addAttributesTo(Map<PropertyDescriptorField, String> attributes) {
|
||||
super.addAttributesTo(attributes);
|
||||
|
||||
attributes.put(LEGAL_PACKAGES, delimitedPackageNames());
|
||||
}
|
||||
|
||||
|
||||
private String delimitedPackageNames() {
|
||||
|
||||
if (legalPackageNames == null || legalPackageNames.length == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (legalPackageNames.length == 1) {
|
||||
return legalPackageNames[0];
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(legalPackageNames[0]);
|
||||
for (int i = 1; i < legalPackageNames.length; i++) {
|
||||
sb.append(PACKAGE_NAME_DELIMITER).append(legalPackageNames[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
module.addAttributesTo(attributes);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String valueErrorFor(T value) {
|
||||
|
||||
if (value == null) {
|
||||
String err = super.valueErrorFor(null);
|
||||
if (err != null) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (legalPackageNames == null) {
|
||||
return null; // no restriction
|
||||
}
|
||||
|
||||
String name = packageNameOf(value);
|
||||
|
||||
for (int i = 0; i < legalPackageNames.length; i++) {
|
||||
if (name.startsWith(legalPackageNames[i])) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return "Disallowed " + itemTypeName() + ": " + name;
|
||||
return module.valueErrorFor(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the type of item.
|
||||
*
|
||||
* @return The name of the type of item
|
||||
*/
|
||||
protected abstract String itemTypeName();
|
||||
|
||||
|
||||
@Override
|
||||
public String[] legalPackageNames() {
|
||||
return Arrays.copyOf(legalPackageNames, legalPackageNames.length); // defensive copy
|
||||
return module.legalPackageNames();
|
||||
}
|
||||
|
||||
|
||||
protected static String[] packageNamesIn(Map<PropertyDescriptorField, String> params) {
|
||||
String[] packageNames = StringUtil.substringsOf(params.get(LEGAL_PACKAGES),
|
||||
PACKAGE_NAME_DELIMITER);
|
||||
|
||||
for (String name : packageNames) {
|
||||
if (!packageNamePattern.matcher(name).matches()) {
|
||||
throw new IllegalArgumentException("One name is not a package: '" + name + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return packageNames;
|
||||
protected String[] packageNamesIn(Map<PropertyDescriptorField, String> params) {
|
||||
return module.packageNamesIn(params);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
|
||||
/**
|
||||
* Defines a property type that supports multiple Boolean values.
|
||||
@ -28,7 +29,7 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty<Boole
|
||||
char delimiter = delimiterIn(valuesById);
|
||||
return new BooleanMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER),
|
||||
Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER),
|
||||
0f,
|
||||
isDefinedExternally);
|
||||
}
|
||||
@ -48,6 +49,13 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty<Boole
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private BooleanMultiProperty(String theName, String theDescription, List<Boolean> defaultValues,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a list of defaults.
|
||||
*
|
||||
@ -61,12 +69,6 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty<Boole
|
||||
}
|
||||
|
||||
|
||||
private BooleanMultiProperty(String theName, String theDescription, List<Boolean> defaultValues,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Boolean createFrom(String toParse) {
|
||||
return BOOLEAN_PARSER.valueOf(toParse);
|
||||
|
@ -49,6 +49,12 @@ public final class BooleanProperty extends AbstractSingleValueProperty<Boolean>
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -62,10 +68,6 @@ public final class BooleanProperty extends AbstractSingleValueProperty<Boolean>
|
||||
}
|
||||
|
||||
|
||||
private BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Boolean> type() {
|
||||
return Boolean.class;
|
||||
|
@ -11,6 +11,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
/**
|
||||
@ -29,7 +30,7 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty<Cha
|
||||
char delimiter = delimiterIn(valuesById);
|
||||
return new CharacterMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER),
|
||||
Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER),
|
||||
0.0f,
|
||||
delimiter,
|
||||
isDefinedExternally);
|
||||
@ -53,6 +54,7 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty<Cha
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private CharacterMultiProperty(String theName, String theDescription, List<Character> defaultValues, float theUIOrder,
|
||||
char delimiter, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally);
|
||||
|
@ -49,19 +49,7 @@ public final class CharacterProperty extends AbstractSingleValueProperty<Charact
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
public CharacterProperty(String theName, String theDescription, Character theDefault, float theUIOrder) {
|
||||
this(theName, theDescription, theDefault, theUIOrder, false);
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private CharacterProperty(String theName, String theDescription, Character theDefault, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
@ -81,6 +69,19 @@ public final class CharacterProperty extends AbstractSingleValueProperty<Charact
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
public CharacterProperty(String theName, String theDescription, Character theDefault, float theUIOrder) {
|
||||
this(theName, theDescription, theDefault, theUIOrder, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Character> type() {
|
||||
return Character.class;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY;
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.DOUBLE_PARSER;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -29,7 +28,8 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty<Doub
|
||||
public DoubleMultiProperty createWith(Map<PropertyDescriptorField, String> valuesById, boolean isDefinedExternally) {
|
||||
String[] minMax = minMaxFrom(valuesById);
|
||||
char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER);
|
||||
List<Double> defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER);
|
||||
List<Double> defaultValues = ValueParser.Companion.parsePrimitives(numericDefaultValueIn(valuesById),
|
||||
delimiter, DOUBLE_PARSER);
|
||||
return new DoubleMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
DOUBLE_PARSER.valueOf(minMax[0]),
|
||||
@ -59,6 +59,13 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty<Doub
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private DoubleMultiProperty(String theName, String theDescription, Double min, Double max,
|
||||
List<Double> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a list of defaults.
|
||||
*
|
||||
@ -76,11 +83,6 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty<Doub
|
||||
this(theName, theDescription, min, max, defaultValues, theUIOrder, false);
|
||||
}
|
||||
|
||||
private DoubleMultiProperty(String theName, String theDescription, Double min, Double max,
|
||||
List<Double> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Double> type() {
|
||||
|
@ -57,6 +57,25 @@ public final class DoubleProperty extends AbstractNumericProperty<Double> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a String into a Double.
|
||||
*
|
||||
* @param numberString String to parse
|
||||
*
|
||||
* @return Parsed Double
|
||||
*/
|
||||
public static Double doubleFrom(String numberString) {
|
||||
return Double.valueOf(numberString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor that limits itself to a single value within the specified limits.
|
||||
*
|
||||
@ -75,24 +94,6 @@ public final class DoubleProperty extends AbstractNumericProperty<Double> {
|
||||
}
|
||||
|
||||
|
||||
private DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a String into a Double.
|
||||
*
|
||||
* @param numberString String to parse
|
||||
*
|
||||
* @return Parsed Double
|
||||
*/
|
||||
public static Double doubleFrom(String numberString) {
|
||||
return Double.valueOf(numberString);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Double> type() {
|
||||
return Double.class;
|
||||
|
@ -64,20 +64,6 @@ public final class EnumeratedMultiProperty<E> extends AbstractMultiValueProperty
|
||||
selection(choiceIndices, theChoices), valueType, theUIOrder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor using a map to define the label-value mappings. The default values are specified with a list.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param choices Map of labels to values
|
||||
* @param defaultValues List of default values
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
public EnumeratedMultiProperty(String theName, String theDescription, Map<String, E> choices,
|
||||
List<E> defaultValues, Class<E> valueType, float theUIOrder) {
|
||||
this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false);
|
||||
}
|
||||
|
||||
|
||||
private EnumeratedMultiProperty(String theName, String theDescription, Map<String, E> choices,
|
||||
List<E> defaultValues, Class<E> valueType, float theUIOrder,
|
||||
@ -113,6 +99,21 @@ public final class EnumeratedMultiProperty<E> extends AbstractMultiValueProperty
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a map to define the label-value mappings. The default values are specified with a list.
|
||||
*
|
||||
* @param theName Name
|
||||
* @param theDescription Description
|
||||
* @param choices Map of labels to values
|
||||
* @param defaultValues List of default values
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
public EnumeratedMultiProperty(String theName, String theDescription, Map<String, E> choices,
|
||||
List<E> defaultValues, Class<E> valueType, float theUIOrder) {
|
||||
this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, E> mappings() {
|
||||
return choicesByLabel; // unmodifiable
|
||||
|
@ -71,6 +71,16 @@ public final class EnumeratedProperty<E> extends AbstractSingleValueProperty<E>
|
||||
}
|
||||
|
||||
|
||||
private EnumeratedProperty(String theName, String theDescription, Map<String, E> labelsToChoices,
|
||||
E defaultValue, Class<E> valueType, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally);
|
||||
|
||||
this.valueType = valueType;
|
||||
choicesByLabel = Collections.unmodifiableMap(labelsToChoices);
|
||||
labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a map to define the label-value mappings.
|
||||
*
|
||||
@ -86,16 +96,6 @@ public final class EnumeratedProperty<E> extends AbstractSingleValueProperty<E>
|
||||
}
|
||||
|
||||
|
||||
private EnumeratedProperty(String theName, String theDescription, Map<String, E> labelsToChoices,
|
||||
E defaultValue, Class<E> valueType, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally);
|
||||
|
||||
this.valueType = valueType;
|
||||
choicesByLabel = Collections.unmodifiableMap(labelsToChoices);
|
||||
labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<E> type() {
|
||||
return valueType;
|
||||
|
@ -46,10 +46,12 @@ public final class FileProperty extends AbstractSingleValueProperty<File> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private FileProperty(String theName, String theDescription, File theDefault, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<File> type() {
|
||||
return File.class;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY;
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.FLOAT_PARSER;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -13,6 +12,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
|
||||
/**
|
||||
* Multi-valued float property.
|
||||
@ -30,7 +30,7 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty<Float
|
||||
boolean isDefinedExternally) {
|
||||
String[] minMax = minMaxFrom(valuesById);
|
||||
char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER);
|
||||
List<Float> defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER);
|
||||
List<Float> defaultValues = Companion.parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER);
|
||||
return new FloatMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
FLOAT_PARSER.valueOf(minMax[0]),
|
||||
@ -60,6 +60,13 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty<Float
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private FloatMultiProperty(String theName, String theDescription, Float min, Float max,
|
||||
List<Float> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a list of defaults.
|
||||
*
|
||||
@ -78,12 +85,6 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty<Float
|
||||
}
|
||||
|
||||
|
||||
private FloatMultiProperty(String theName, String theDescription, Float min, Float max,
|
||||
List<Float> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Float> type() {
|
||||
return Float.class;
|
||||
|
@ -57,6 +57,13 @@ public final class FloatProperty extends AbstractNumericProperty<Float> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor that limits itself to a single value within the specified limits.
|
||||
*
|
||||
@ -75,12 +82,6 @@ public final class FloatProperty extends AbstractNumericProperty<Float> {
|
||||
}
|
||||
|
||||
|
||||
private FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Float> type() {
|
||||
return Float.class;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY;
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.INTEGER_PARSER;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -13,6 +12,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
|
||||
/**
|
||||
* Multi-valued integer property.
|
||||
@ -30,7 +30,7 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty<Int
|
||||
isDefinedExternally) {
|
||||
String[] minMax = minMaxFrom(valuesById);
|
||||
char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER);
|
||||
List<Integer> defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER);
|
||||
List<Integer> defaultValues = Companion.parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER);
|
||||
return new IntegerMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
INTEGER_PARSER.valueOf(minMax[0]),
|
||||
@ -60,6 +60,14 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty<Int
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max,
|
||||
List<Integer> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a list of defaults.
|
||||
*
|
||||
@ -79,13 +87,6 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty<Int
|
||||
}
|
||||
|
||||
|
||||
private IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max,
|
||||
List<Integer> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Integer> type() {
|
||||
return Integer.class;
|
||||
|
@ -53,8 +53,9 @@ public final class IntegerProperty extends AbstractNumericProperty<Integer> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY;
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.LONG_PARSER;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -13,6 +12,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
|
||||
/**
|
||||
* Multi-valued long property.
|
||||
@ -29,7 +29,7 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty<Long>
|
||||
public LongMultiProperty createWith(Map<PropertyDescriptorField, String> valuesById, boolean isDefinedExternally) {
|
||||
String[] minMax = minMaxFrom(valuesById);
|
||||
char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER);
|
||||
List<Long> defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER);
|
||||
List<Long> defaultValues = Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER);
|
||||
return new LongMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
LONG_PARSER.valueOf(minMax[0]),
|
||||
@ -59,6 +59,13 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty<Long>
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private LongMultiProperty(String theName, String theDescription, Long min, Long max,
|
||||
List<Long> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor using a list of defaults.
|
||||
*
|
||||
@ -77,12 +84,6 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty<Long>
|
||||
}
|
||||
|
||||
|
||||
private LongMultiProperty(String theName, String theDescription, Long min, Long max,
|
||||
List<Long> defaultValues, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Long> type() {
|
||||
return Long.class;
|
||||
|
@ -58,6 +58,13 @@ public final class LongProperty extends AbstractNumericProperty<Long> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor that limits itself to a single value within the specified limits.
|
||||
*
|
||||
@ -74,11 +81,6 @@ public final class LongProperty extends AbstractNumericProperty<Long> {
|
||||
this(theName, theDescription, min, max, theDefault, theUIOrder, false);
|
||||
}
|
||||
|
||||
private LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<Long> type() {
|
||||
|
@ -4,15 +4,16 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.METHOD_PARSER;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule;
|
||||
|
||||
/**
|
||||
* Defines a property type that can specify multiple methods to use as part of a
|
||||
@ -40,6 +41,7 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty<Met
|
||||
0f,
|
||||
isDefinedExternally);
|
||||
}
|
||||
|
||||
}; // @formatter:on
|
||||
|
||||
|
||||
@ -66,9 +68,11 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty<Met
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private MethodMultiProperty(String theName, String theDescription, List<Method> theDefaults,
|
||||
String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder, isDefinedExternally);
|
||||
super(theName, theDescription, theDefaults, theUIOrder, isDefinedExternally,
|
||||
new MethodPropertyModule(legalPackageNames, theDefaults));
|
||||
}
|
||||
|
||||
|
||||
@ -82,47 +86,31 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty<Met
|
||||
* @param theUIOrder float
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* @deprecated will be removed in 7.O.O
|
||||
*/
|
||||
public MethodMultiProperty(String theName, String theDescription, String methodDefaults,
|
||||
String[] legalPackageNames, float theUIOrder) {
|
||||
this(theName, theDescription, methodsFrom(methodDefaults), legalPackageNames, theUIOrder, false);
|
||||
this(theName, theDescription,
|
||||
methodsFrom(methodDefaults),
|
||||
legalPackageNames, theUIOrder,
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
public static List<Method> methodsFrom(String methodsStr) {
|
||||
String[] values = StringUtil.substringsOf(methodsStr, DELIMITER);
|
||||
|
||||
List<Method> methods = new ArrayList<>(values.length);
|
||||
for (String name : values) {
|
||||
methods.add(MethodProperty.methodFrom(name, MethodProperty.CLASS_METHOD_DELIMITER,
|
||||
MethodProperty.METHOD_ARG_DELIMITER));
|
||||
}
|
||||
return methods;
|
||||
private static List<Method> methodsFrom(String valueString) {
|
||||
return ValueParser.Companion.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, METHOD_PARSER);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String asString(Method value) {
|
||||
return value == null ? "" : MethodProperty.asStringFor(value);
|
||||
return MethodPropertyModule.asString(value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Method createFrom(String toParse) {
|
||||
return MethodProperty.methodFrom(toParse, MethodProperty.CLASS_METHOD_DELIMITER,
|
||||
MethodProperty.METHOD_ARG_DELIMITER);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String packageNameOf(Method item) {
|
||||
return item.getDeclaringClass().getName() + '.' + item.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String itemTypeName() {
|
||||
return "method";
|
||||
return METHOD_PARSER.valueOf(toParse);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,14 +4,16 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.properties;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.properties.ValueParser.METHOD_PARSER;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.util.ClassUtil;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
import net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule;
|
||||
|
||||
/**
|
||||
* Defines a property type that can specify a single method to use as part of a
|
||||
@ -26,10 +28,7 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
*/
|
||||
public final class MethodProperty extends AbstractPackagedProperty<Method> {
|
||||
|
||||
|
||||
public static final char CLASS_METHOD_DELIMITER = '#';
|
||||
public static final char METHOD_ARG_DELIMITER = ',';
|
||||
public static final char[] METHOD_GROUP_DELIMITERS = {'(', ')'};
|
||||
/** Factory. */
|
||||
public static final PropertyDescriptorFactory<Method> FACTORY // @formatter:off
|
||||
= new SingleValuePropertyDescriptorFactory<Method>(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) {
|
||||
@Override
|
||||
@ -37,22 +36,37 @@ public final class MethodProperty extends AbstractPackagedProperty<Method> {
|
||||
char delimiter = delimiterIn(valuesById);
|
||||
return new MethodProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
methodFrom(defaultValueIn(valuesById)),
|
||||
METHOD_PARSER.valueOf(defaultValueIn(valuesById)),
|
||||
legalPackageNamesIn(valuesById, delimiter),
|
||||
0f,
|
||||
isDefinedExternally);
|
||||
}
|
||||
}; // @formatter:on
|
||||
private static final String ARRAY_FLAG = "[]";
|
||||
private static final Map<Class<?>, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for MethodProperty.
|
||||
*
|
||||
* @param theName Name of the property
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param legalPackageNames Legal packages
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames,
|
||||
float theUIOrder) {
|
||||
this(theName, theDescription, theDefault, legalPackageNames, theUIOrder, false);
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally,
|
||||
new MethodPropertyModule(legalPackageNames, Collections.singletonList(theDefault)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for MethodProperty using a string as a default value.
|
||||
*
|
||||
@ -61,104 +75,19 @@ public final class MethodProperty extends AbstractPackagedProperty<Method> {
|
||||
* @param defaultMethodStr Default value, that will be parsed into a Method object
|
||||
* @param legalPackageNames Legal packages
|
||||
* @param theUIOrder UI order
|
||||
*
|
||||
* @deprecated will be removed in 7.0.0
|
||||
*/
|
||||
public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames,
|
||||
float theUIOrder) {
|
||||
this(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder, false);
|
||||
this(theName, theDescription, METHOD_PARSER.valueOf(defaultMethodStr),
|
||||
legalPackageNames, theUIOrder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for MethodProperty.
|
||||
*
|
||||
* @param theName Name of the property
|
||||
* @param theDescription Description
|
||||
* @param theDefault Default value
|
||||
* @param legalPackageNames Legal packages
|
||||
* @param theUIOrder UI order
|
||||
*/
|
||||
private MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames,
|
||||
float theUIOrder, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, theDefault, legalPackageNames, theUIOrder, isDefinedExternally);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String asString(Method value) {
|
||||
return value == null ? "" : asStringFor(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the value of `method' as a string that can be easily recognized
|
||||
* and parsed when we see it again.
|
||||
*
|
||||
* @param method the method to convert
|
||||
*
|
||||
* @return the string value
|
||||
*/
|
||||
public static String asStringFor(Method method) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
asStringOn(method, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the method signature onto the specified buffer.
|
||||
*
|
||||
* @param method Method
|
||||
* @param sb StringBuilder
|
||||
*/
|
||||
public static void asStringOn(Method method, StringBuilder sb) {
|
||||
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
|
||||
sb.append(shortestNameFor(clazz));
|
||||
sb.append(CLASS_METHOD_DELIMITER);
|
||||
sb.append(method.getName());
|
||||
|
||||
sb.append(METHOD_GROUP_DELIMITERS[0]);
|
||||
|
||||
Class<?>[] argTypes = method.getParameterTypes();
|
||||
if (argTypes.length == 0) {
|
||||
sb.append(METHOD_GROUP_DELIMITERS[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
serializedTypeIdOn(argTypes[0], sb);
|
||||
for (int i = 1; i < argTypes.length; i++) {
|
||||
sb.append(METHOD_ARG_DELIMITER);
|
||||
serializedTypeIdOn(argTypes[i], sb);
|
||||
}
|
||||
sb.append(METHOD_GROUP_DELIMITERS[1]);
|
||||
}
|
||||
|
||||
|
||||
private static String shortestNameFor(Class<?> cls) {
|
||||
String compactName = TYPE_SHORTCUTS.get(cls);
|
||||
return compactName == null ? cls.getName() : compactName;
|
||||
}
|
||||
|
||||
|
||||
private static void serializedTypeIdOn(Class<?> type, StringBuilder sb) {
|
||||
|
||||
Class<?> arrayType = type.getComponentType();
|
||||
if (arrayType == null) {
|
||||
sb.append(shortestNameFor(type));
|
||||
return;
|
||||
}
|
||||
sb.append(shortestNameFor(arrayType)).append(ARRAY_FLAG);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String packageNameOf(Method method) {
|
||||
return method == null ? null : method.getDeclaringClass().getName() + '.' + method.getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String itemTypeName() {
|
||||
return "method";
|
||||
return MethodPropertyModule.asString(value);
|
||||
}
|
||||
|
||||
|
||||
@ -170,118 +99,8 @@ public final class MethodProperty extends AbstractPackagedProperty<Method> {
|
||||
|
||||
@Override
|
||||
public Method createFrom(String valueString) throws IllegalArgumentException {
|
||||
return methodFrom(valueString);
|
||||
return METHOD_PARSER.valueOf(valueString);
|
||||
}
|
||||
|
||||
|
||||
private static Class<?> typeFor(String typeName) {
|
||||
|
||||
Class<?> type;
|
||||
|
||||
if (typeName.endsWith(ARRAY_FLAG)) {
|
||||
String arrayTypeName = typeName.substring(0, typeName.length() - ARRAY_FLAG.length());
|
||||
type = typeFor(arrayTypeName); // recurse
|
||||
return Array.newInstance(type, 0).getClass(); // TODO is there a
|
||||
// better way to get
|
||||
// an array type?
|
||||
}
|
||||
|
||||
type = ClassUtil.getTypeFor(typeName); // try shortcut first
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
try {
|
||||
return Class.forName(typeName);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the method specified within the string argument after parsing out
|
||||
* its source class and any optional arguments. Callers need to specify the
|
||||
* delimiters expected between the various elements. I.e.:
|
||||
*
|
||||
* <p>"String#isEmpty()" "String#indexOf(int)" "String#substring(int,int)"
|
||||
*
|
||||
* <p>If a method isn't part of the specified class we will walk up any
|
||||
* superclasses to Object to try and find it.
|
||||
*
|
||||
* <p>If the classes are listed in the ClassUtil class within in Typemaps then
|
||||
* you likely can avoid specifying fully-qualified class names per the above
|
||||
* example.
|
||||
*
|
||||
* <p>Returns null if a matching method cannot be found.
|
||||
*
|
||||
* @param methodNameAndArgTypes Method name (with its declaring class and arguments)
|
||||
* @param classMethodDelimiter Delimiter between the class and method names
|
||||
* @param methodArgDelimiter Method arguments delimiter
|
||||
*
|
||||
* @return Method
|
||||
*/
|
||||
public static Method methodFrom(String methodNameAndArgTypes, char classMethodDelimiter, char methodArgDelimiter) {
|
||||
|
||||
// classname#methodname(arg1,arg2)
|
||||
// 0 1 2
|
||||
|
||||
int delimPos0 = -1;
|
||||
if (methodNameAndArgTypes != null) {
|
||||
delimPos0 = methodNameAndArgTypes.indexOf(classMethodDelimiter);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (delimPos0 < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String className = methodNameAndArgTypes.substring(0, delimPos0);
|
||||
Class<?> type = ClassUtil.getTypeFor(className);
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int delimPos1 = methodNameAndArgTypes.indexOf(METHOD_GROUP_DELIMITERS[0]);
|
||||
if (delimPos1 < 0) {
|
||||
String methodName = methodNameAndArgTypes.substring(delimPos0 + 1);
|
||||
return ClassUtil.methodFor(type, methodName, ClassUtil.EMPTY_CLASS_ARRAY);
|
||||
}
|
||||
|
||||
String methodName = methodNameAndArgTypes.substring(delimPos0 + 1, delimPos1);
|
||||
if (StringUtil.isEmpty(methodName)) {
|
||||
return null;
|
||||
} // missing method name?
|
||||
|
||||
int delimPos2 = methodNameAndArgTypes.indexOf(METHOD_GROUP_DELIMITERS[1]);
|
||||
if (delimPos2 < 0) {
|
||||
return null;
|
||||
} // error!
|
||||
|
||||
String argTypesStr = methodNameAndArgTypes.substring(delimPos1 + 1, delimPos2);
|
||||
if (StringUtil.isEmpty(argTypesStr)) {
|
||||
return ClassUtil.methodFor(type, methodName, ClassUtil.EMPTY_CLASS_ARRAY);
|
||||
} // no arg(s)
|
||||
|
||||
String[] argTypeNames = StringUtil.substringsOf(argTypesStr, methodArgDelimiter);
|
||||
Class<?>[] argTypes = new Class[argTypeNames.length];
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
argTypes[i] = typeFor(argTypeNames[i]);
|
||||
}
|
||||
|
||||
return ClassUtil.methodFor(type, methodName, argTypes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a String into a Method.
|
||||
*
|
||||
* @param methodStr String to parse
|
||||
*
|
||||
* @return Parsed Method
|
||||
*/
|
||||
public static Method methodFrom(String methodStr) {
|
||||
return methodFrom(methodStr, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public abstract class MultiValuePropertyDescriptorFactory<T> extends AbstractPro
|
||||
|
||||
@Override
|
||||
protected abstract MultiValuePropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById,
|
||||
boolean isDefinedExternally);
|
||||
boolean isDefinedExternally);
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -11,9 +11,12 @@ import java.util.Map;
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
|
||||
/**
|
||||
* Utility class allowing to find the factory of a specific type of descriptor. That's used to define descriptors in
|
||||
* the xml, eg for xpath rules.
|
||||
*
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
public class PropertyDescriptorUtil {
|
||||
public final class PropertyDescriptorUtil {
|
||||
|
||||
private static final Map<String, PropertyDescriptorFactory<?>> DESCRIPTOR_FACTORIES_BY_TYPE;
|
||||
|
||||
@ -38,8 +41,8 @@ public class PropertyDescriptorUtil {
|
||||
temp.put("Double", DoubleProperty.FACTORY);
|
||||
temp.put("List<Double>", DoubleMultiProperty.FACTORY);
|
||||
|
||||
// temp.put("Enum", EnumeratedProperty.FACTORY);
|
||||
// temp.put("List<Enum>", EnumeratedMultiProperty.FACTORY);
|
||||
// temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf implement that
|
||||
// temp.put("List<Enum>", EnumeratedMultiProperty.FACTORY);
|
||||
|
||||
temp.put("Class", TypeProperty.FACTORY);
|
||||
temp.put("List<Class>", TypeMultiProperty.FACTORY);
|
||||
@ -55,14 +58,28 @@ public class PropertyDescriptorUtil {
|
||||
private PropertyDescriptorUtil() { }
|
||||
|
||||
|
||||
/**
|
||||
* Gets the factory for the descriptor identified by the string id.
|
||||
*
|
||||
* @param typeId The identifier of the type
|
||||
*
|
||||
* @return The factory used to build new instances of a descriptor
|
||||
*/
|
||||
public static PropertyDescriptorFactory<?> factoryFor(String typeId) {
|
||||
return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the string representation of this type, as it should be given when defining a descriptor in the xml.
|
||||
*
|
||||
* @param valueType The type to look for
|
||||
* @param multiValue Whether the descriptor is multivalued or not
|
||||
*
|
||||
* @return The type id
|
||||
*/
|
||||
public static String typeIdFor(Class<?> valueType, boolean multiValue) {
|
||||
|
||||
// a reverse lookup, not very efficient but fine for now
|
||||
for (Map.Entry<String, PropertyDescriptorFactory<?>> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) {
|
||||
if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) {
|
||||
return entry.getKey();
|
||||
|
@ -20,13 +20,13 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor;
|
||||
*/
|
||||
public abstract class SingleValuePropertyDescriptorFactory<T> extends AbstractPropertyDescriptorFactory<T> {
|
||||
|
||||
public SingleValuePropertyDescriptorFactory(Class<T> theValueType) {
|
||||
/* default */ SingleValuePropertyDescriptorFactory(Class<T> theValueType) {
|
||||
super(theValueType);
|
||||
}
|
||||
|
||||
|
||||
public SingleValuePropertyDescriptorFactory(Class<T> theValueType,
|
||||
Map<PropertyDescriptorField, Boolean> additionalFieldTypesByKey) {
|
||||
/* default */ SingleValuePropertyDescriptorFactory(Class<T> theValueType,
|
||||
Map<PropertyDescriptorField, Boolean> additionalFieldTypesByKey) {
|
||||
super(theValueType, additionalFieldTypesByKey);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.PropertyDescriptorFactory;
|
||||
import net.sourceforge.pmd.PropertyDescriptorField;
|
||||
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
|
||||
import net.sourceforge.pmd.util.StringUtil;
|
||||
|
||||
/**
|
||||
@ -31,7 +32,7 @@ public final class StringMultiProperty extends AbstractMultiValueProperty<String
|
||||
char delimiter = delimiterIn(valuesById);
|
||||
return new StringMultiProperty(nameIn(valuesById),
|
||||
descriptionIn(valuesById),
|
||||
parsePrimitives(defaultValueIn(valuesById), delimiter, STRING_PARSER),
|
||||
Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, STRING_PARSER),
|
||||
0.0f,
|
||||
delimiter,
|
||||
isDefinedExternally);
|
||||
@ -75,7 +76,7 @@ public final class StringMultiProperty extends AbstractMultiValueProperty<String
|
||||
}
|
||||
|
||||
|
||||
/** For external defition. */
|
||||
/** Master constructor. */
|
||||
private StringMultiProperty(String theName, String theDescription, List<String> defaultValues, float theUIOrder,
|
||||
char delimiter, boolean isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally);
|
||||
|
@ -44,6 +44,7 @@ public final class StringProperty extends AbstractSingleValueProperty<String> {
|
||||
}
|
||||
|
||||
|
||||
/** Master constructor. */
|
||||
private StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder, boolean
|
||||
isDefinedExternally) {
|
||||
super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user