From 578bbf8f7bcb0ff5d9522d19260f13e32662cb19 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Sun, 25 Jun 2017 17:40:16 +0200 Subject: [PATCH 01/53] Draft for the new API --- .../sourceforge/pmd/PropertyDescriptor.java | 39 +- .../AbstractMultiValueProperty.java | 202 ++++++++++ .../rule/properties/AbstractProperty.java | 365 +++--------------- .../AbstractSingleValueProperty.java | 121 ++++++ 4 files changed, 406 insertions(+), 321 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index bd13191967..e1387bbe67 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -12,10 +12,11 @@ import java.util.Map; * descriptor instances are static and immutable they provide validation, * serialization, and default values for any specific datatypes. * - * @author Brian Remedios * @param type of the property's value + * + * @author Brian Remedios */ -public interface PropertyDescriptor extends Comparable> { +public interface PropertyDescriptor extends Comparable> { /** * The name of the property without spaces as it serves as the key into the * property map. @@ -33,11 +34,12 @@ public interface PropertyDescriptor extends Comparable type(); + Class type(); /** * Returns whether the property is multi-valued, i.e. an array of strings, @@ -71,18 +73,18 @@ public interface PropertyDescriptor extends ComparableExample:
* name -> 0.0 description 1.0 minValue -> 2.0 maxValue -> 2.1 *

@@ -98,12 +100,13 @@ public interface PropertyDescriptor extends Comparable extends Comparable extends Comparable choices(); /** * A convenience method that returns an error string if the rule holds onto * a property value that has a problem. Returns null otherwise. * - * @param rule - * Rule + * @param rule Rule + * * @return String */ String propertyErrorFor(Rule rule); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java new file mode 100644 index 0000000000..4bd2d804b0 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -0,0 +1,202 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import net.sourceforge.pmd.Rule; + +/** + * Multi valued property. + * + * @param The type of the individual values. The multiple values are wrapped into a list. + * + * @author Clément Fournier + */ +public abstract class AbstractMultiValueProperty extends AbstractProperty> { + + /** The default value. */ + protected final List defaultValue; + + + /** + * Creates a multi valued property using the default delimiter {@link #DEFAULT_DELIMITER}. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theDefault Default value + * @param theUIOrder UI order (must be positive or zero) + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + public AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder) { + this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER); + } + + + /** + * Creates a multi valued property using another delimiter. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theDefault Default value + * @param theUIOrder UI order (must be positive or zero) + * @param delimiter The delimiter to use + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + public AbstractMultiValueProperty(String theName, String theDescription, List theDefault, + float theUIOrder, char delimiter) { + + super(theName, theDescription, theUIOrder, delimiter); + defaultValue = theDefault; + } + + + /** + * Creates a multi valued property using the default delimiter {@link #DEFAULT_DELIMITER}. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theDefault Default value + * @param theUIOrder UI order (must be positive or zero) + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + protected AbstractMultiValueProperty(String theName, String theDescription, V[] theDefault, float theUIOrder) { + this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER); + } + + /** + * Constructor for AbstractPMDProperty. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theDefault Default value + * @param theUIOrder UI order (must be positive or zero) + * @param delimiter The delimiter to separate multi values + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + protected AbstractMultiValueProperty(String theName, String theDescription, V[] theDefault, + float theUIOrder, char delimiter) { + + this(theName, theDescription, Arrays.asList(theDefault), theUIOrder, delimiter); + } + + + @Override + public List defaultValue() { + return defaultValue; + } + + /** + * Returns true if a default value is null. + * + * @return True if a default value is null + */ + private boolean defaultHasNullValue() { + return defaultValue == null || defaultValue.contains(null); + } + + @Override + public final boolean isMultiValue() { + return true; + } + + @Override + public String asDelimitedString(List values, char delimiter) { + if (values == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + for (V value : values) { + sb.append(value == null ? "" : value.toString()).append(delimiter); + } + if (sb.length() > 0) { + sb.deleteCharAt(sb.length() - 1); + } + + return sb.toString(); + } + + + @Override + public String errorFor(List values) { + + String err; + for (V value2 : values) { + err = valueErrorFor(value2); + if (err != null) { + return err; + } + } + + return null; + } + + /** + * Checks a single value for a "missing value" error. + * + * @param value Value to check + * + * @return A descriptive String of the error or null if there was none + */ + protected String valueErrorFor(V value) { + return value != null || defaultHasNullValue() ? null : "missing value"; + } + + @Override + public Map> choices() { + return null; + } + + + /* This is the one overriden in PropertyDescriptor */ + @Override + public String propertyErrorFor(Rule rule) { + List realValues = rule.getProperty(this); + if (realValues == null && !isRequired()) { + return null; + } + return errorFor(realValues); + } + + /** + * Returns a string representation of the default value. + * + * @return A string representation of the default value. + */ + protected String defaultAsString() { + return asDelimitedString(defaultValue(), multiValueDelimiter()); + } + + /** + * Parse a string and returns an instance of a value. + * + * @param toParse String to parse + * + * @return An instance of a value + */ + protected abstract V createFrom(String toParse); + + @Override + public List valueFrom(String valueString) throws IllegalArgumentException { + String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter())); + + List values = new ArrayList<>(strValues.length); + for (int i = 0; i < strValues.length; i++) { + values.add(createFrom(strValues[i])); + } + + return values; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 2bc1c8c037..9865aaa0b4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -13,359 +13,150 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFields; -import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.util.StringUtil; /** + * Abstract class for properties. + * + * @param The type of the values. * * @author Brian Remedios - * @param */ public abstract class AbstractProperty implements PropertyDescriptor { - private final String name; - private final String description; - private final T defaultValue; - private final boolean isRequired; - private final float uiOrder; - /** * Default delimiter for multi properties. Note: Numeric properties usual * use the {@value #DEFAULT_NUMERIC_DELIMITER}. */ public static final char DEFAULT_DELIMITER = '|'; + /** * Default delimiter for numeric properties. */ public static final char DEFAULT_NUMERIC_DELIMITER = ','; + private final String name; + private final String description; + private final boolean isRequired; + private final float uiOrder; private char multiValueDelimiter = DEFAULT_DELIMITER; - protected AbstractProperty(String theName, String theDescription, T theDefault, float theUIOrder) { - this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER); + + /** + * Creates an AbstractProperty using the default delimiter {@link #DEFAULT_DELIMITER}. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theUIOrder UI order (must be positive or zero) + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + protected AbstractProperty(String theName, String theDescription, float theUIOrder) { + this(theName, theDescription, theUIOrder, DEFAULT_DELIMITER); } /** * Constructor for AbstractPMDProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * Object - * @param theUIOrder - * float - * @throws IllegalArgumentException + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theUIOrder UI order (must be positive or zero) + * @param delimiter The delimiter to separate multi values + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - protected AbstractProperty(String theName, String theDescription, T theDefault, float theUIOrder, char delimiter) { + protected AbstractProperty(String theName, String theDescription, + float theUIOrder, char delimiter) { + if (theUIOrder < 0) { + throw new IllegalArgumentException("Property attribute 'UI order' cannot be null or blank"); + } + name = checkNotEmpty(theName, NAME); description = checkNotEmpty(theDescription, DESCRIPTION); - defaultValue = theDefault; isRequired = false; // TODO - do we need this? - uiOrder = checkPositive(theUIOrder, "UI order"); + uiOrder = theUIOrder; multiValueDelimiter = delimiter; } - /** - * @param arg - * String - * @param argId - * String - * @return String - * @throws IllegalArgumentException - */ - private static String checkNotEmpty(String arg, String argId) { + private static String checkNotEmpty(String arg, String argId) throws IllegalArgumentException { if (StringUtil.isEmpty(arg)) { throw new IllegalArgumentException("Property attribute '" + argId + "' cannot be null or blank"); } - return arg; } /** - * @param arg - * float - * @param argId - * String - * @return float - * @throws IllegalArgumentException + * Tests if two values are equal. + * + * @param value First value + * @param otherValue Object + * + * @return True if the two values are equal. + * + * @deprecated Never used in pmd's codebase + is just an alias for Object#equals. */ - private static float checkPositive(float arg, String argId) { - if (arg < 0) { - throw new IllegalArgumentException("Property attribute " + argId + "' must be zero or positive"); - } - return arg; + @SuppressWarnings("PMD.CompareObjectsWithEquals") + public static boolean areEqual(Object value, Object otherValue) { + return value != null && value.equals(otherValue); } - /** - * {@inheritDoc} - */ - @Override - public char multiValueDelimiter() { - return multiValueDelimiter; - } - /** - * {@inheritDoc} - */ @Override public String name() { return name; } - /** - * {@inheritDoc} - */ @Override public String description() { return description; } - /** - * {@inheritDoc} - */ - @Override - public T defaultValue() { - return defaultValue; - } - - /** - * Method defaultHasNullValue. - * - * @return boolean - */ - protected boolean defaultHasNullValue() { - - if (defaultValue == null) { - return true; - } - - if (isMultiValue() && isArray(defaultValue)) { - Object[] defaults = (Object[]) defaultValue; - for (Object default1 : defaults) { - if (default1 == null) { - return true; - } - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isMultiValue() { - return false; - } - - /** - * {@inheritDoc} - */ @Override public boolean isRequired() { return isRequired; } - /** - * {@inheritDoc} - */ @Override public float uiOrder() { return uiOrder; } - /** - * Return the value as a string that can be easily recognized and parsed - * when we see it again. - * - * @param value - * Object - * @return String - */ - protected String asString(Object value) { - return value == null ? "" : value.toString(); + @Override + public char multiValueDelimiter() { + return multiValueDelimiter; } - /** - * {@inheritDoc} - */ @Override - public String asDelimitedString(T values) { + public final String asDelimitedString(T values) { return asDelimitedString(values, multiValueDelimiter()); } /** * Return the specified values as a single string using the delimiter. * - * @param values - * Object - * @param delimiter - * char + * @param values Values to format + * @param delimiter char + * * @return String - * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(Object) + * + * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(T) */ - public String asDelimitedString(T values, char delimiter) { - if (values == null) { - return ""; - } + public abstract String asDelimitedString(T values, char delimiter); - if (values instanceof Object[]) { - Object[] valueSet = (Object[]) values; - if (valueSet.length == 0) { - return ""; - } - if (valueSet.length == 1) { - return asString(valueSet[0]); - } - - StringBuilder sb = new StringBuilder(); - sb.append(asString(valueSet[0])); - for (int i = 1; i < valueSet.length; i++) { - sb.append(delimiter); - sb.append(asString(valueSet[i])); - } - return sb.toString(); - } - - return asString(values); - } - - /** - * {@inheritDoc} - */ @Override - public int compareTo(PropertyDescriptor otherProperty) { + public final int compareTo(PropertyDescriptor otherProperty) { float otherOrder = otherProperty.uiOrder(); return (int) (otherOrder - uiOrder); } - /** - * {@inheritDoc} - */ - @Override - public String errorFor(Object value) { - String typeError = typeErrorFor(value); - if (typeError != null) { - return typeError; - } - return isMultiValue() ? valuesErrorFor(value) : valueErrorFor(value); - } - - /** - * @param value - * Object - * @return String - */ - protected String valueErrorFor(Object value) { - - if (value == null) { - if (defaultHasNullValue()) { - return null; - } - return "missing value"; - } - return null; - } - - /** - * @param value - * Object - * @return String - */ - protected String valuesErrorFor(Object value) { - - if (!isArray(value)) { - return "multiple values expected"; - } - - Object[] values = (Object[]) value; - - String err = null; - for (Object value2 : values) { - err = valueErrorFor(value2); - if (err != null) { - return err; - } - } - - return null; - } - - /** - * @param value - * Object - * @return boolean - */ - protected static boolean isArray(Object value) { - return value != null && value.getClass().getComponentType() != null; - } - - /** - * @param value - * Object - * @return String - */ - protected String typeErrorFor(Object value) { - - if (value == null && !isRequired) { - return null; - } - - if (isMultiValue()) { - if (!isArray(value)) { - return "Value is not an array of type: " + type(); - } - - Class arrayType = value.getClass().getComponentType(); - if (arrayType == null || !arrayType.isAssignableFrom(type().getComponentType())) { - return "Value is not an array of type: " + type(); - } - return null; - } - - if (!type().isAssignableFrom(value.getClass())) { - return value + " is not an instance of " + type(); - } - - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public String propertyErrorFor(Rule rule) { - Object realValue = rule.getProperty(this); - if (realValue == null && !isRequired()) { - return null; - } - return errorFor(realValue); - } - - /** - * {@inheritDoc} - */ - @Override - public Object[][] choices() { - return null; - } - - /** - * {@inheritDoc} - */ @Override public int preferredRowCount() { return 1; } - /** - * {@inheritDoc} - */ + @Override public boolean equals(Object obj) { if (this == obj) { @@ -380,58 +171,26 @@ public abstract class AbstractProperty implements PropertyDescriptor { return false; } - /** - * {@inheritDoc} - */ @Override public int hashCode() { return name.hashCode(); } - /** - * {@inheritDoc} - */ + @Override public String toString() { return "[PropertyDescriptor: name=" + name() + ", type=" + type() + ", value=" + defaultValue() + "]"; } /** - * @return String + * Returns a string representation of the default value. + * + * @return A string representation of the default value. */ - protected String defaultAsString() { - if (isMultiValue()) { - return asDelimitedString(defaultValue(), multiValueDelimiter()); - } else { - return defaultValue().toString(); - } - } - - /** - * @param value - * Object - * @param otherValue - * Object - * @return boolean - */ - @SuppressWarnings("PMD.CompareObjectsWithEquals") - public static final boolean areEqual(Object value, Object otherValue) { - if (value == otherValue) { - return true; - } - if (value == null) { - return false; - } - if (otherValue == null) { - return false; - } - - return value.equals(otherValue); - } + protected abstract String defaultAsString(); @Override public Map attributeValuesById() { - Map values = new HashMap<>(); addAttributesTo(values); return values; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java new file mode 100644 index 0000000000..897fe854e7 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -0,0 +1,121 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.Map; + +import net.sourceforge.pmd.Rule; + +/** + * Single value property. + * + * @param The type of the value. + * + * @author Clément Fournier + */ +public abstract class AbstractSingleValueProperty extends AbstractProperty { + + /** Default value. */ + protected T defaultValue; + + /** + * Creates a single value property using the default delimiter {@link #DEFAULT_DELIMITER}. + * + * @param theName Name of the property (must not be empty) + * @param theDescription Description (must not be empty) + * @param theUIOrder UI order (must be positive or zero) + * @param theDefault Default value + * + * @throws IllegalArgumentException If name or description are empty, or UI order is negative. + */ + protected AbstractSingleValueProperty(String theName, String theDescription, T theDefault, float theUIOrder) { + super(theName, theDescription, theUIOrder, DEFAULT_DELIMITER); + + defaultValue = theDefault; + } + + + @Override + public final T defaultValue() { + return defaultValue; + } + + /** + * Returns true if the default value is {@code null}. + * + * @return True if the default value is {@code null}. + */ + private boolean defaultHasNullValue() { + return defaultValue == null; + } + + @Override + public final boolean isMultiValue() { + return false; + } + + @Override + public String asDelimitedString(T values, char delimiter) { + return values == null ? "" : values.toString(); + } + + @Override + public String propertyErrorFor(Rule rule) { + T realValue = rule.getProperty(this); + if (realValue == null && !isRequired()) { + return null; + } + return errorFor(realValue); + } + + @Override + public String errorFor(T value) { + String typeError = typeErrorFor(value); + if (typeError != null) { + return typeError; + } + return valueErrorFor(value); + } + + private String typeErrorFor(T value) { // TODO:cf consider subtypes!! + + if (value != null && !type().isAssignableFrom(value.getClass())) { + return value + " is not an instance of " + type(); + } + + return null; + } + + protected String valueErrorFor(T value) { + return value != null || defaultHasNullValue() ? null : "missing value"; + } + + @Override + protected final String defaultAsString() { + return defaultValue().toString(); + } + + @Override + public Map choices() { + return null; + } + + /** + * Parse a string and returns an instance of a value. + * + * @param toParse String to parse + * + * @return An instance of a value + */ + protected abstract T createFrom(String toParse); + + // this is there to be symmetrical. + + @Override + public final T valueFrom(String valueString) throws IllegalArgumentException { + return createFrom(valueString); + } + +} From b2673b38b5553db85c360567fdf3d04321dcf771 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Sun, 25 Jun 2017 20:55:43 +0200 Subject: [PATCH 02/53] POC on boolean and enumerated properties --- .../sourceforge/pmd/PropertyDescriptor.java | 4 +- .../AbstractMultiValueProperty.java | 19 ++- .../AbstractSingleValueProperty.java | 17 ++- .../rule/properties/BooleanMultiProperty.java | 79 ++++------ .../lang/rule/properties/BooleanProperty.java | 59 +++----- .../properties/EnumeratedMultiProperty.java | 135 +++++++----------- .../rule/properties/EnumeratedProperty.java | 96 +++++++------ 7 files changed, 178 insertions(+), 231 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index e1387bbe67..b0091d98d5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; /** * Property value descriptor that defines the use & requirements for setting @@ -126,7 +128,7 @@ public interface PropertyDescriptor extends Comparable> * * @return Object[][] */ - Map choices(); + Set> choices(); /** * A convenience method that returns an error string if the rule holds onto diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 4bd2d804b0..9e0aafdc4b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -7,7 +7,8 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import java.util.regex.Pattern; import net.sourceforge.pmd.Rule; @@ -52,7 +53,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty theDefault, - float theUIOrder, char delimiter) { + float theUIOrder, char delimiter) { super(theName, theDescription, theUIOrder, delimiter); defaultValue = theDefault; @@ -69,7 +70,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty extends AbstractProperty extends AbstractProperty values, char delimiter) { if (values == null) { @@ -118,7 +123,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty 0) { sb.deleteCharAt(sb.length() - 1); @@ -154,7 +159,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty> choices() { + public Set>> choices() { return null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 897fe854e7..c56e550716 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -4,7 +4,8 @@ package net.sourceforge.pmd.lang.rule.properties; -import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import net.sourceforge.pmd.Rule; @@ -56,6 +57,8 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return false; } + + @Override public String asDelimitedString(T values, char delimiter) { return values == null ? "" : values.toString(); @@ -92,13 +95,17 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return value != null || defaultHasNullValue() ? null : "missing value"; } - @Override - protected final String defaultAsString() { - return defaultValue().toString(); + protected String asString(T value) { + return value == null ? "" : value.toString(); } @Override - public Map choices() { + protected final String defaultAsString() { + return asString(defaultValue); + } + + @Override + public Set> choices() { return null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index b742e4cc4b..e598a65ed1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -14,79 +15,59 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class BooleanMultiProperty extends AbstractScalarProperty { +public class BooleanMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - String[].class) { + /** + * Factory. + */ + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( + Boolean.class) { @Override public BooleanMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new BooleanMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - booleanValuesIn(defaultValueIn(valuesById), delimiter), 0f); + booleanValuesIn(defaultValueIn(valuesById), delimiter), 0f); } }; /** * Constructor for BooleanMultiProperty that allows for multiple values. * - * @param theName - * String - * @param theDescription - * String - * @param defaultValues - * Boolean[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param defaultValues Boolean[] + * @param theUIOrder float */ public BooleanMultiProperty(String theName, String theDescription, Boolean[] defaultValues, float theUIOrder) { super(theName, theDescription, defaultValues, theUIOrder); } /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ - @Override - public Class type() { - return Boolean[].class; - } - - /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() - */ - @Override - public boolean isMultiValue() { - return true; - } - - /** - * Creates and returns a Boolean instance from a raw string + * Constructor for BooleanMultiProperty that allows for multiple values. * - * @param value - * String - * @return Object + * @param theName String + * @param theDescription String + * @param defaultValues Boolean[] + * @param theUIOrder float */ - @Override - protected Object createFrom(String value) { - return Boolean.valueOf(value); + public BooleanMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder) { + super(theName, theDescription, defaultValues, theUIOrder); } - /** - * @param size - * int - * @return Object[] - */ @Override - protected Boolean[] arrayFor(int size) { - return new Boolean[size]; + protected Boolean createFrom(String toParse) { + return Boolean.valueOf(toParse); } - /** - * @return String - */ + @Override - protected String defaultAsString() { - return asDelimitedString(defaultValue()); + public Class type() { + return Boolean.class; + } + + + @Override + public List valueFrom(String propertyString) throws IllegalArgumentException { + return null; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 6a03a0fc93..b980ad6b97 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -14,77 +14,52 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class BooleanProperty extends AbstractScalarProperty { +public class BooleanProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Boolean.class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( + Boolean.class) { @Override public BooleanProperty createWith(Map valuesById) { return new BooleanProperty(nameIn(valuesById), descriptionIn(valuesById), - Boolean.valueOf(defaultValueIn(valuesById)), 0f); + Boolean.valueOf(defaultValueIn(valuesById)), 0f); } }; /** * Constructor for BooleanProperty limited to a single value. * - * @param theName - * String - * @param theDescription - * String - * @param defaultValue - * boolean - * @param theUIOrder - * float + * @param theName Name + * @param theDescription Description + * @param defaultValue Default value + * @param theUIOrder UI order */ - public BooleanProperty(String theName, String theDescription, Boolean defaultValue, float theUIOrder) { - super(theName, theDescription, Boolean.valueOf(defaultValue), theUIOrder); + public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) { + super(theName, theDescription, defaultValue, theUIOrder); } /** * Constructor for BooleanProperty limited to a single value. Converts * default argument string into a boolean. * - * @param theName - * String - * @param theDescription - * String - * @param defaultBoolStr - * String - * @param theUIOrder - * float + * @param theName Name + * @param theDescription Description + * @param defaultBoolStr String representing the default value. + * @param theUIOrder UI order */ public BooleanProperty(String theName, String theDescription, String defaultBoolStr, float theUIOrder) { this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override public Class type() { return Boolean.class; } - /** - * @return String - */ @Override - protected String defaultAsString() { - return Boolean.toString(defaultValue()); + public Boolean createFrom(String propertyString) throws IllegalArgumentException { + return null; } - /** - * Creates and returns a Boolean instance from a raw string - * - * @param value - * String - * @return Object - */ - @Override - protected Object createFrom(String value) { - return Boolean.valueOf(value); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index a3dc611ea1..8f2e7cb031 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -4,12 +4,14 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.ArrayList; import java.util.Enumeration; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; -import net.sourceforge.pmd.util.StringUtil; +import net.sourceforge.pmd.util.CollectionUtil; /** * Defines a datatype with a set of preset values of any type as held within a @@ -17,118 +19,91 @@ import net.sourceforge.pmd.util.StringUtil; * serve as keys to obtain the values. The choices() method provides the ordered * selections to be used in an editor widget. * - * @author Brian Remedios * @param + * + * @author Brian Remedios */ -public class EnumeratedMultiProperty extends AbstractEnumeratedProperty { +public class EnumeratedMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Enumeration[].class) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Enumeration.class) { @Override public EnumeratedMultiProperty createWith(Map valuesById) { - return new EnumeratedMultiProperty(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), - choicesIn(valuesById), indiciesIn(valuesById), 0f); + return new EnumeratedMultiProperty<>(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), + choicesIn(valuesById), indicesIn(valuesById), 0f); } }; + protected Map choicesByLabel; + protected Map labelsByChoice; + + /** * Constructor for EnumeratedProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theLabels - * String[] - * @param theChoices - * E[] - * @param choiceIndices - * int[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theLabels String[] + * @param theChoices E[] + * @param choiceIndices int[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, - int[] choiceIndices, float theUIOrder) { - super(theName, theDescription, theLabels, theChoices, choiceIndices, theUIOrder, true); + int[] choiceIndices, float theUIOrder) { + super(theName, theDescription, selection(choiceIndices, theChoices), theUIOrder); + choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices); + labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ - @Override - public Class type() { - return Object[].class; + private static List selection(int[] choiceIndices, E[] theChoices) { + List selected = new ArrayList<>(); + for (int i : choiceIndices) { + selected.add(theChoices[i]); + } + return selected; } - /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() - */ + @Override - public boolean isMultiValue() { - return true; + public Class type() { + return Enumeration.class; } - /** - * @param value - * Object - * @return String - * @see net.sourceforge.pmd.PropertyDescriptor#errorFor(Object) - */ + + private String nonLegalValueMsgFor(E value) { + return value + " is not a legal value"; + } + + @Override - public String errorFor(Object value) { - Object[] values = (Object[]) value; - for (int i = 0; i < values.length; i++) { - if (!labelsByChoice.containsKey(values[i])) { - return nonLegalValueMsgFor(values[i]); + public String errorFor(List values) { + for (E value : values) { + if (!labelsByChoice.containsKey(value)) { + return nonLegalValueMsgFor(value); } } return null; } - /** - * - * @param value - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ - @Override - public Object[] valueFrom(String value) throws IllegalArgumentException { - String[] strValues = StringUtil.substringsOf(value, multiValueDelimiter()); - - Object[] values = new Object[strValues.length]; - for (int i = 0; i < values.length; i++) { - values[i] = choiceFrom(strValues[i]); + private E choiceFrom(String label) { + E result = choicesByLabel.get(label); + if (result != null) { + return result; } - return values; + throw new IllegalArgumentException(label); } - /** - * - * @param value - * Object - * @return String - * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(Object) - */ @Override - public String asDelimitedString(Object[] value) { - Object[] choices = value; + protected E createFrom(String toParse) { + return choiceFrom(toParse); + } - StringBuilder sb = new StringBuilder(); - - sb.append(labelsByChoice.get(choices[0])); - - for (int i = 1; i < choices.length; i++) { - sb.append(multiValueDelimiter()); - sb.append(labelsByChoice.get(choices[i])); - } - - return sb.toString(); + @Override + public String asString(E item) { + return labelsByChoice.get(item); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index c824e2f9aa..ecc662a615 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -6,9 +6,12 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Enumeration; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; +import net.sourceforge.pmd.util.CollectionUtil; /** * Defines a datatype with a set of preset values of any type as held within a @@ -16,85 +19,84 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * serve as keys to obtain the values. The choices() method provides the ordered * selections to be used in an editor widget. * + * @param Type of the choices + * * @author Brian Remedios - * @param */ -public class EnumeratedProperty extends AbstractEnumeratedProperty { +public class EnumeratedProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Enumeration.class) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Enumeration.class) { @Override public EnumeratedProperty createWith(Map valuesById) { - - return new EnumeratedProperty(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), - choicesIn(valuesById), indexIn(valuesById), 0f); + return new EnumeratedProperty<>(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), + choicesIn(valuesById), indexIn(valuesById), 0f); } }; + protected Map choicesByLabel; + protected Map labelsByChoice; /** * Constructor for EnumeratedProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theLabels - * String[] - * @param theChoices - * E[] - * @param defaultIndex - * int - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theLabels String[] + * @param theChoices E[] + * @param defaultIndex int + * @param theUIOrder float + * * @throws IllegalArgumentException */ public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, - int defaultIndex, float theUIOrder) { - super(theName, theDescription, theLabels, theChoices, new int[] { defaultIndex }, theUIOrder, false); + int defaultIndex, float theUIOrder) { + super(theName, theDescription, theChoices[defaultIndex], theUIOrder); + + choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices); + labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override public Class type() { return Object.class; } - /** - * @param value - * Object - * @return String - * @see net.sourceforge.pmd.PropertyDescriptor#errorFor(Object) - */ + @Override public String errorFor(Object value) { return labelsByChoice.containsKey(value) ? null : nonLegalValueMsgFor(value); } - /** - * @param value - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ + + private String nonLegalValueMsgFor(Object value) { + return value + " is not a legal value"; + } + + + private E choiceFrom(String label) { + E result = choicesByLabel.get(label); + if (result != null) { + return result; + } + throw new IllegalArgumentException(label); + } + + @Override - public Object valueFrom(String value) throws IllegalArgumentException { + public E createFrom(String value) throws IllegalArgumentException { return choiceFrom(value); } - /** - * - * @param value - * Object - * @return String - * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(Object) - */ @Override - public String asDelimitedString(Object value) { + public String asString(E value) { return labelsByChoice.get(value); } + + @Override + public Set> choices() { + return choicesByLabel.entrySet(); + } + } From 785d663553072e5aeca8d8448347087e9d6c8aa3 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Mon, 26 Jun 2017 14:22:10 +0200 Subject: [PATCH 03/53] Finished refactoring properties --- .../pmd/NumericPropertyDescriptor.java | 6 +- .../pmd/PropertyDescriptorFields.java | 2 +- .../AbstractEnumeratedProperty.java | 120 ---------- .../AbstractMultiNumericProperty.java | 88 ++++--- .../AbstractMultiPackagedProperty.java | 163 +++++++++++-- .../properties/AbstractNumericProperty.java | 66 ++---- .../properties/AbstractPackagedProperty.java | 103 +++----- .../rule/properties/AbstractProperty.java | 1 + .../properties/AbstractScalarProperty.java | 77 ------ .../properties/CharacterMultiProperty.java | 88 +++---- .../rule/properties/CharacterProperty.java | 73 ++---- .../rule/properties/DoubleMultiProperty.java | 71 +++--- .../lang/rule/properties/DoubleProperty.java | 69 ++---- .../lang/rule/properties/FileProperty.java | 19 +- .../rule/properties/FloatMultiProperty.java | 82 +++---- .../lang/rule/properties/FloatProperty.java | 69 ++---- .../rule/properties/IntegerMultiProperty.java | 82 +++---- .../lang/rule/properties/IntegerProperty.java | 67 ++---- .../rule/properties/LongMultiProperty.java | 76 +++--- .../lang/rule/properties/LongProperty.java | 69 +++--- .../rule/properties/MethodMultiProperty.java | 119 ++++------ .../lang/rule/properties/MethodProperty.java | 132 ++++------- .../properties/PropertyDescriptorFactory.java | 41 ++-- .../properties/PropertyDescriptorWrapper.java | 25 +- .../rule/properties/StringMultiProperty.java | 113 ++++----- .../lang/rule/properties/StringProperty.java | 42 +--- .../rule/properties/TypeMultiProperty.java | 105 ++++----- .../lang/rule/properties/TypeProperty.java | 127 ++++------ .../BasicPropertyDescriptorFactory.java | 222 ++++++++++-------- .../pmd/renderers/CodeClimateRenderer.java | 51 ++-- .../pmd/util/designer/Designer.java | 7 +- .../AbstractPropertyDescriptorTester.java | 20 +- 32 files changed, 1035 insertions(+), 1360 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractEnumeratedProperty.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractScalarProperty.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index 9616c16062..8fcd554e0c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -12,17 +12,17 @@ package net.sourceforge.pmd; * * @param type of the property value */ -public interface NumericPropertyDescriptor extends PropertyDescriptor { +public interface NumericPropertyDescriptor extends PropertyDescriptor { /** - * Returns the maximum value that instances of the property can have + * Returns the maximum value that instances of the property can have. * * @return Number */ Number upperLimit(); /** - * Returns the minimum value that instances of the property can have + * Returns the minimum value that instances of the property can have. * * @return Number */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java index 1de85f25a9..476f09e22b 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java @@ -20,7 +20,7 @@ public class PropertyDescriptorFields { * @see PropertyDescriptorUtil */ public static final String TYPE = "type"; - /** The name of the property */ + /** The name of the property. */ public static final String NAME = "name"; /** The description of the property. */ public static final String DESCRIPTION = "description"; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractEnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractEnumeratedProperty.java deleted file mode 100644 index d241ae564b..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractEnumeratedProperty.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.Map; - -import net.sourceforge.pmd.util.CollectionUtil; - -/** - * @author Brian Remedios - * @param - */ -public abstract class AbstractEnumeratedProperty extends AbstractProperty { - - protected Map choicesByLabel; - protected Map labelsByChoice; - - private String[] orderedLabels; - protected Object[][] choices; - - /** - * @param theName - * @param theDescription - * @param theLabels - * @param theChoices - * @param choiceIndices - * @param theUIOrder - * @param isMulti - * @throws IllegalArgumentException - */ - @SuppressWarnings("unchecked") - public AbstractEnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, - int[] choiceIndices, float theUIOrder, boolean isMulti) { - super(theName, theDescription, (T) selectionsIn(theLabels, choiceIndices, isMulti), theUIOrder); - - choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices); - labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); - orderedLabels = theLabels; - } - - /** - * Method selectionsIn. - * - * @param items - * String[] - * @param selectionIndices - * int[] - * @param isMulti - * boolean - * @return Object - */ - private static Object selectionsIn(String[] items, int[] selectionIndices, boolean isMulti) { - String[] selections = new String[selectionIndices.length]; - final int maxIdx = items.length - 1; - for (int i = 0; i < selections.length; i++) { - if (i < 0 || i > maxIdx) { - throw new IllegalArgumentException("Invalid item index: " + i); - } - selections[i] = items[selectionIndices[i]]; - } - return isMulti ? selections : selections[0]; - } - - /** - * @return String - */ - @Override - protected String defaultAsString() { - - return isMultiValue() ? (String) defaultValue() : asDelimitedString(defaultValue(), '|'); - } - - /** - * Method nonLegalValueMsgFor. - * - * @param value - * Object - * @return String - */ - protected String nonLegalValueMsgFor(Object value) { - return value + " is not a legal value"; - } - - /** - * Method choiceFrom. - * - * @param label - * String - * @return E - */ - protected E choiceFrom(String label) { - E result = choicesByLabel.get(label); - if (result != null) { - return result; - } - throw new IllegalArgumentException(label); - } - - /** - * @see net.sourceforge.pmd.PropertyDescriptor#choices() - */ - @Override - public Object[][] choices() { - - if (choices != null) { - return choices; - } - - choices = new Object[orderedLabels.length][2]; - - for (int i = 0; i < choices.length; i++) { - choices[i][0] = orderedLabels[i]; - choices[i][1] = choicesByLabel.get(orderedLabels[i]); - } - orderedLabels = null; // no longer needed - return choices; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index e0eaeb0736..75adb71d0a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -4,48 +4,78 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.PropertyDescriptorFields.MAX; +import static net.sourceforge.pmd.PropertyDescriptorFields.MIN; + +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.NumericPropertyDescriptor; + /** + * @param * * @author Brian Remedios - * @param */ -public abstract class AbstractMultiNumericProperty extends AbstractNumericProperty { +public abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty + implements NumericPropertyDescriptor> { + + + private Number lowerLimit; + private Number upperLimit; + /** - * Constructor for AbstractMultiNumericProperty. + * Constructor for AbstractMultiNumericProperty.Object * - * @param theName - * String - * @param theDescription - * String - * @param lower - * Number - * @param upper - * Number - * @param theDefault - * T - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param lower Number + * @param upper Number + * @param theDefault T + * @param theUIOrder float */ - protected AbstractMultiNumericProperty(String theName, String theDescription, Number lower, Number upper, - T theDefault, float theUIOrder) { - super(theName, theDescription, lower, upper, theDefault, theUIOrder); + public AbstractMultiNumericProperty(String theName, String theDescription, Number lower, Number upper, + List theDefault, float theUIOrder) { + super(theName, theDescription, theDefault, theUIOrder); + + if (lower.doubleValue() > upper.doubleValue()) { + throw new IllegalArgumentException("Lower limit cannot be greater than the upper limit"); + } + + lowerLimit = lower; + upperLimit = upper; } - /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() - */ + @Override - public boolean isMultiValue() { - return true; + public Number lowerLimit() { + return lowerLimit; } - /** - * @return String - */ + @Override - protected String defaultAsString() { - return asDelimitedString(defaultValue()); + public Number upperLimit() { + return upperLimit; + } + + + @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; + } + + @Override + protected void addAttributesTo(Map attributes) { + super.addAttributesTo(attributes); + attributes.put(MIN, lowerLimit.toString()); + attributes.put(MAX, upperLimit.toString()); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index 63f1c1d6bc..17dbfe331b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -4,48 +4,163 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; + /** + * @param * * @author Brian Remedios - * @param */ -public abstract class AbstractMultiPackagedProperty extends AbstractPackagedProperty { +public abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty { protected static final char DELIMITER = '|'; + protected static final Map PACKAGED_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory + .expectedFieldTypesWith(new String[] {LEGAL_PACKAGES}, new Boolean[] {Boolean.FALSE}); + private static final char PACKAGE_NAME_DELIMITER = ' '; + private String[] legalPackageNames; + /** - * Constructor for AbstractMultiPackagedProperty. + * Create a packaged property. * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * T - * @param theLegalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName Name + * @param theDescription Description + * @param theDefault Default value + * @param theLegalPackageNames Legal package names + * @param theUIOrder UI order + * + * @throws IllegalArgumentException */ - protected AbstractMultiPackagedProperty(String theName, String theDescription, T theDefault, - String[] theLegalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefault, theLegalPackageNames, theUIOrder); + protected AbstractMultiPackagedProperty(String theName, String theDescription, List theDefault, + String[] theLegalPackageNames, float theUIOrder) { + super(theName, theDescription, theDefault, theUIOrder); + + checkValidPackages(theDefault, theLegalPackageNames); + + legalPackageNames = theLegalPackageNames; + } + + protected static String[] packageNamesIn(Map params) { + // TODO + return null; + } + + @Override + protected void addAttributesTo(Map 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(); } /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() + * 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 */ - @Override - public boolean isMultiValue() { - return true; + private void checkValidPackages(List items, String[] legalNamePrefixes) { + + Set nameSet = new HashSet<>(); + + for (T item : items) { + nameSet.add(packageNameOf(item)); + } + + Set 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); } /** - * @return String + * Returns the name of the type of item. + * + * @return The name of the type of item */ + protected abstract String itemTypeName(); + + @Override - protected String defaultAsString() { - return asDelimitedString(defaultValue()); + 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; + } + + /** + * Returns the package name of the item. + * + * @param item Item + * + * @return Package name of the item + */ + protected abstract String packageNameOf(T item); + + /** + * Returns the legal package names. + * + * @return The legal package names + */ + public String[] legalPackageNames() { + return legalPackageNames; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index b9c21498be..b70cbef6ac 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -16,30 +16,23 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * Maintains a pair of boundary limit values between which all values managed by * the subclasses must fit. * + * @param The type of value. + * * @author Brian Remedios - * @param */ -public abstract class AbstractNumericProperty extends AbstractScalarProperty - implements NumericPropertyDescriptor { +public abstract class AbstractNumericProperty extends AbstractSingleValueProperty + implements NumericPropertyDescriptor { + + public static final Map NUMBER_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory + .expectedFieldTypesWith(new String[] {MIN, MAX}, new Boolean[] {Boolean.TRUE, Boolean.TRUE}); + private Number lowerLimit; private Number upperLimit; - public static final Map NUMBER_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory - .expectedFieldTypesWith(new String[] { MIN, MAX }, new Boolean[] { Boolean.TRUE, Boolean.TRUE }); - /** - * - * @param theName - * @param theDescription - * @param lower - * @param upper - * @param theDefault - * @param theUIOrder - * @throws IllegalArgumentException - */ protected AbstractNumericProperty(String theName, String theDescription, Number lower, Number upper, T theDefault, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); if (lower.doubleValue() > upper.doubleValue()) { @@ -50,60 +43,50 @@ public abstract class AbstractNumericProperty extends AbstractScalarProperty< upperLimit = upper; } + /** + * Returns a string representing the range defined by the two bounds. + * + * @return String + */ + public 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. - * @see net.sourceforge.pmd.NumericPropertyDescriptor#lowerLimit() + * @return The minimum value */ @Override public Number lowerLimit() { return lowerLimit; } - /** - * @return String - */ - @Override - protected String defaultAsString() { - return defaultValue().toString(); - } - /** * Returns the maximum value that instances of the property can have * * @return The maximum value. - * @see net.sourceforge.pmd.NumericPropertyDescriptor#upperLimit() */ @Override public Number upperLimit() { return upperLimit; } - /** - * @return String - */ - public String rangeString() { - StringBuilder sb = new StringBuilder().append('(').append(lowerLimit).append(" -> ").append(upperLimit) - .append(')'); - return sb.toString(); - } - /** * Returns a string describing any error the value may have when * characterized by the receiver. * - * @param value - * Object + * @param value Object + * * @return String */ @Override - protected String valueErrorFor(Object value) { + protected String valueErrorFor(T value) { - double number = ((Number) value).doubleValue(); + double number = value.doubleValue(); if (number > upperLimit.doubleValue() || number < lowerLimit.doubleValue()) { - return value + " is out of range " + rangeString(); + return value + " is out of range " + rangeString(lowerLimit, upperLimit); } return null; @@ -112,7 +95,6 @@ public abstract class AbstractNumericProperty extends AbstractScalarProperty< @Override protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); - attributes.put(MIN, lowerLimit.toString()); attributes.put(MAX, upperLimit.toString()); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index e9b9ee93b7..ba2afcbafb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -6,9 +6,7 @@ package net.sourceforge.pmd.lang.rule.properties; import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; @@ -18,29 +16,31 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * items by specifying portions of their package names in the constructor. If * the legalPackageNames value is set to null then no restrictions are made. * - * @author Brian Remedios * @param + * + * @author Brian Remedios */ -public abstract class AbstractPackagedProperty extends AbstractProperty { - - private String[] legalPackageNames; - - private static final char PACKAGE_NAME_DELIMITER = ' '; +public abstract class AbstractPackagedProperty extends AbstractSingleValueProperty { protected static final Map PACKAGED_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory - .expectedFieldTypesWith(new String[] { LEGAL_PACKAGES }, new Boolean[] { Boolean.FALSE }); + .expectedFieldTypesWith(new String[] {LEGAL_PACKAGES}, new Boolean[] {Boolean.FALSE}); + private static final char PACKAGE_NAME_DELIMITER = ' '; + private String[] legalPackageNames; + /** + * 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 - * @param theDescription - * @param theDefault - * @param theLegalPackageNames - * @param theUIOrder * @throws IllegalArgumentException */ protected AbstractPackagedProperty(String theName, String theDescription, T theDefault, - String[] theLegalPackageNames, float theUIOrder) { + String[] theLegalPackageNames, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); checkValidPackages(theDefault, theLegalPackageNames); @@ -60,14 +60,13 @@ public abstract class AbstractPackagedProperty extends AbstractProperty { attributes.put(LEGAL_PACKAGES, delimitedPackageNames()); } - /** - * @return String - */ + private String delimitedPackageNames() { if (legalPackageNames == null || legalPackageNames.length == 0) { return ""; } + if (legalPackageNames.length == 1) { return legalPackageNames[0]; } @@ -84,61 +83,33 @@ public abstract class AbstractPackagedProperty extends AbstractProperty { * 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 - * @param legalNamePrefixes - * @throws IllegalArgumentException + * @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(Object item, String[] legalNamePrefixes) { - Object[] items = new Object[0]; + private void checkValidPackages(T item, String[] legalNamePrefixes) { + String name = packageNameOf(item); - if (item != null) { - if (item.getClass().isArray()) { - items = (Object[]) item; - } else { - items = new Object[] { item }; + for (String legalNamePrefixe : legalNamePrefixes) { + if (name.startsWith(legalNamePrefixe)) { + return; } } - String[] names = new String[items.length]; - Set nameSet = new HashSet<>(items.length); - String name = null; - - for (int i = 0; i < items.length; i++) { - name = packageNameOf(items[i]); - names[i] = name; - nameSet.add(name); - } - - for (int i = 0; i < names.length; i++) { - for (int l = 0; l < legalNamePrefixes.length; l++) { - if (names[i].startsWith(legalNamePrefixes[l])) { - nameSet.remove(names[i]); - break; - } - } - } - if (nameSet.isEmpty()) { - return; - } - - throw new IllegalArgumentException("Invalid items: " + nameSet); + throw new IllegalArgumentException("Invalid item: " + item); } /** - * Method itemTypeName. + * Returns the name of the type of item. * - * @return String + * @return The name of the type of item */ protected abstract String itemTypeName(); - /** - * - * @param value - * Object - * @return String - */ + @Override - protected String valueErrorFor(Object value) { + protected String valueErrorFor(T value) { if (value == null) { String err = super.valueErrorFor(null); @@ -163,16 +134,18 @@ public abstract class AbstractPackagedProperty extends AbstractProperty { } /** + * Returns the package name of the item. * - * @param item - * Object - * @return String + * @param item Item + * + * @return Package name of the item */ - protected abstract String packageNameOf(Object item); + protected abstract String packageNameOf(T item); /** + * Returns the legal package names. * - * @return String[] + * @return The legal package names */ public String[] legalPackageNames() { return legalPackageNames; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 9865aaa0b4..68f07a9dd2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -182,6 +182,7 @@ public abstract class AbstractProperty implements PropertyDescriptor { return "[PropertyDescriptor: name=" + name() + ", type=" + type() + ", value=" + defaultValue() + "]"; } + /** * Returns a string representation of the default value. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractScalarProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractScalarProperty.java deleted file mode 100644 index 66fdc1c67e..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractScalarProperty.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import net.sourceforge.pmd.util.StringUtil; - -/** - * No, subclasses are not necessarily scalar per se, they're just easy to parse - * without error. If you can come up with a better name... - * - * @author Brian Remedios - * @param - */ -public abstract class AbstractScalarProperty extends AbstractProperty { - - /** - * Constructor for AbstractScalarProperty. - * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * Object - * @param theUIOrder - * float - */ - protected AbstractScalarProperty(String theName, String theDescription, T theDefault, float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); - } - - /** - * @param value - * String - * @return Object - */ - protected abstract Object createFrom(String value); - - /** - * @param size - * int - * @return Object[] - */ - protected Object[] arrayFor(int size) { - if (isMultiValue()) { - throw new IllegalStateException( - "Subclass '" + this.getClass().getSimpleName() + "' must implement the arrayFor(int) method."); - } - throw new UnsupportedOperationException("Arrays not supported on single valued property descriptors."); - } - - /** - * @param valueString - * String - * @return Object[] - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ - @Override - @SuppressWarnings("unchecked") - public T valueFrom(String valueString) throws IllegalArgumentException { - - if (!isMultiValue()) { - return (T) createFrom(valueString); - } - - String[] strValues = StringUtil.substringsOf(valueString, multiValueDelimiter()); - - Object[] values = arrayFor(strValues.length); - for (int i = 0; i < strValues.length; i++) { - values[i] = createFrom(strValues[i]); - } - return (T) values; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index af3044f0c9..295a00faa2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -4,10 +4,13 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; +import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory.PrimitiveExtractor; import net.sourceforge.pmd.util.StringUtil; /** @@ -15,80 +18,79 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class CharacterMultiProperty extends AbstractProperty { +public class CharacterMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Character[].class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Character.class) { @Override public CharacterMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); - return new CharacterMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - charsIn(defaultValueIn(valuesById), delimiter), 0.0f, delimiter); + return new CharacterMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + parsePrimitives(defaultValueIn(valuesById), delimiter, PrimitiveExtractor.CHARACTER_EXTRACTOR), 0.0f, + delimiter); } }; + /** * Constructor for CharacterProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefaults - * char[] - * @param theUIOrder - * float - * @param delimiter - * char - * @throws IllegalArgumentException + * @param theName String + * @param theDescription String + * @param theDefaults char[] + * @param theUIOrder float + * @param delimiter char + * + * @throws IllegalArgumentException If the delimiter is in the default values */ public CharacterMultiProperty(String theName, String theDescription, Character[] theDefaults, float theUIOrder, - char delimiter) { + char delimiter) { super(theName, theDescription, theDefaults, theUIOrder, delimiter); if (theDefaults != null) { - for (int i = 0; i < theDefaults.length; i++) { - if (theDefaults[i].charValue() == delimiter) { + for (Character theDefault : theDefaults) { + if (theDefault == delimiter) { throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); } } } } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override - public Class type() { - return Character[].class; + protected Character createFrom(String toParse) { + return CharacterProperty.charFrom(toParse); } - /** - * @param valueString - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ + + public CharacterMultiProperty(String theName, String theDescription, List theDefaults, float theUIOrder, + char delimiter) { + super(theName, theDescription, theDefaults, theUIOrder, delimiter); + + if (theDefaults != null) { + for (Character c : theDefaults) { + if (c == delimiter) { + throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); + } + } + } + } + + @Override - public Character[] valueFrom(String valueString) throws IllegalArgumentException { + public Class type() { + return Character.class; + } + + @Override + public List valueFrom(String valueString) throws IllegalArgumentException { String[] values = StringUtil.substringsOf(valueString, multiValueDelimiter()); - Character[] chars = new Character[values.length]; + List chars = new ArrayList<>(values.length); for (int i = 0; i < values.length; i++) { - chars[i] = Character.valueOf(values[i].charAt(0)); + chars.add(values[i].charAt(0)); } return chars; } - /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() - */ - @Override - public boolean isMultiValue() { - return true; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 2c86ae36e5..71f711ac07 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -14,30 +14,27 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class CharacterProperty extends AbstractProperty { +public class CharacterProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Character.class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Character.class) { @Override public CharacterProperty createWith(Map valuesById) { - return new CharacterProperty(nameIn(valuesById), descriptionIn(valuesById), - defaultValueIn(valuesById) != null ? new Character(defaultValueIn(valuesById).charAt(0)) : null, - 0f); + return new CharacterProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById) == null ? null + : defaultValueIn(valuesById).charAt(0), + 0f); } }; /** * Constructor for CharacterProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * Character - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefault Character + * @param theUIOrder float */ public CharacterProperty(String theName, String theDescription, Character theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); @@ -46,61 +43,43 @@ public class CharacterProperty extends AbstractProperty { /** * Constructor for CharacterProperty. * - * @param theName - * String - * @param theDescription - * String - * @param defaultStr - * String - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param defaultStr String + * @param theUIOrder float + * * @throws IllegalArgumentException */ public CharacterProperty(String theName, String theDescription, String defaultStr, float theUIOrder) { this(theName, theDescription, charFrom(defaultStr), theUIOrder); } + /** - * @param charStr - * String - * @return Character + * Parses a String into a Character. + * + * @param charStr String to parse + * + * @return Parsed Character + * + * @throws IllegalArgumentException if the String doesn't have length 1 */ public static Character charFrom(String charStr) { - if (charStr == null || charStr.length() != 1) { throw new IllegalArgumentException("missing/invalid character value"); } return charStr.charAt(0); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override public Class type() { return Character.class; } - /** - * @param valueString - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ + @Override - public Character valueFrom(String valueString) throws IllegalArgumentException { + public Character createFrom(String valueString) throws IllegalArgumentException { return charFrom(valueString); } - /** - * Method defaultAsString. - * - * @return String - */ - @Override - protected String defaultAsString() { - return Character.toString(defaultValue()); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index 00c9da0966..405f61eecf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY; + +import java.util.Arrays; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -15,10 +19,10 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class DoubleMultiProperty extends AbstractMultiNumericProperty { +public class DoubleMultiProperty extends AbstractMultiNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Double[].class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleMultiProperty createWith(Map valuesById) { @@ -26,57 +30,48 @@ public class DoubleMultiProperty extends AbstractMultiNumericProperty char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); Double[] defaultValues = doublesIn(numericDefaultValueIn(valuesById), delimiter); return new DoubleMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Double.parseDouble(minMax[0]), - Double.parseDouble(minMax[1]), defaultValues, 0f); + Double.parseDouble(minMax[1]), defaultValues, 0f); } }; /** * Constructor for DoubleProperty. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Double - * @param max - * Double - * @param defaultValues - * Double[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Double + * @param max Double + * @param defaultValues Double[] + * @param theUIOrder float */ public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, Double[] defaultValues, - float theUIOrder) { + float theUIOrder) { + this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); + } + + /** + * Constructor for DoubleProperty. + * + * @param theName String + * @param theDescription String + * @param min Double + * @param max Double + * @param defaultValues Double[] + * @param theUIOrder float + */ + public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, List defaultValues, + float theUIOrder) { super(theName, theDescription, min, max, defaultValues, theUIOrder); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override - public Class type() { - return Double[].class; + public Class type() { + return Double.class; } - /** - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { + protected Double createFrom(String value) { return Double.valueOf(value); } - /** - * @param size - * int - * @return Object[] - */ - @Override - protected Object[] arrayFor(int size) { - return new Double[size]; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index b6a01d270e..dd0cb3b476 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -17,88 +17,69 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class DoubleProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Double.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( + Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); return new DoubleProperty(nameIn(valuesById), descriptionIn(valuesById), Double.valueOf(minMax[0]), - Double.valueOf(minMax[1]), Double.valueOf(numericDefaultValueIn(valuesById)), 0f); + Double.valueOf(minMax[1]), Double.valueOf(numericDefaultValueIn(valuesById)), 0f); } }; /** * Constructor for DoubleProperty. * - * @param theName - * String - * @param theDescription - * String - * @param min - * double - * @param max - * double - * @param theDefault - * double - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min double + * @param max double + * @param theDefault double + * @param theUIOrder float + * * @throws IllegalArgumentException */ public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, min, max, theDefault, theUIOrder); } /** * Constructor for DoubleProperty. * - * @param theName - * String - * @param theDescription - * String - * @param minStr - * String - * @param maxStr - * String - * @param defaultStr - * String - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param minStr String + * @param maxStr String + * @param defaultStr String + * @param theUIOrder float + * * @throws IllegalArgumentException */ public DoubleProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, doubleFrom(minStr), doubleFrom(maxStr), doubleFrom(defaultStr), theUIOrder); } /** - * @param numberString - * String - * @return Double + * Parses a String into a Double. + * + * @param numberString String to parse + * + * @return Parsed Double */ public static Double doubleFrom(String numberString) { return Double.valueOf(numberString); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override public Class type() { return Double.class; } - /** - * Deserializes a string into its Double form. - * - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { + protected Double createFrom(String value) { return doubleFrom(value); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index 455085ae19..11abd8d418 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -12,20 +12,19 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto import net.sourceforge.pmd.util.StringUtil; /** - * * @author Brian Remedios */ -public class FileProperty extends AbstractProperty { - - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - File.class) { +public class FileProperty extends AbstractSingleValueProperty { + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(File.class) { @Override public FileProperty createWith(Map valuesById) { return new FileProperty(nameIn(valuesById), descriptionIn(valuesById), null, 0f); } }; + public FileProperty(String theName, String theDescription, File theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); } @@ -36,15 +35,7 @@ public class FileProperty extends AbstractProperty { } @Override - public File valueFrom(String propertyString) throws IllegalArgumentException { - + public File createFrom(String propertyString) { return StringUtil.isEmpty(propertyString) ? null : new File(propertyString); } - - @Override - protected String defaultAsString() { - // TODO Auto-generated method stub - return null; - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index fa19b7231a..4dcd65d6f6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY; + +import java.util.Arrays; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -15,10 +19,10 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class FloatMultiProperty extends AbstractMultiNumericProperty { +public class FloatMultiProperty extends AbstractMultiNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Float[].class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public FloatMultiProperty createWith(Map valuesById) { @@ -26,7 +30,7 @@ public class FloatMultiProperty extends AbstractMultiNumericProperty { char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); Float[] defaultValues = floatsIn(numericDefaultValueIn(valuesById), delimiter); return new FloatMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Float.parseFloat(minMax[0]), - Float.parseFloat(minMax[1]), defaultValues, 0f); + Float.parseFloat(minMax[1]), defaultValues, 0f); } }; @@ -34,55 +38,47 @@ public class FloatMultiProperty extends AbstractMultiNumericProperty { * Constructor for FloatProperty that configures it to accept multiple * values and any number of defaults. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Float - * @param max - * Float - * @param defaultValues - * Float[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Float + * @param max Float + * @param defaultValues Float[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public FloatMultiProperty(String theName, String theDescription, Float min, Float max, Float[] defaultValues, - float theUIOrder) { + float theUIOrder) { + this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); + } + + /** + * Constructor for FloatProperty that configures it to accept multiple + * values and any number of defaults. + * + * @param theName String + * @param theDescription String + * @param min Float + * @param max Float + * @param defaultValues Float[] + * @param theUIOrder float + * + * @throws IllegalArgumentException + */ + public FloatMultiProperty(String theName, String theDescription, Float min, Float max, + List defaultValues, float theUIOrder) { super(theName, theDescription, min, max, defaultValues, theUIOrder); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override - public Class type() { - return Float[].class; + public Class type() { + return Float.class; } - /** - * Creates an property value of the right type from a raw string. - * - * @param value - * String - * @return Object - */ + @Override - protected Object createFrom(String value) { + protected Float createFrom(String value) { return Float.valueOf(value); } - - /** - * Returns an array of the correct type for the receiver. - * - * @param size - * int - * @return Object[] - */ - @Override - protected Object[] arrayFor(int size) { - return new Float[size]; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 69c9aa3648..f84c66f363 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -17,14 +17,14 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class FloatProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - float.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public FloatProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); return new FloatProperty(nameIn(valuesById), descriptionIn(valuesById), Float.valueOf(minMax[0]), - Float.valueOf(minMax[1]), Float.valueOf(numericDefaultValueIn(valuesById)), 0f); + Float.valueOf(minMax[1]), Float.valueOf(numericDefaultValueIn(valuesById)), 0f); } }; @@ -32,22 +32,17 @@ public class FloatProperty extends AbstractNumericProperty { * Constructor for FloatProperty that limits itself to a single value within * the specified limits. * - * @param theName - * String - * @param theDescription - * String - * @param min - * float - * @param max - * float - * @param theDefault - * float - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min float + * @param max float + * @param theDefault float + * @param theUIOrder float + * * @throws IllegalArgumentException */ public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, Float.valueOf(min), Float.valueOf(max), Float.valueOf(theDefault), theUIOrder); } @@ -55,52 +50,38 @@ public class FloatProperty extends AbstractNumericProperty { * Constructor for FloatProperty that limits itself to a single value within * the specified limits. Converts string arguments into the Float values. * - * @param theName - * String - * @param theDescription - * String - * @param minStr - * String - * @param maxStr - * String - * @param defaultStr - * String - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param minStr String + * @param maxStr String + * @param defaultStr String + * @param theUIOrder float + * * @throws IllegalArgumentException */ public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, floatFrom(minStr), floatFrom(maxStr), floatFrom(defaultStr), theUIOrder); } /** - * @param numberString - * String - * @return Float + * Parses a String into a Float. + * + * @param numberString String to parse + * + * @return Parsed Float */ public static Float floatFrom(String numberString) { return Float.valueOf(numberString); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override public Class type() { return Float.class; } - /** - * Creates an property value of the right type from a raw string. - * - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { + protected Float createFrom(String value) { return floatFrom(value); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index b437b12000..3d87e3c36a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY; + +import java.util.Arrays; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -15,69 +19,65 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class IntegerMultiProperty extends AbstractMultiNumericProperty { +public class IntegerMultiProperty extends AbstractMultiNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Integer[].class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( + Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - Integer[] defaultValues = integersIn(numericDefaultValueIn(valuesById), delimiter); + Integer[] defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, PrimitiveExtractor.INTEGER_EXTRACTOR); return new IntegerMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Integer.parseInt(minMax[0]), - Integer.parseInt(minMax[1]), defaultValues, 0f); + Integer.parseInt(minMax[1]), defaultValues, 0f); } }; /** * Constructor for IntegerProperty. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Integer - * @param max - * Integer - * @param theDefaults - * Integer[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Integer + * @param max Integer + * @param theDefaults Integer[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, Integer[] theDefaults, - float theUIOrder) { + float theUIOrder) { + + this(theName, theDescription, min, max, Arrays.asList(theDefaults), theUIOrder); + } + + /** + * Constructor for IntegerProperty. + * + * @param theName String + * @param theDescription String + * @param min Integer + * @param max Integer + * @param theDefaults Integer[] + * @param theUIOrder float + * + * @throws IllegalArgumentException + */ + public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, + List theDefaults, float theUIOrder) { + super(theName, theDescription, min, max, theDefaults, theUIOrder); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override - public Class type() { - return Integer[].class; + public Class type() { + return Integer.class; } - /** - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { - return Integer.valueOf(value); - } - - /** - * @param size - * int - * @return Object[] - */ - @Override - protected Object[] arrayFor(int size) { - return new Integer[size]; + protected Integer createFrom(String toParse) { + return Integer.valueOf(toParse); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 9d6ca78020..209428235b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -17,14 +17,14 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class IntegerProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); return new IntegerProperty(nameIn(valuesById), descriptionIn(valuesById), Integer.valueOf(minMax[0]), - Integer.valueOf(minMax[1]), Integer.valueOf(numericDefaultValueIn(valuesById)), 0f); + Integer.valueOf(minMax[1]), Integer.valueOf(numericDefaultValueIn(valuesById)), 0f); } }; @@ -32,22 +32,17 @@ public class IntegerProperty extends AbstractNumericProperty { * Constructor for IntegerProperty that limits itself to a single value * within the specified limits. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Integer - * @param max - * Integer - * @param theDefault - * Integer - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Integer + * @param max Integer + * @param theDefault Integer + * @param theUIOrder float + * * @throws IllegalArgumentException */ public IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, min, max, theDefault, theUIOrder); } @@ -56,49 +51,39 @@ public class IntegerProperty extends AbstractNumericProperty { * within the specified limits. Converts string arguments into the Float * values. * - * @param theName - * String - * @param theDescription - * String - * @param minStr - * String - * @param maxStr - * String - * @param defaultStr - * String - * @param theUIOrder + * @param theName String + * @param theDescription String + * @param minStr String + * @param maxStr String + * @param defaultStr String + * @param theUIOrder UI order + * * @throws IllegalArgumentException */ public IntegerProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, intFrom(minStr), intFrom(maxStr), intFrom(defaultStr), theUIOrder); } /** - * @param numberString - * String - * @return Integer + * Parses a String into an Integer. + * + * @param numberString String to parse + * + * @return Parsed Integer */ public static Integer intFrom(String numberString) { return Integer.valueOf(numberString); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override public Class type() { return Integer.class; } - /** - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { + protected Integer createFrom(String value) { return intFrom(value); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index e83e58cfaa..7a0c2e4599 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.AbstractNumericProperty.NUMBER_FIELD_TYPES_BY_KEY; + +import java.util.Arrays; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -15,10 +19,10 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class LongMultiProperty extends AbstractMultiNumericProperty { +public class LongMultiProperty extends AbstractMultiNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Long[].class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public LongMultiProperty createWith(Map valuesById) { @@ -26,60 +30,52 @@ public class LongMultiProperty extends AbstractMultiNumericProperty { char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); Long[] defaultValues = longsIn(defaultValueIn(valuesById), delimiter); return new LongMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Long.parseLong(minMax[0]), - Long.parseLong(minMax[1]), defaultValues, 0f); + Long.parseLong(minMax[1]), defaultValues, 0f); } }; /** * Constructor for LongProperty. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Long - * @param max - * Long - * @param theDefaults - * Long[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Long + * @param max Long + * @param theDefaults Long[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public LongMultiProperty(String theName, String theDescription, Long min, Long max, Long[] theDefaults, - float theUIOrder) { + float theUIOrder) { + super(theName, theDescription, min, max, Arrays.asList(theDefaults), theUIOrder); + } + + /** + * Constructor for LongProperty. + * + * @param theName String + * @param theDescription String + * @param min Long + * @param max Long + * @param theDefaults Long[] + * @param theUIOrder float + * + * @throws IllegalArgumentException + */ + public LongMultiProperty(String theName, String theDescription, Long min, Long max, List theDefaults, + float theUIOrder) { super(theName, theDescription, min, max, theDefaults, theUIOrder); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override - public Class type() { - return Long[].class; + public Class type() { + return Long.class; } - /** - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { + protected Long createFrom(String value) { return Long.valueOf(value); } - /** - * Returns an array of the correct type for the receiver. - * - * @param size - * int - * @return Object[] - */ - @Override - protected Object[] arrayFor(int size) { - return new Long[size]; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index ea0476b38d..fe7dc5689e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -17,32 +17,27 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class LongProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Long.class, - NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public LongProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); return new LongProperty(nameIn(valuesById), descriptionIn(valuesById), Long.valueOf(minMax[0]), - Long.valueOf(minMax[1]), Long.valueOf(numericDefaultValueIn(valuesById)), 0f); + Long.valueOf(minMax[1]), Long.valueOf(numericDefaultValueIn(valuesById)), 0f); } }; /** * Constructor for LongProperty. * - * @param theName - * String - * @param theDescription - * String - * @param min - * Long - * @param max - * Long - * @param theDefault - * Long - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param min Long + * @param max Long + * @param theDefault Long + * @param theUIOrder float + * * @throws IllegalArgumentException */ public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { @@ -53,50 +48,40 @@ public class LongProperty extends AbstractNumericProperty { * Constructor for LongProperty that limits itself to a single value within * the specified limits. Converts string arguments into the Long values. * - * @param theName - * String - * @param theDescription - * String - * @param minStr - * String - * @param maxStr - * String - * @param defaultStr - * String - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param minStr String + * @param maxStr String + * @param defaultStr String + * @param theUIOrder float + * * @throws IllegalArgumentException */ public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, longFrom(minStr), longFrom(maxStr), longFrom(defaultStr), theUIOrder); } /** - * @param numberString - * String - * @return Long + * Parses a String into a Long. + * + * @param numberString String to parse + * + * @return Parsed Long */ public static Long longFrom(String numberString) { return Long.valueOf(numberString); } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override public Class type() { return Long.class; } - /** - * @param value - * String - * @return Object - */ @Override - protected Object createFrom(String value) { - return longFrom(value); + protected Long createFrom(String toParse) { + return Long.valueOf(toParse); } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 13baad7d1c..cc0dd17cf5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang.rule.properties; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -21,133 +23,102 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class MethodMultiProperty extends AbstractMultiPackagedProperty { +public class MethodMultiProperty extends AbstractMultiPackagedProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Method[].class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new MethodMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + legalPackageNamesIn(valuesById, delimiter), 0f); } }; /** * Constructor for MethodProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefaults - * Method[] - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefaults Method[] + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ - public MethodMultiProperty(String theName, String theDescription, Method[] theDefaults, String[] legalPackageNames, - float theUIOrder) { + public MethodMultiProperty(String theName, String theDescription, List theDefaults, + String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); } /** * Constructor for MethodProperty. * - * @param theName - * String - * @param theDescription - * String - * @param methodDefaults - * String - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param methodDefaults String + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ - public MethodMultiProperty(String theName, String theDescription, String methodDefaults, String[] legalPackageNames, - float theUIOrder) { + public MethodMultiProperty(String theName, String theDescription, String methodDefaults, + String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, methodsFrom(methodDefaults), legalPackageNames, theUIOrder); } public MethodMultiProperty(String theName, String theDescription, String methodDefaults, - Map otherParams, float theUIOrder) { + Map otherParams, float theUIOrder) { this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); } - /** - * @param methodsStr - * String - * @return Method[] - */ - public static Method[] methodsFrom(String methodsStr) { + public static List methodsFrom(String methodsStr) { String[] values = StringUtil.substringsOf(methodsStr, DELIMITER); - Method[] methods = new Method[values.length]; - for (int i = 0; i < methods.length; i++) { - methods[i] = MethodProperty.methodFrom(values[i], MethodProperty.CLASS_METHOD_DELIMITER, - MethodProperty.METHOD_ARG_DELIMITER); + List methods = new ArrayList<>(values.length); + for (String name : values) { + methods.add(MethodProperty.methodFrom(name, MethodProperty.CLASS_METHOD_DELIMITER, + MethodProperty.METHOD_ARG_DELIMITER)); } return methods; } - /** - * Return the value as a string that can be easily recognized and parsed - * when we see it again. - * - * @param value - * Object - * @return String - */ + @Override - protected String asString(Object value) { - return value == null ? "" : MethodProperty.asStringFor((Method) value); + public String asString(Method value) { + return value == null ? "" : MethodProperty.asStringFor(value); } - /** - * @param item - * Object - * @return String - */ @Override - protected String packageNameOf(Object item) { + protected Method createFrom(String toParse) { + return MethodProperty.methodFrom(toParse, MethodProperty.CLASS_METHOD_DELIMITER, + MethodProperty.METHOD_ARG_DELIMITER); + } - final Method method = (Method) item; + + @Override + protected String packageNameOf(Method item) { + final Method method = item; return method.getDeclaringClass().getName() + '.' + method.getName(); } - /** - * @return String - */ + @Override protected String itemTypeName() { return "method"; } - /** - * - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ + @Override - public Class type() { - return Method[].class; + public Class type() { + return Method.class; } - /** - * @param valueString - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ + @Override - public Method[] valueFrom(String valueString) throws IllegalArgumentException { + public List valueFrom(String valueString) throws IllegalArgumentException { return methodsFrom(valueString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 2347eed987..80550b3e38 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -27,64 +27,54 @@ public class MethodProperty extends AbstractPackagedProperty { public static final char CLASS_METHOD_DELIMITER = '#'; public static final char METHOD_ARG_DELIMITER = ','; - public static final char[] METHOD_GROUP_DELIMITERS = new char[] { '(', ')' }; - - private static final String ARRAY_FLAG = "[]"; - private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); - - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final char[] METHOD_GROUP_DELIMITERS = {'(', ')'}; + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new MethodProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + legalPackageNamesIn(valuesById, delimiter), 0f); } }; + private static final String ARRAY_FLAG = "[]"; + private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); /** * Constructor for MethodProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * Method - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefault Method + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); } /** * Constructor for MethodProperty. * - * @param theName - * String - * @param theDescription - * String - * @param defaultMethodStr - * String - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param defaultMethodStr String + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder); } public MethodProperty(String theName, String theDescription, String defaultMethodStr, - Map otherParams, float theUIOrder) { + Map otherParams, float theUIOrder) { this(theName, theDescription, methodFrom(defaultMethodStr), packageNamesIn(otherParams), theUIOrder); } @@ -97,8 +87,8 @@ public class MethodProperty extends AbstractPackagedProperty { * 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 + * @param method the method to convert + * * @return the string value */ public static String asStringFor(Method method) { @@ -107,14 +97,6 @@ public class MethodProperty extends AbstractPackagedProperty { return sb.toString(); } - /** - * @return String - */ - @Override - protected String defaultAsString() { - return asStringFor(defaultValue()); - } - private static void serializedTypeIdOn(Class type, StringBuilder sb) { Class arrayType = type.getComponentType(); @@ -128,10 +110,8 @@ public class MethodProperty extends AbstractPackagedProperty { /** * Serializes the method signature onto the specified buffer. * - * @param method - * Method - * @param sb - * StringBuilder + * @param method Method + * @param sb StringBuilder */ public static void asStringOn(Method method, StringBuilder sb) { @@ -159,7 +139,7 @@ public class MethodProperty extends AbstractPackagedProperty { private static Class typeFor(String typeName) { - Class type = null; + Class type; if (typeName.endsWith(ARRAY_FLAG)) { String arrayTypeName = typeName.substring(0, typeName.length() - ARRAY_FLAG.length()); @@ -186,20 +166,21 @@ public class MethodProperty extends AbstractPackagedProperty { * its source class and any optional arguments. Callers need to specify the * delimiters expected between the various elements. I.e.: * - * "String#isEmpty()" "String#indexOf(int)" "String#substring(int,int)" + *

"String#isEmpty()" "String#indexOf(int)" "String#substring(int,int)" * - * If a method isn't part of the specified class we will walk up any + *

If a method isn't part of the specified class we will walk up any * superclasses to Object to try and find it. * - * If the classes are listed in the ClassUtil class within in Typemaps then + *

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. * - * Returns null if a matching method cannot be found. + *

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 * - * @param methodNameAndArgTypes - * @param classMethodDelimiter - * @param methodArgDelimiter * @return Method */ public static Method methodFrom(String methodNameAndArgTypes, char classMethodDelimiter, char methodArgDelimiter) { @@ -255,65 +236,38 @@ public class MethodProperty extends AbstractPackagedProperty { } /** - * @param methodStr - * String - * @return Method + * 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); } - /** - * Return the value as a string that can be easily recognized and parsed - * when we see it again. - * - * @param value - * Object - * @return String - */ @Override - protected String asString(Object value) { - return value == null ? "" : asStringFor((Method) value); + protected String asString(Method value) { + return value == null ? "" : asStringFor(value); } - /** - * @param item - * Object - * @return String - */ @Override - protected String packageNameOf(Object item) { - - final Method method = (Method) item; + protected String packageNameOf(Method method) { return method.getDeclaringClass().getName() + '.' + method.getName(); } - /** - * @return String - */ @Override protected String itemTypeName() { return "method"; } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override public Class type() { return Method.class; } - /** - * @param valueString - * String - * @return Object - * @throws IllegalArgumentException - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ @Override - public Method valueFrom(String valueString) throws IllegalArgumentException { + public Method createFrom(String valueString) throws IllegalArgumentException { return methodFrom(valueString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index 23116766ce..120d9361a6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.util.StringUtil; @@ -21,7 +23,7 @@ public class PropertyDescriptorFactory { String typeName = null; // TODO - yes we can, investigate if (propertyDescriptor instanceof EnumeratedProperty || propertyDescriptor instanceof MethodProperty - || propertyDescriptor instanceof TypeProperty) { + || propertyDescriptor instanceof TypeProperty) { // Cannot serialize these kinds of PropertyDescriptors } else if ("java.lang".equals(type.getPackage().getName())) { typeName = type.getSimpleName(); @@ -33,57 +35,58 @@ public class PropertyDescriptorFactory { } public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { - return new PropertyDescriptorWrapper( - createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); + String delimiter, String min, String max, String value) { + return new PropertyDescriptorWrapper<>( + createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); } private static PropertyDescriptor createRawPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { + String delimiter, String min, String max, String value) { if ("Boolean".equals(type)) { return new BooleanProperty(name, description, value, 0.0f); } else if ("Boolean[]".equals(type)) { - BooleanMultiProperty property = new BooleanMultiProperty(name, description, null, 0.0f); + BooleanMultiProperty property = new BooleanMultiProperty(name, description, (List) null, 0.0f); return new BooleanMultiProperty(name, description, property.valueFrom(value), 0.0f); } else if ("Character".equals(type)) { return new CharacterProperty(name, description, CharacterProperty.charFrom(value), 0.0f); } else if ("Character[]".equals(type)) { checkDelimiter(name, type, delimiter); char delim = delimiter.charAt(0); - CharacterMultiProperty property = new CharacterMultiProperty(name, description, null, 0.0f, delim); + CharacterMultiProperty property = new CharacterMultiProperty(name, description, (List) null, 0.0f, delim); return new CharacterMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); } else if ("Double".equals(type)) { checkMinMax(name, type, min, max); return new DoubleProperty(name, description, min, max, value, 0.0f); } else if ("Double[]".equals(type)) { checkMinMax(name, type, min, max); - DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, null, 0.0f); + DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, (List) null, 0.0f); return new DoubleMultiProperty(name, description, DoubleProperty.doubleFrom(min), - DoubleProperty.doubleFrom(max), property.valueFrom(value), 0.0f); + DoubleProperty.doubleFrom(max), property.valueFrom(value), 0.0f); } else if ("Float".equals(type)) { checkMinMax(name, type, min, max); return new FloatProperty(name, description, min, max, value, 0.0f); } else if ("Float[]".equals(type)) { checkMinMax(name, type, min, max); - FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, null, 0.0f); + FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); return new FloatMultiProperty(name, description, FloatProperty.floatFrom(min), FloatProperty.floatFrom(max), - property.valueFrom(value), 0.0f); + property.valueFrom(value), 0.0f); } else if ("Integer".equals(type)) { checkMinMax(name, type, min, max); return new IntegerProperty(name, description, min, max, value, 0.0f); } else if ("Integer[]".equals(type)) { checkMinMax(name, type, min, max); - IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, null, 0.0f); + IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, + 0.0f); return new IntegerMultiProperty(name, description, IntegerProperty.intFrom(min), - IntegerProperty.intFrom(max), property.valueFrom(value), 0.0f); + IntegerProperty.intFrom(max), property.valueFrom(value), 0.0f); } else if ("Long".equals(type)) { checkMinMax(name, type, min, max); return new LongProperty(name, description, min, max, value, 0.0f); } else if ("Long[]".equals(type)) { checkMinMax(name, type, min, max); - LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, null, 0.0f); + LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); return new LongMultiProperty(name, description, LongProperty.longFrom(min), LongProperty.longFrom(max), - property.valueFrom(value), 0.0f); + property.valueFrom(value), 0.0f); // TODO - include legal package names for next four types } else if ("Type".equals(type)) { @@ -100,7 +103,7 @@ public class PropertyDescriptorFactory { } else if ("String[]".equals(type)) { checkDelimiter(name, type, delimiter); char delim = delimiter.charAt(0); - StringMultiProperty property = new StringMultiProperty(name, description, null, 0.0f, delim); + StringMultiProperty property = new StringMultiProperty(name, description, (String[]) null, 0.0f, delim); return new StringMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); } else { throw new IllegalArgumentException("Cannot define property type '" + type + "'."); @@ -110,18 +113,18 @@ public class PropertyDescriptorFactory { private static void checkDelimiter(String name, String type, String delimiter) { if (delimiter == null || delimiter.length() == 0) { throw new IllegalArgumentException( - "Delimiter must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + "Delimiter must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); } } private static void checkMinMax(String name, String type, String min, String max) { if (StringUtil.isEmpty(min)) { throw new IllegalArgumentException( - "Min must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + "Min must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); } if (StringUtil.isEmpty(max)) { throw new IllegalArgumentException( - "Max must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + "Max must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); } } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index 5e0eab37d9..025ea02406 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -4,7 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; @@ -16,8 +19,7 @@ import net.sourceforge.pmd.Rule; * in the encoding of a Rule to XML format to distinguish Rule defined * PropertyDescriptors and those which were originally defined in XML. * - * @param - * The type of the underlying PropertyDescriptor. + * @param The type of the underlying PropertyDescriptor. */ public class PropertyDescriptorWrapper implements PropertyDescriptor { private final PropertyDescriptor propertyDescriptor; @@ -39,7 +41,7 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } @Override - public Object[][] choices() { + public Set> choices() { return propertyDescriptor.choices(); } @@ -59,7 +61,7 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } @Override - public String errorFor(Object value) { + public String errorFor(T value) { return propertyDescriptor.errorFor(value); } @@ -93,9 +95,22 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { return propertyDescriptor.propertyErrorFor(rule); } + @SuppressWarnings("unchecked") @Override public Class type() { - return propertyDescriptor.type(); + Class clazz = propertyDescriptor.type(); + Class result = null; + try { + result = (Class) clazz; + } catch (ClassCastException e1) { + try { + result = (Class) List.class; + } catch (ClassCastException e2) { + + } + } + + return result; } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 76948becde..51fdcda06c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -4,6 +4,9 @@ package net.sourceforge.pmd.lang.rule.properties; + +import java.util.Arrays; +import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -16,110 +19,112 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class StringMultiProperty extends AbstractProperty { +public class StringMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - String[].class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { @Override public StringMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new StringMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), 0.0f, delimiter); + StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), 0.0f, delimiter); } }; /** * Constructor for StringProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefaults - * String[] - * @param theUIOrder - * float - * @param delimiter - * String - * @throws IllegalArgumentException + * @param theName String + * @param theDescription String + * @param theDefaults String[] + * @param theUIOrder float + * @param delimiter String + * + * @throws IllegalArgumentException if a default value contains the delimiter + * @throws NullPointerException if the defaults array is null */ public StringMultiProperty(String theName, String theDescription, String[] theDefaults, float theUIOrder, - char delimiter) { + char delimiter) { + this(theName, theDescription, Arrays.asList(theDefaults), theUIOrder, delimiter); + } + + /** + * Constructor for StringProperty. + * + * @param theName String + * @param theDescription String + * @param theDefaults String[] + * @param theUIOrder float + * @param delimiter String + * + * @throws IllegalArgumentException if a default value contains the delimiter + * @throws NullPointerException if the defaults array is null + */ + public StringMultiProperty(String theName, String theDescription, List theDefaults, float theUIOrder, + char delimiter) { super(theName, theDescription, theDefaults, theUIOrder, delimiter); checkDefaults(theDefaults, delimiter); } + /** - * @param defaultValue - * @param delim - * @throws IllegalArgumentException + * Checks if the values are valid. + * + * @param defaultValue The default value + * @param delim The delimiter + * + * @throws IllegalArgumentException if one value contains the delimiter */ - private static void checkDefaults(String[] defaultValue, char delim) { + private static void checkDefaults(List defaultValue, char delim) { if (defaultValue == null) { return; } - for (int i = 0; i < defaultValue.length; i++) { - if (defaultValue[i].indexOf(delim) >= 0) { + for (String aDefaultValue : defaultValue) { + if (aDefaultValue.indexOf(delim) >= 0) { throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); } } } - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override - public Class type() { - return String[].class; + public Class type() { + return String.class; } - /** - * @param valueString - * String - * @return Object - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ @Override - public String[] valueFrom(String valueString) { - return StringUtil.substringsOf(valueString, multiValueDelimiter()); + public List valueFrom(String valueString) { + return Arrays.asList(StringUtil.substringsOf(valueString, multiValueDelimiter())); } + /** - * @param value - * String + * Returns true if the multi value delimiter is present in the string. + * + * @param value String + * * @return boolean */ private boolean containsDelimiter(String value) { return value.indexOf(multiValueDelimiter()) >= 0; } - /** - * @return String - */ + private String illegalCharMsg() { return "Value cannot contain the '" + multiValueDelimiter() + "' character"; } - /** - * - * @param value - * Object - * @return String - */ + @Override - protected String valueErrorFor(Object value) { + protected String valueErrorFor(String value) { if (value == null) { return "missing value"; } - String testValue = (String) value; - if (containsDelimiter(testValue)) { + if (containsDelimiter(value)) { return illegalCharMsg(); } @@ -128,12 +133,8 @@ public class StringMultiProperty extends AbstractProperty { return null; } - /** - * @return boolean - * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue() - */ @Override - public boolean isMultiValue() { - return true; + protected String createFrom(String toParse) { + return toParse; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 9d0e1e0c76..b1dd360b26 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -14,10 +14,12 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class StringProperty extends AbstractProperty { +public class StringProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - String.class) { + /** + * Factory. + */ + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { @Override public StringProperty createWith(Map valuesById) { @@ -28,46 +30,22 @@ public class StringProperty extends AbstractProperty { /** * Constructor for StringProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefaultValue - * String - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefaultValue String + * @param theUIOrder float */ public StringProperty(String theName, String theDescription, String theDefaultValue, float theUIOrder) { super(theName, theDescription, theDefaultValue, theUIOrder); } - /** - * @return String - */ - @Override - protected String defaultAsString() { - return defaultValue(); - } - - /** - * - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ @Override public Class type() { return String.class; } - /** - * - * @param valueString - * String - * @return Object - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ @Override - public String valueFrom(String valueString) { + public String createFrom(String valueString) { return valueString; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 55817523b7..f677f7b9e9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -4,9 +4,10 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; @@ -19,36 +20,32 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class TypeMultiProperty extends AbstractMultiPackagedProperty { +public class TypeMultiProperty extends AbstractMultiPackagedProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Class[].class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public TypeMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new TypeMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + legalPackageNamesIn(valuesById, delimiter), 0f); } }; /** * Constructor for TypeProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefaults - * Class[] - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefaults Class[] + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ - public TypeMultiProperty(String theName, String theDescription, Class[] theDefaults, String[] legalPackageNames, - float theUIOrder) { + public TypeMultiProperty(String theName, String theDescription, List theDefaults, String[] + legalPackageNames, float theUIOrder) { super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); } @@ -56,89 +53,69 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { /** * Constructor for TypeProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theTypeDefaults - * String - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theTypeDefaults String + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public TypeMultiProperty(String theName, String theDescription, String theTypeDefaults, String[] legalPackageNames, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, typesFrom(theTypeDefaults), legalPackageNames, theUIOrder); } public TypeMultiProperty(String theName, String theDescription, String theTypeDefaults, - Map otherParams, float theUIOrder) { + Map otherParams, float theUIOrder) { this(theName, theDescription, typesFrom(theTypeDefaults), packageNamesIn(otherParams), theUIOrder); } /** - * @param classesStr - * String - * @return Class[] + * Returns a list of Class objects parsed from the input string. + * + * @param classesStr String to parse + * + * @return A list of class objects */ - public static Class[] typesFrom(String classesStr) { + public static List typesFrom(String classesStr) { String[] values = StringUtil.substringsOf(classesStr, DELIMITER); - Class[] classes = new Class[values.length]; + List classes = new ArrayList<>(values.length); for (int i = 0; i < values.length; i++) { - classes[i] = TypeProperty.classFrom(values[i]); + classes.add(TypeProperty.classFrom(values[i])); } return classes; } - /** - * @param item - * Object - * @return String - */ @Override - protected String packageNameOf(Object item) { + protected String packageNameOf(Class item) { return ((Class) item).getName(); } - /** - * @return Class - * @see PropertyDescriptor#type() - */ @Override - public Class type() { - return Class[].class; + public Class type() { + return Class.class; } - /** - * @return String - */ @Override protected String itemTypeName() { return "type"; } - /** - * @param value - * Object - * @return String - */ @Override - protected String asString(Object value) { - return value == null ? "" : ((Class) value).getName(); + public String asString(Class value) { + return value == null ? "" : value.getName(); } - /** - * @param valueString - * String - * @return Object - * @see PropertyDescriptor#valueFrom(String) - */ @Override - public Class[] valueFrom(String valueString) { + protected Class createFrom(String toParse) { + throw new UnsupportedOperationException(); // not used + } + + @Override + public List valueFrom(String valueString) { return typesFrom(valueString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index 2df16ebdf1..1f42e13bd4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -21,114 +21,55 @@ import net.sourceforge.pmd.util.StringUtil; */ public class TypeProperty extends AbstractPackagedProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public TypeProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new TypeProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + legalPackageNamesIn(valuesById, delimiter), 0f); } }; /** * Constructor for TypeProperty. * - * @param theName - * String - * @param theDescription - * String - * @param theDefault - * Class - * @param legalPackageNames - * String[] - * @param theUIOrder - * float + * @param theName String + * @param theDescription String + * @param theDefault Class + * @param legalPackageNames String[] + * @param theUIOrder float + * * @throws IllegalArgumentException */ public TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); } /** + * Constructor for TypeProperty using a string as default value. * - * @param theName - * String - * @param theDescription - * String - * @param defaultTypeStr - * String - * @param legalPackageNames - * String[] - * @param theUIOrder - * float - * @throws IllegalArgumentException + * @param theName String + * @param theDescription String + * @param defaultTypeStr String + * @param legalPackageNames String[] + * @param theUIOrder float + * + * @throws IllegalArgumentException if the default string could not be parsed into a Class */ public TypeProperty(String theName, String theDescription, String defaultTypeStr, String[] legalPackageNames, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, classFrom(defaultTypeStr), legalPackageNames, theUIOrder); } public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, - float theUIOrder) { + float theUIOrder) { this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); } - /** - * @return String - */ - @Override - protected String defaultAsString() { - return asString(defaultValue()); - } - /** - * Method packageNameOf. - * - * @param item - * Object - * @return String - */ - @Override - protected String packageNameOf(Object item) { - return ((Class) item).getName(); - } - - /** - * @return Class - * @see net.sourceforge.pmd.PropertyDescriptor#type() - */ - @Override - public Class type() { - return Class.class; - } - - /** - * @return String - */ - @Override - protected String itemTypeName() { - return "type"; - } - - /** - * @param value - * Object - * @return String - */ - @Override - protected String asString(Object value) { - return value == null ? "" : ((Class) value).getName(); - } - - /** - * @param className - * String - * @return Class - * @throws IllegalArgumentException - */ static Class classFrom(String className) { if (StringUtil.isEmpty(className)) { return null; @@ -146,14 +87,28 @@ public class TypeProperty extends AbstractPackagedProperty { } } - /** - * @param valueString - * String - * @return Object - * @see net.sourceforge.pmd.PropertyDescriptor#valueFrom(String) - */ @Override - public Class valueFrom(String valueString) { + protected String packageNameOf(Class item) { + return item.getName(); + } + + @Override + public Class type() { + return Class.class; + } + + @Override + protected String itemTypeName() { + return "type"; + } + + @Override + protected String asString(Class value) { + return value == null ? "" : value.getName(); + } + + @Override + public Class createFrom(String valueString) { return classFrom(valueString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index 45979ea1e3..18ca0851fe 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -25,36 +26,25 @@ import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** + * @param * * @author Brian Remedios - * - * @param */ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { - private final Class valueType; + protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom( + new String[] {NAME, DESC, DEFAULT_VALUE, DELIMITER}, new Boolean[] {true, true, true, false}); + + private final Class valueType; + private final Map fieldTypesByKey; - protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom( - new String[] { NAME, DESC, DEFAULT_VALUE, DELIMITER }, - new Boolean[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.FALSE }); - - public BasicPropertyDescriptorFactory(Class theValueType) { + public BasicPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY); } - // public interface WrapperBuilder { - // T[] newArray(int size); - // T itemFrom(String txt); - // } - // - // protected WrapperBuilder intBuilder = new WrapperBuilder() { - // public Integer[] newArray(int size) { return new Integer[size]; } - // public Integer itemFrom(String txt) { return Integer.parseInt(txt); } - // }; - - public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { + public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; Map temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); @@ -64,40 +54,6 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact fieldTypesByKey = Collections.unmodifiableMap(temp); } - @Override - public Class valueType() { - return valueType; - } - - @Override - public PropertyDescriptor createWith(Map valuesById) { - throw new RuntimeException("Unimplemented createWith() method in subclass"); - } - - @Override - public Map expectedFields() { - return fieldTypesByKey; - } - - protected String nameIn(Map valuesById) { - return valuesById.get(NAME); - } - - protected String descriptionIn(Map valuesById) { - return valuesById.get(DESC); - } - - protected String defaultValueIn(Map valuesById) { - return valuesById.get(DEFAULT_VALUE); - } - - protected String numericDefaultValueIn(Map valuesById) { - String number = defaultValueIn(valuesById); - return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 - // reasonable if - // undefined? - } - protected static String minValueIn(Map valuesById) { return valuesById.get(MIN); } @@ -106,24 +62,9 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return valuesById.get(MAX); } - // protected static T[] primitivesFrom(String text, WrapperBuilder - // builder) { - // - // String[] values = text.split(","); // TODO - // List items = new ArrayList(values.length); - // for (String value : values) { - // try { - // Object newIten = builder.itemFrom(value); - // items.add(newIten); - // } catch (Exception ex) { - // - // } - // } - // return items.toArray(builder.newArray(items.size())); - // } - protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) { - String[] values = StringUtil.substringsOf(booleanString, delimiter); + String[] values = booleanString.split(Pattern.quote("" + delimiter)); + Boolean[] result = new Boolean[values.length]; for (int i = 0; i < values.length; i++) { result[i] = Boolean.valueOf(values[i]); @@ -131,31 +72,15 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return result; } - protected static Character[] charsIn(String charString, char delimiter) { - String[] values = StringUtil.substringsOf(charString, delimiter); - Character[] chars = new Character[values.length]; - - for (int i = 0; i < values.length; i++) { - if (values.length != 1) { - throw new IllegalArgumentException("missing/ambiguous character value"); - } - chars[i] = values[i].charAt(0); + // TODO change return type to List someday + @SuppressWarnings("unckecked") + protected static U[] parsePrimitives(String toParse, char delimiter, PrimitiveExtractor extractor) { + String[] values = StringUtil.substringsOf(toParse, delimiter); + List result = new ArrayList<>(); + for (String s : values) { + result.add(extractor.valueOf(s)); } - return chars; - } - - protected static Integer[] integersIn(String numberString, char delimiter) { - String[] values = StringUtil.substringsOf(numberString, delimiter); - List ints = new ArrayList<>(values.length); - for (String value : values) { - try { - Integer newInt = Integer.parseInt(value); - ints.add(newInt); - } catch (Exception ex) { - - } - } - return ints.toArray(new Integer[ints.size()]); + return (U[]) result.toArray(); } protected static Long[] longsIn(String numberString, char delimiter) { @@ -212,7 +137,23 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return 0; // TODO } - protected static int[] indiciesIn(Map valuesById) { + // protected static T[] primitivesFrom(String text, WrapperBuilder + // builder) { + // + // String[] values = text.split(","); // TODO + // List items = new ArrayList(values.length); + // for (String value : values) { + // try { + // Object newIten = builder.itemFrom(value); + // items.add(newIten); + // } catch (Exception ex) { + // + // } + // } + // return items.toArray(builder.newArray(items.size())); + // } + + protected static int[] indicesIn(Map valuesById) { return null; // TODO } @@ -237,7 +178,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) { throw new RuntimeException("min and max values must be specified"); } - return new String[] { min, max }; + return new String[] {min, max}; } protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { @@ -257,6 +198,95 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return largerMap; } + @Override + public Class valueType() { + return valueType; + } + + @Override + public PropertyDescriptor createWith(Map valuesById) { + throw new RuntimeException("Unimplemented createWith() method in subclass"); + } + + @Override + public Map expectedFields() { + return fieldTypesByKey; + } + + protected String nameIn(Map valuesById) { + return valuesById.get(NAME); + } + + protected String descriptionIn(Map valuesById) { + return valuesById.get(DESC); + } + + protected String defaultValueIn(Map valuesById) { + return valuesById.get(DEFAULT_VALUE); + } + + protected String numericDefaultValueIn(Map valuesById) { + String number = defaultValueIn(valuesById); + return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 + // reasonable if + // undefined? + } + + /** + * Extracts a primitive from a string + * + * @param + */ + // FUTURE @FunctionalInterface + public interface PrimitiveExtractor { + /** Extracts characters. */ + PrimitiveExtractor CHARACTER_EXTRACTOR = new PrimitiveExtractor() { + @Override + public Character valueOf(String value) { + if (value.length() != 1) { + throw new IllegalArgumentException("missing/ambiguous character value"); + } + return value.charAt(0); + } + }; + + // FUTURE Integer::valueOf + /** Extracts integers. */ + PrimitiveExtractor INTEGER_EXTRACTOR = new PrimitiveExtractor() { + @Override + public Integer valueOf(String value) { + return Integer.valueOf(value); + } + }; + + // FUTURE Boolean::valueOf + /** Extracts booleans. */ + PrimitiveExtractor BOOLEAN_EXTRACTOR = new PrimitiveExtractor() { + @Override + public Boolean valueOf(String value) { + return Boolean.valueOf(value); + } + }; + + /** Extracts characters. */ + PrimitiveExtractor FLOAT_EXTRACTOR = new PrimitiveExtractor() { + @Override + public Float valueOf(String value) { + return Float.valueOf(value); + } + }; + + /** + * Extracts a primitive from a string. + * + * @param value The string to parse + * + * @return The primitive found + */ + U valueOf(String value); + + } + // protected static Map // factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) { // Map factoryMap = new HashMap categories = rule.getProperty(CODECLIMATE_CATEGORIES); + result = categories.toArray(new String[0]); } else { result = CODECLIMATE_DEFAULT_CATEGORIES; } @@ -142,21 +145,13 @@ public class CodeClimateRenderer extends AbstractIncrementingRenderer { return result; } - private static String getPmdDeveloperURL() { - String url = "http://pmd.github.io/pmd-" + PMD.VERSION + "/customizing/pmd-developer.html"; - if (PMD.VERSION.contains("SNAPSHOT") || "unknown".equals(PMD.VERSION)) { - url = "http://pmd.sourceforge.net/snapshot/customizing/pmd-developer.html"; - } - return url; - } - private String getBody() { String result = "## " + rule.getName() + "\\n\\n" + "Since: PMD " + rule.getSince() + "\\n\\n" + "Priority: " - + rule.getPriority() + "\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): " - + Arrays.toString(getCategories()).replaceAll("[\\[\\]]", "") + "\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): " - + getRemediationPoints() + "\\n\\n" + cleaned(rule.getDescription()); + + rule.getPriority() + "\\n\\n" + + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): " + + Arrays.toString(getCategories()).replaceAll("[\\[\\]]", "") + "\\n\\n" + + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): " + + getRemediationPoints() + "\\n\\n" + cleaned(rule.getDescription()); if (!rule.getExamples().isEmpty()) { result += "\\n\\n### Example:\\n\\n"; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java index a5692babcc..cd159f0dbc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java @@ -34,6 +34,7 @@ import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.swing.AbstractAction; import javax.swing.AbstractButton; @@ -864,11 +865,11 @@ public class Designer implements ClipboardOwner { private JPanel createXPathVersionPanel() { JPanel p = new JPanel(); p.add(new JLabel("XPath Version:")); - for (Object[] values : XPathRule.VERSION_DESCRIPTOR.choices()) { + for (Entry values : XPathRule.VERSION_DESCRIPTOR.choices()) { JRadioButton b = new JRadioButton(); - b.setText((String) values[0]); + b.setText(values.getKey()); b.setActionCommand(b.getText()); - if (values[0].equals(XPathRule.VERSION_DESCRIPTOR.defaultValue())) { + if (values.getKey().equals(XPathRule.VERSION_DESCRIPTOR.defaultValue())) { b.setSelected(true); } xpathVersionButtonGroup.add(b); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 881fd74da6..9f583fe63b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -28,7 +28,7 @@ import net.sourceforge.pmd.util.CollectionUtil; * * @author Brian Remedios */ -public abstract class AbstractPropertyDescriptorTester { +public abstract class AbstractPropertyDescriptorTester { public AbstractPropertyDescriptorTester(String typeName) { this.typeName = typeName; @@ -52,7 +52,7 @@ public abstract class AbstractPropertyDescriptorTester { * int * @return Object */ - protected abstract Object createValue(int count); + protected abstract T createValue(int count); /** * Return a value(s) that is known to be faulty per the general scope of the @@ -62,7 +62,7 @@ public abstract class AbstractPropertyDescriptorTester { * int * @return Object */ - protected abstract Object createBadValue(int count); + protected abstract T createBadValue(int count); /** * Creates and returns a properly configured property descriptor. @@ -71,7 +71,7 @@ public abstract class AbstractPropertyDescriptorTester { * boolean * @return PropertyDescriptor */ - protected abstract PropertyDescriptor createProperty(boolean multiValue); + protected abstract PropertyDescriptor createProperty(boolean multiValue); /** * Attempt to create a property with faulty configuration values. This @@ -81,7 +81,7 @@ public abstract class AbstractPropertyDescriptorTester { * boolean * @return PropertyDescriptor */ - protected abstract PropertyDescriptor createBadProperty(boolean multiValue); + protected abstract PropertyDescriptor createBadProperty(boolean multiValue); protected final PropertyDescriptorFactory getSingleFactory() { return PropertyDescriptorUtil.factoryFor(typeName); @@ -181,8 +181,8 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testErrorFor() { - Object testValue = createValue(1); - PropertyDescriptor pmdProp = createProperty(false); // plain vanilla + T testValue = createValue(1); + PropertyDescriptor pmdProp = createProperty(false); // plain vanilla // property & // valid test // value @@ -200,8 +200,8 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testErrorForBad() { - PropertyDescriptor pmdProp = createProperty(false); - Object testValue = createBadValue(1); + PropertyDescriptor pmdProp = createProperty(false); + T testValue = createBadValue(1); String errorMsg = pmdProp.errorFor(testValue); // bad value should // result in an error if (errorMsg == null) { @@ -220,7 +220,7 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testType() { - PropertyDescriptor pmdProp = createProperty(false); + PropertyDescriptor pmdProp = createProperty(false); assertNotNull(pmdProp.type()); } From bb8fe903eac94c0f0e849d14a0be86e1e2503890 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Mon, 26 Jun 2017 15:12:14 +0200 Subject: [PATCH 04/53] Generified PropertyDescriptorFactory --- .../pmd/PropertyDescriptorFactory.java | 4 +-- .../rule/properties/BooleanMultiProperty.java | 2 +- .../properties/CharacterMultiProperty.java | 2 +- .../rule/properties/DoubleMultiProperty.java | 2 +- .../rule/properties/FloatMultiProperty.java | 2 +- .../rule/properties/IntegerMultiProperty.java | 4 +-- .../rule/properties/LongMultiProperty.java | 2 +- .../rule/properties/MethodMultiProperty.java | 8 +++++- .../properties/PropertyDescriptorFactory.java | 23 ++++++++++------- .../rule/properties/TypeMultiProperty.java | 25 ++++++++++++++++--- .../BasicPropertyDescriptorFactory.java | 12 ++++----- .../factories/PropertyDescriptorUtil.java | 20 +++++++-------- 12 files changed, 67 insertions(+), 39 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index 9ed7c55997..61b4450f6a 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -11,7 +11,7 @@ import java.util.Map; * * @author Brian Remedios */ -public interface PropertyDescriptorFactory { +public interface PropertyDescriptorFactory { /** * The type of the value of the {@link PropertyDescriptor} created by this @@ -37,5 +37,5 @@ public interface PropertyDescriptorFactory { * the map of values * @return a new and initialized {@link PropertyDescriptor} */ - PropertyDescriptor createWith(Map valuesById); + PropertyDescriptor createWith(Map valuesById); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index e598a65ed1..ee1b8302da 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -20,7 +20,7 @@ public class BooleanMultiProperty extends AbstractMultiValueProperty { /** * Factory. */ - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>( Boolean.class) { @Override public BooleanMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 295a00faa2..d3b975f889 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -20,7 +20,7 @@ import net.sourceforge.pmd.util.StringUtil; */ public class CharacterMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Character.class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Character.class) { @Override public CharacterMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index 405f61eecf..b16cdfb637 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -22,7 +22,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class DoubleMultiProperty extends AbstractMultiNumericProperty { public static final PropertyDescriptorFactory FACTORY - = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { + = new BasicPropertyDescriptorFactory>(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 4dcd65d6f6..fcc767fc82 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -22,7 +22,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class FloatMultiProperty extends AbstractMultiNumericProperty { public static final PropertyDescriptorFactory FACTORY - = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { + = new BasicPropertyDescriptorFactory>(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public FloatMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 3d87e3c36a..6aee44910c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -21,8 +21,8 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class IntegerMultiProperty extends AbstractMultiNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 7a0c2e4599..2cc1c7eba6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -22,7 +22,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class LongMultiProperty extends AbstractMultiNumericProperty { public static final PropertyDescriptorFactory FACTORY - = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { + = new BasicPropertyDescriptorFactory>(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public LongMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index cc0dd17cf5..c27ac8535d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -26,7 +27,7 @@ import net.sourceforge.pmd.util.StringUtil; public class MethodMultiProperty extends AbstractMultiPackagedProperty { public static final PropertyDescriptorFactory FACTORY - = new BasicPropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { + = new BasicPropertyDescriptorFactory>(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodMultiProperty createWith(Map valuesById) { @@ -52,6 +53,11 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); } + public MethodMultiProperty(String theName, String theDescription, Method[] theDefaults, + String[] legalPackageNames, float theUIOrder) { + this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); + } + /** * Constructor for MethodProperty. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index 120d9361a6..b87b972b9d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -20,6 +20,7 @@ public class PropertyDescriptorFactory { */ public static String getPropertyDescriptorType(PropertyDescriptor propertyDescriptor) { Class type = propertyDescriptor.type(); + String typeName = null; // TODO - yes we can, investigate if (propertyDescriptor instanceof EnumeratedProperty || propertyDescriptor instanceof MethodProperty @@ -31,6 +32,10 @@ public class PropertyDescriptorFactory { if (typeName == null) { throw new IllegalArgumentException("Cannot encode type for PropertyDescriptor class: " + type.getName()); } + if (propertyDescriptor.isMultiValue()) { + typeName = "List<" + typeName + ">"; // TODO:cf + } + return typeName; } @@ -44,12 +49,12 @@ public class PropertyDescriptorFactory { String delimiter, String min, String max, String value) { if ("Boolean".equals(type)) { return new BooleanProperty(name, description, value, 0.0f); - } else if ("Boolean[]".equals(type)) { + } else if ("List".equals(type)) { BooleanMultiProperty property = new BooleanMultiProperty(name, description, (List) null, 0.0f); return new BooleanMultiProperty(name, description, property.valueFrom(value), 0.0f); } else if ("Character".equals(type)) { return new CharacterProperty(name, description, CharacterProperty.charFrom(value), 0.0f); - } else if ("Character[]".equals(type)) { + } else if ("List".equals(type)) { checkDelimiter(name, type, delimiter); char delim = delimiter.charAt(0); CharacterMultiProperty property = new CharacterMultiProperty(name, description, (List) null, 0.0f, delim); @@ -57,7 +62,7 @@ public class PropertyDescriptorFactory { } else if ("Double".equals(type)) { checkMinMax(name, type, min, max); return new DoubleProperty(name, description, min, max, value, 0.0f); - } else if ("Double[]".equals(type)) { + } else if ("List".equals(type)) { checkMinMax(name, type, min, max); DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, (List) null, 0.0f); return new DoubleMultiProperty(name, description, DoubleProperty.doubleFrom(min), @@ -65,7 +70,7 @@ public class PropertyDescriptorFactory { } else if ("Float".equals(type)) { checkMinMax(name, type, min, max); return new FloatProperty(name, description, min, max, value, 0.0f); - } else if ("Float[]".equals(type)) { + } else if ("List".equals(type)) { checkMinMax(name, type, min, max); FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); return new FloatMultiProperty(name, description, FloatProperty.floatFrom(min), FloatProperty.floatFrom(max), @@ -73,7 +78,7 @@ public class PropertyDescriptorFactory { } else if ("Integer".equals(type)) { checkMinMax(name, type, min, max); return new IntegerProperty(name, description, min, max, value, 0.0f); - } else if ("Integer[]".equals(type)) { + } else if ("List".equals(type)) { checkMinMax(name, type, min, max); IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, 0.0f); @@ -82,7 +87,7 @@ public class PropertyDescriptorFactory { } else if ("Long".equals(type)) { checkMinMax(name, type, min, max); return new LongProperty(name, description, min, max, value, 0.0f); - } else if ("Long[]".equals(type)) { + } else if ("List".equals(type)) { checkMinMax(name, type, min, max); LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); return new LongMultiProperty(name, description, LongProperty.longFrom(min), LongProperty.longFrom(max), @@ -91,16 +96,16 @@ public class PropertyDescriptorFactory { // TODO - include legal package names for next four types } else if ("Type".equals(type)) { return new TypeProperty(name, description, value, (String[]) null, 0.0f); - } else if ("Type[]".equals(type)) { + } else if ("List".equals(type)) { return new TypeMultiProperty(name, description, value, (String[]) null, 0.0f); } else if ("Method".equals(type)) { return new MethodProperty(name, description, value, (String[]) null, 0.0f); - } else if ("Method[]".equals(type)) { + } else if ("List".equals(type)) { return new MethodMultiProperty(name, description, value, (String[]) null, 0.0f); } else if ("String".equals(type)) { return new StringProperty(name, description, value, 0.0f); - } else if ("String[]".equals(type)) { + } else if ("List".equals(type)) { checkDelimiter(name, type, delimiter); char delim = delimiter.charAt(0); StringMultiProperty property = new StringMultiProperty(name, description, (String[]) null, 0.0f, delim); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index f677f7b9e9..07f7384203 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -44,12 +45,28 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { * * @throws IllegalArgumentException */ - public TypeMultiProperty(String theName, String theDescription, List theDefaults, String[] - legalPackageNames, float theUIOrder) { + public TypeMultiProperty(String theName, String theDescription, List theDefaults, + String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); } + /** + * Constructor for TypeProperty. + * + * @param theName String + * @param theDescription String + * @param theDefaults Class[] + * @param legalPackageNames String[] + * @param theUIOrder float + * + * @throws IllegalArgumentException + */ + public TypeMultiProperty(String theName, String theDescription, Class[] theDefaults, + String[] legalPackageNames, float theUIOrder) { + this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); + } + /** * Constructor for TypeProperty. * @@ -61,8 +78,8 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { * * @throws IllegalArgumentException */ - public TypeMultiProperty(String theName, String theDescription, String theTypeDefaults, String[] legalPackageNames, - float theUIOrder) { + public TypeMultiProperty(String theName, String theDescription, String theTypeDefaults, + String[] legalPackageNames, float theUIOrder) { this(theName, theDescription, typesFrom(theTypeDefaults), legalPackageNames, theUIOrder); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index 18ca0851fe..38e72f8997 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -30,21 +30,21 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { +public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom( new String[] {NAME, DESC, DEFAULT_VALUE, DELIMITER}, new Boolean[] {true, true, true, false}); - private final Class valueType; + private final Class valueType; private final Map fieldTypesByKey; - public BasicPropertyDescriptorFactory(Class theValueType) { + public BasicPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY); } - public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { + public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; Map temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); @@ -63,7 +63,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) { - String[] values = booleanString.split(Pattern.quote("" + delimiter)); + String[] values = StringUtil.substringsOf(booleanString, delimiter); Boolean[] result = new Boolean[values.length]; for (int i = 0; i < values.length; i++) { @@ -204,7 +204,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } @Override - public PropertyDescriptor createWith(Map valuesById) { + public PropertyDescriptor createWith(Map valuesById) { throw new RuntimeException("Unimplemented createWith() method in subclass"); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java index 8baf3d6f0a..492495646b 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java @@ -52,29 +52,29 @@ public class PropertyDescriptorUtil { Map temp = new HashMap<>(18); temp.put("Boolean", BooleanProperty.FACTORY); - temp.put("Boolean[]", BooleanMultiProperty.FACTORY); + temp.put("List", BooleanMultiProperty.FACTORY); temp.put("String", StringProperty.FACTORY); - temp.put("String[]", StringMultiProperty.FACTORY); + temp.put("List", StringMultiProperty.FACTORY); temp.put("Character", CharacterProperty.FACTORY); - temp.put("Character[]", CharacterMultiProperty.FACTORY); + temp.put("List", CharacterMultiProperty.FACTORY); temp.put("Integer", IntegerProperty.FACTORY); - temp.put("Integer[]", IntegerMultiProperty.FACTORY); + temp.put("List", IntegerMultiProperty.FACTORY); temp.put("Long", LongProperty.FACTORY); - temp.put("Long[]", LongMultiProperty.FACTORY); + temp.put("List", LongMultiProperty.FACTORY); temp.put("Float", FloatProperty.FACTORY); - temp.put("Float[]", FloatMultiProperty.FACTORY); + temp.put("List", FloatMultiProperty.FACTORY); temp.put("Double", DoubleProperty.FACTORY); - temp.put("Double[]", DoubleMultiProperty.FACTORY); + temp.put("List", DoubleMultiProperty.FACTORY); temp.put("Enum", EnumeratedProperty.FACTORY); - temp.put("Enum[]", EnumeratedMultiProperty.FACTORY); + temp.put("List", EnumeratedMultiProperty.FACTORY); temp.put("Class", TypeProperty.FACTORY); - temp.put("Class[]", TypeMultiProperty.FACTORY); + temp.put("List", TypeMultiProperty.FACTORY); temp.put("Method", MethodProperty.FACTORY); - temp.put("Method[]", MethodMultiProperty.FACTORY); + temp.put("List", MethodMultiProperty.FACTORY); temp.put("File", FileProperty.FACTORY); From 739dccfcca05778793fc7d613b660e86fb3b7b99 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Mon, 26 Jun 2017 16:03:35 +0200 Subject: [PATCH 05/53] Refactored AbstractPropertyTester and subclasses Still fails test though --- .../rule/properties/StringMultiProperty.java | 3 +- .../rule/properties/TypeMultiProperty.java | 2 +- .../factories/PropertyDescriptorUtil.java | 8 +- .../AbstractPropertyDescriptorTester.java | 427 +++++++++--------- .../pmd/properties/BooleanPropertyTest.java | 73 ++- .../pmd/properties/CharacterPropertyTest.java | 103 ++--- .../pmd/properties/DoublePropertyTest.java | 85 +--- .../properties/EnumeratedPropertyTest.java | 95 ++-- .../pmd/properties/FloatPropertyTest.java | 92 ++-- .../pmd/properties/IntegerPropertyTest.java | 99 ++-- .../pmd/properties/MethodPropertyTest.java | 76 ++-- .../pmd/properties/PropertyAccessorTest.java | 19 +- .../pmd/properties/StringPropertyTest.java | 100 ++-- .../pmd/properties/TypePropertyTest.java | 96 ++-- 14 files changed, 496 insertions(+), 782 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 51fdcda06c..10db240a2d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -21,7 +21,8 @@ import net.sourceforge.pmd.util.StringUtil; */ public class StringMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(String + .class) { @Override public StringMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 07f7384203..719afb612c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -24,7 +24,7 @@ import net.sourceforge.pmd.util.StringUtil; public class TypeMultiProperty extends AbstractMultiPackagedProperty { public static final PropertyDescriptorFactory FACTORY - = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { + = new BasicPropertyDescriptorFactory>(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public TypeMultiProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java index 492495646b..4b3de3d11d 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java @@ -46,10 +46,10 @@ public class PropertyDescriptorUtil { } }; - private static final Map DESCRIPTOR_FACTORIES_BY_TYPE; + private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; static { - Map temp = new HashMap<>(18); + Map> temp = new HashMap<>(18); temp.put("Boolean", BooleanProperty.FACTORY); temp.put("List", BooleanMultiProperty.FACTORY); @@ -83,14 +83,14 @@ public class PropertyDescriptorUtil { private PropertyDescriptorUtil() { } - public static PropertyDescriptorFactory factoryFor(String typeId) { + public static PropertyDescriptorFactory factoryFor(String typeId) { return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId); } public static String typeIdFor(Class valueType) { // a reverse lookup, not very efficient but fine for now - for (Map.Entry entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { + for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { if (entry.getValue().valueType() == valueType) { return entry.getKey(); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 9f583fe63b..814dbf341e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -4,22 +4,23 @@ package net.sourceforge.pmd.properties; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorFields; import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; -import net.sourceforge.pmd.util.CollectionUtil; /** * Base functionality for all concrete subclasses that evaluate type-specific @@ -30,199 +31,17 @@ import net.sourceforge.pmd.util.CollectionUtil; */ public abstract class AbstractPropertyDescriptorTester { - public AbstractPropertyDescriptorTester(String typeName) { - this.typeName = typeName; - } - - protected final String typeName; - - private static final int MULTI_VALUE_COUNT = 10; - public static final String PUNCTUATION_CHARS = "!@#$%^&*()_-+=[]{}\\|;:'\",.<>/?`~"; public static final String WHITESPACE_CHARS = " \t\n"; public static final String DIGIST_CHARS = "0123456789"; public static final String ALPHA_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmniopqrstuvwxyz"; public static final String ALPHA_NUMERIC_CHARS = DIGIST_CHARS + ALPHA_CHARS; public static final String ALL_CHARS = PUNCTUATION_CHARS + WHITESPACE_CHARS + ALPHA_NUMERIC_CHARS; + private static final int MULTI_VALUE_COUNT = 10; + protected final String typeName; - /** - * Return a legal value(s) per the general scope of the descriptor. - * - * @param count - * int - * @return Object - */ - protected abstract T createValue(int count); - - /** - * Return a value(s) that is known to be faulty per the general scope of the - * descriptor. - * - * @param count - * int - * @return Object - */ - protected abstract T createBadValue(int count); - - /** - * Creates and returns a properly configured property descriptor. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ - protected abstract PropertyDescriptor createProperty(boolean multiValue); - - /** - * Attempt to create a property with faulty configuration values. This - * method should throw an IllegalArgumentException if done correctly. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ - protected abstract PropertyDescriptor createBadProperty(boolean multiValue); - - protected final PropertyDescriptorFactory getSingleFactory() { - return PropertyDescriptorUtil.factoryFor(typeName); - } - - protected final PropertyDescriptorFactory getMultiFactory() { - return PropertyDescriptorUtil.factoryFor(typeName + "[]"); - } - - private Map getPropertyDescriptorValues() { - Map valuesById = new HashMap<>(); - valuesById.put(PropertyDescriptorFields.NAME, "test"); - valuesById.put(PropertyDescriptorFields.DESCRIPTION, "desc"); - valuesById.put(PropertyDescriptorFields.MIN, "0"); - valuesById.put(PropertyDescriptorFields.MAX, "10"); - return valuesById; - } - - @Test - public void testFactorySingleValue() { - PropertyDescriptor prop = getSingleFactory().createWith(getPropertyDescriptorValues()); - Object originalValue = createValue(1); - Object value = prop.valueFrom( - originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); - String asDelimitedString = prop.asDelimitedString(value); - Object value2 = prop.valueFrom(asDelimitedString); - Assert.assertEquals(value, value2); - } - - @Test - public void testFactoryMultiValueDefaultDelimiter() { - PropertyDescriptorFactory multiFactory = getMultiFactory(); - PropertyDescriptor prop = multiFactory.createWith(getPropertyDescriptorValues()); - Object originalValue = createValue(MULTI_VALUE_COUNT); - String asDelimitedString = prop.asDelimitedString(originalValue); - Object value2 = prop.valueFrom(asDelimitedString); - Assert.assertArrayEquals((Object[]) originalValue, (Object[]) value2); - } - - @Test - public void testFactoryMultiValueCustomDelimiter() { - PropertyDescriptorFactory multiFactory = getMultiFactory(); - Map valuesById = getPropertyDescriptorValues(); - String customDelimiter = "ä"; - Assert.assertFalse(ALL_CHARS.contains(customDelimiter)); - valuesById.put(PropertyDescriptorFields.DELIMITER, customDelimiter); - PropertyDescriptor prop = multiFactory.createWith(valuesById); - Object originalValue = createValue(MULTI_VALUE_COUNT); - String asDelimitedString = prop.asDelimitedString(originalValue); - Object value2 = prop.valueFrom(asDelimitedString); - Assert.assertEquals(Arrays.toString((Object[]) originalValue), Arrays.toString((Object[]) value2)); - Assert.assertArrayEquals((Object[]) originalValue, (Object[]) value2); - } - - @Test - public void testConstructors() { - - PropertyDescriptor desc = createProperty(false); - assertNotNull(desc); - - try { - createBadProperty(false); - - } catch (Exception ex) { - return; // caught ok - } - - Assert.fail("uncaught constructor exception"); - } - - @Test - public void testAsDelimitedString() { - - Object testValue = createValue(MULTI_VALUE_COUNT); - PropertyDescriptor pmdProp = createProperty(true); - - String storeValue = pmdProp.asDelimitedString(testValue); - - Object returnedValue = pmdProp.valueFrom(storeValue); - - assertTrue(CollectionUtil.areEqual(returnedValue, testValue)); - } - - @Test - public void testValueFrom() { - - Object testValue = createValue(1); - PropertyDescriptor pmdProp = createProperty(false); - - String storeValue = pmdProp.asDelimitedString(testValue); - - Object returnedValue = pmdProp.valueFrom(storeValue); - - assertTrue(CollectionUtil.areEqual(returnedValue, testValue)); - } - - @Test - public void testErrorFor() { - - T testValue = createValue(1); - PropertyDescriptor pmdProp = createProperty(false); // plain vanilla - // property & - // valid test - // value - String errorMsg = pmdProp.errorFor(testValue); - assertNull(errorMsg, errorMsg); - - testValue = createValue(MULTI_VALUE_COUNT); // multi-value property, all - // valid test values - pmdProp = createProperty(true); - errorMsg = pmdProp.errorFor(testValue); - assertNull(errorMsg, errorMsg); - - } - - @Test - public void testErrorForBad() { - - PropertyDescriptor pmdProp = createProperty(false); - T testValue = createBadValue(1); - String errorMsg = pmdProp.errorFor(testValue); // bad value should - // result in an error - if (errorMsg == null) { - Assert.fail("uncaught bad value: " + testValue); - } - - testValue = createBadValue(MULTI_VALUE_COUNT); // multi-value prop, - // several bad values - pmdProp = createProperty(true); - errorMsg = pmdProp.errorFor(testValue); - if (errorMsg == null) { - Assert.fail("uncaught bad value in: " + testValue); - } - } - - @Test - public void testType() { - - PropertyDescriptor pmdProp = createProperty(false); - - assertNotNull(pmdProp.type()); + public AbstractPropertyDescriptorTester(String typeName) { + this.typeName = typeName; } public static boolean randomBool() { @@ -243,10 +62,9 @@ public abstract class AbstractPropertyDescriptorTester { /** * Method randomInt. * - * @param min - * int - * @param max - * int + * @param min int + * @param max int + * * @return int */ public static int randomInt(int min, int max) { @@ -272,10 +90,9 @@ public abstract class AbstractPropertyDescriptorTester { /** * Method randomFloat. * - * @param min - * float - * @param max - * float + * @param min float + * @param max float + * * @return float */ public static float randomFloat(float min, float max) { @@ -286,10 +103,9 @@ public abstract class AbstractPropertyDescriptorTester { /** * Method randomDouble. * - * @param min - * double - * @param max - * double + * @param min double + * @param max double + * * @return double */ public static double randomDouble(double min, double max) { @@ -304,8 +120,8 @@ public abstract class AbstractPropertyDescriptorTester { /** * Method randomChar. * - * @param characters - * char[] + * @param characters char[] + * * @return char */ public static char randomChar(char[] characters) { @@ -315,21 +131,20 @@ public abstract class AbstractPropertyDescriptorTester { /** * Method randomChoice. * - * @param items - * Object[] + * @param items Object[] + * * @return Object */ - public static Object randomChoice(Object[] items) { + public static T randomChoice(T[] items) { return items[randomInt(0, items.length - 1)]; } /** * Method filter. * - * @param chars - * char[] - * @param removeChar - * char + * @param chars char[] + * @param removeChar char + * * @return char[] */ protected static final char[] filter(char[] chars, char removeChar) { @@ -349,4 +164,194 @@ public abstract class AbstractPropertyDescriptorTester { } return results; } + + /** + * Return a legal value(s) per the general scope of the descriptor. + * + * @return Object + */ + protected abstract T createValue(); + + private List createMultipleValues(int count) { + List res = new ArrayList<>(); + while (count > 0) { + res.add(createValue()); + count--; + } + return res; + } + + /** + * Return a value(s) that is known to be faulty per the general scope of the + * descriptor. + * + * @return Object + */ + protected abstract T createBadValue(); + + private List createMultipleBadValues(int count) { + List res = new ArrayList<>(); + while (count > 0) { + res.add(createBadValue()); + count--; + } + return res; + } + + /** + * Creates and returns a properly configured property descriptor. + * + * @return PropertyDescriptor + */ + protected abstract PropertyDescriptor createProperty(); + + protected abstract PropertyDescriptor> createMultiProperty(); + + /** + * Attempt to create a property with faulty configuration values. This + * method should throw an IllegalArgumentException if done correctly. + * + * @return PropertyDescriptor + */ + protected abstract PropertyDescriptor createBadProperty(); + + protected abstract PropertyDescriptor> createBadMultiProperty(); + + @SuppressWarnings("unchecked") + protected final PropertyDescriptorFactory getSingleFactory() { + return (PropertyDescriptorFactory) PropertyDescriptorUtil.factoryFor(typeName); + } + + @SuppressWarnings("unchecked") + protected final PropertyDescriptorFactory> getMultiFactory() { + return (PropertyDescriptorFactory>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); + } + + private Map getPropertyDescriptorValues() { + Map valuesById = new HashMap<>(); + valuesById.put(PropertyDescriptorFields.NAME, "test"); + valuesById.put(PropertyDescriptorFields.DESCRIPTION, "desc"); + valuesById.put(PropertyDescriptorFields.MIN, "0"); + valuesById.put(PropertyDescriptorFields.MAX, "10"); + return valuesById; + } + + @Test + public void testFactorySingleValue() { + PropertyDescriptor prop = getSingleFactory().createWith(getPropertyDescriptorValues()); + T originalValue = createValue(); + T value = prop.valueFrom( + originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); + String asDelimitedString = prop.asDelimitedString(value); + Object value2 = prop.valueFrom(asDelimitedString); + assertEquals(value, value2); + } + + @Test + public void testFactoryMultiValueDefaultDelimiter() { + PropertyDescriptorFactory> multiFactory = getMultiFactory(); + PropertyDescriptor> prop = multiFactory.createWith(getPropertyDescriptorValues()); + List originalValue = createMultipleValues(MULTI_VALUE_COUNT); + String asDelimitedString = prop.asDelimitedString(originalValue); + List value2 = prop.valueFrom(asDelimitedString); + assertEquals(originalValue, value2); + } + + @Test + public void testFactoryMultiValueCustomDelimiter() { + PropertyDescriptorFactory> multiFactory = getMultiFactory(); + Map valuesById = getPropertyDescriptorValues(); + String customDelimiter = "ä"; + assertFalse(ALL_CHARS.contains(customDelimiter)); + valuesById.put(PropertyDescriptorFields.DELIMITER, customDelimiter); + PropertyDescriptor> prop = multiFactory.createWith(valuesById); + List originalValue = createMultipleValues(MULTI_VALUE_COUNT); + String asDelimitedString = prop.asDelimitedString(originalValue); + List value2 = prop.valueFrom(asDelimitedString); + assertEquals(originalValue.toString(), value2.toString()); + assertEquals(originalValue, value2); + } + + @Test + public void testConstructors() { + + PropertyDescriptor desc = createProperty(); + assertNotNull(desc); + + try { + createBadProperty(); + } catch (Exception ex) { + return; // caught ok + } + + fail("uncaught constructor exception"); + } + + @Test + public void testAsDelimitedString() { + + List testValue = createMultipleValues(MULTI_VALUE_COUNT); + PropertyDescriptor> pmdProp = createMultiProperty(); + + String storeValue = pmdProp.asDelimitedString(testValue); + List returnedValue = pmdProp.valueFrom(storeValue); + + assertEquals(returnedValue, testValue); + } + + @Test + public void testValueFrom() { + + T testValue = createValue(); + PropertyDescriptor pmdProp = createProperty(); + + String storeValue = pmdProp.asDelimitedString(testValue); + + T returnedValue = pmdProp.valueFrom(storeValue); + + assertEquals(returnedValue, testValue); + } + + @Test + public void testErrorForCorrectSingle() { + T testValue = createValue(); + PropertyDescriptor pmdProp = createProperty(); // plain vanilla + // property & valid test value + String errorMsg = pmdProp.errorFor(testValue); + assertNull(errorMsg, errorMsg); + } + + @Test + public void testErrorForCorrectMulti() { + List testMultiValues = createMultipleValues(MULTI_VALUE_COUNT); // multi-value property, all + // valid test values + PropertyDescriptor> multiProperty = createMultiProperty(); + String errorMsg = multiProperty.errorFor(testMultiValues); + assertNull(errorMsg, errorMsg); + + } + + @Test + public void testErrorForBadSingle() { + T testValue = createBadValue(); + PropertyDescriptor pmdProp = createProperty(); // plain vanilla + // property & valid test value + String errorMsg = pmdProp.errorFor(testValue); + assertNotNull("uncaught bad value: " + testValue, errorMsg); + } + + @Test + public void testErrorForBadMulti() { + List testMultiValues = createMultipleBadValues(MULTI_VALUE_COUNT); // multi-value property, all + // valid test values + PropertyDescriptor> multiProperty = createMultiProperty(); + String errorMsg = multiProperty.errorFor(testMultiValues); + assertNotNull("uncaught bad value in: " + testMultiValues, errorMsg); + } + + @Test + public void testType() { + PropertyDescriptor pmdProp = createProperty(); + assertNotNull(pmdProp.type()); + } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java index 2ed4c68a0d..69652d3066 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; @@ -13,69 +15,54 @@ import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; /** * @author Brian Remedios */ -public class BooleanPropertyTest extends AbstractPropertyDescriptorTester { +public class BooleanPropertyTest extends AbstractPropertyDescriptorTester { public BooleanPropertyTest() { super("Boolean"); } - /** - * Method createValue. - * - * @param valueCount - * int - * @return Object - */ + @Override - protected Object createValue(int valueCount) { - - if (valueCount == 1) { - return System.currentTimeMillis() % 1 > 0 ? Boolean.TRUE : Boolean.FALSE; - } - - Boolean[] values = new Boolean[valueCount]; - for (int i = 0; i < values.length; i++) { - values[i] = (Boolean) createValue(1); - } - return values; + protected Boolean createValue() { + return System.currentTimeMillis() % 1 > 0 ? Boolean.TRUE : Boolean.FALSE; } @Override @Test - public void testErrorForBad() { + public void testErrorForBadSingle() { // override, cannot create a 'bad' boolean per se } @Override - protected Object createBadValue(int count) { + @Test + public void testErrorForBadMulti() { + // override, cannot create a 'bad' boolean per se + } + + @Override + protected Boolean createBadValue() { return null; } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - return multiValue ? new BooleanMultiProperty("testBoolean", "Test boolean property", - new Boolean[] { false, true, true }, 1.0f) - : new BooleanProperty("testBoolean", "Test boolean property", false, 1.0f); + protected PropertyDescriptor createProperty() { + return new BooleanProperty("testBoolean", "Test boolean property", false, 1.0f); } - /** - * Method createBadProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { - return multiValue - ? new BooleanMultiProperty("", "Test boolean property", new Boolean[] { false, true, true }, 1.0f) - : new BooleanProperty("testBoolean", "", false, 1.0f); + protected PropertyDescriptor> createMultiProperty() { + return new BooleanMultiProperty("testBoolean", "Test boolean property", + new Boolean[] {false, true, true}, 1.0f); } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new BooleanMultiProperty("", "Test boolean property", new Boolean[] {false, true, true}, 1.0f); + } + + @Override + protected PropertyDescriptor createBadProperty() { + return new BooleanProperty("testBoolean", "", false, 1.0f); + } + } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java index e111060331..57e36fe616 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; @@ -17,7 +19,7 @@ import net.sourceforge.pmd.lang.rule.properties.CharacterProperty; * * @author Brian Remedios */ -public class CharacterPropertyTest extends AbstractPropertyDescriptorTester { +public class CharacterPropertyTest extends AbstractPropertyDescriptorTester { private static final char DELIMITER = '|'; private static final char[] CHARSET = filter(ALL_CHARS.toCharArray(), DELIMITER); @@ -26,83 +28,48 @@ public class CharacterPropertyTest extends AbstractPropertyDescriptorTester { super("Character"); } - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ - @Override - protected Object createValue(int count) { - - if (count == 1) { - return new Character(randomChar(CHARSET)); - } - - Character[] values = new Character[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Character) createValue(1); - } - return values; - } - - /** - * Method createBadValue. - * - * @param count - * int - * @return Object - */ - @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return null; - } - - Character[] values = new Character[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Character) createBadValue(1); - } - return values; - } @Override @Test - public void testErrorForBad() { + public void testErrorForBadSingle() { } // not until char properties use illegal chars - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { + @Test + public void testErrorForBadMulti() { + } // not until char properties use illegal chars - return multiValue - ? new CharacterMultiProperty("testCharacter", "Test character property", - new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER) - : new CharacterProperty("testCharacter", "Test character property", 'a', 1.0f); + + + @Override + protected Character createValue() { + return randomChar(CHARSET); } - /** - * Creates a bad property that is missing either its name or description or - * includes a delimiter in the set of legal values. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { + protected Character createBadValue() { + return null; + } - return multiValue - ? new CharacterMultiProperty("testCharacter", "Test character property", - new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER) - : new CharacterProperty("", "Test character property", 'a', 1.0f); + @Override + protected PropertyDescriptor createProperty() { + return new CharacterProperty("testCharacter", "Test character property", 'a', 1.0f); + } + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new CharacterMultiProperty("testCharacter", "Test character property", + new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER); + } + + @Override + protected PropertyDescriptor createBadProperty() { + return new CharacterProperty("", "Test character property", 'a', 1.0f); + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new CharacterMultiProperty("testCharacter", "Test character property", + new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java index af730a1dcc..0a7b84f424 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.DoubleMultiProperty; import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; @@ -16,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; * * @author Brian Remedios */ -public class DoublePropertyTest extends AbstractPropertyDescriptorTester { +public class DoublePropertyTest extends AbstractPropertyDescriptorTester { private static final double MIN = -10.0; private static final double MAX = 100.0; @@ -26,78 +28,37 @@ public class DoublePropertyTest extends AbstractPropertyDescriptorTester { super("Double"); } - /** - * Creates and returns (count) number of legal Double values - * - * @param count - * int - * @return Object - */ + @Override - protected Object createValue(int count) { - - if (count == 1) { - return Double.valueOf(randomDouble(MIN, MAX)); - } - - Double[] values = new Double[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Double) createValue(1); - } - return values; + protected Double createValue() { + return randomDouble(MIN, MAX); } - /** - * Creates and returns (count) number of out-of-range values - * - * @param count - * int - * @return Object - */ @Override - protected Object createBadValue(int count) { + protected Double createBadValue() { + return randomBool() ? randomDouble(MIN - SHIFT, MIN - 0.01) : randomDouble(MAX + 0.01, MAX + SHIFT); - if (count == 1) { - return Double.valueOf( - randomBool() ? randomDouble(MIN - SHIFT, MIN - 0.01) : randomDouble(MAX + 0.01, MAX + SHIFT)); - } - - Double[] values = new Double[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Double) createBadValue(1); - } - return values; } - /** - * Creates and returns a property with a (maxCount) value cardinality. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - return multiValue - ? new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, - new Double[] { -1d, 0d, 1d, 2d }, 1.0f) - : new DoubleProperty("testDouble", "Test double property", MIN, MAX, 9.0, 1.0f); + protected PropertyDescriptor createProperty() { + return new DoubleProperty("testDouble", "Test double property", MIN, MAX, 9.0, 1.0f); } - /** - * Attempts to create a property with invalid constructor arguments. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { + protected PropertyDescriptor> createMultiProperty() { + return new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, + new Double[] {-1d, 0d, 1d, 2d}, 1.0f); + } - return multiValue - ? new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, - new Double[] { MIN - SHIFT, MIN, MIN + SHIFT, MAX + SHIFT }, 1.0f) - : new DoubleProperty("testDouble", "Test double property", MAX, MIN, 9.0, 1.0f); + @Override + protected PropertyDescriptor createBadProperty() { + return new DoubleProperty("testDouble", "Test double property", MAX, MIN, 9.0, 1.0f); + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, + new Double[] {MIN - SHIFT, MIN, MIN + SHIFT, MAX + SHIFT}, 1.0f); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java index a49dc582ef..847f75421c 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java @@ -23,90 +23,51 @@ import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; */ public class EnumeratedPropertyTest extends AbstractPropertyDescriptorTester { - private static final String[] KEYS = new String[] { "map", "emptyArray", "list", "string", }; + private static final String[] KEYS = new String[] {"map", "emptyArray", "list", "string",}; - private static final Object[] VALUES = new Object[] { new HashMap(), new Object[0], new ArrayList(), - "Hello World!", }; + private static final Object[] VALUES = new Object[] {new HashMap(), new Object[0], new ArrayList(), + "Hello World!",}; public EnumeratedPropertyTest() { super("Enum"); } - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ + @Override - protected Object createValue(int count) { - - if (count == 1) { - return randomChoice(VALUES); - } - - Object[] values = new Object[count]; - for (int i = 0; i < values.length; i++) { - values[i] = createValue(1); - } - return values; + protected Object createValue() { + return randomChoice(VALUES); } - /** - * Returns a (count) number of values that are not in the set of legal - * values. - * - * @param count - * int - * @return Object - */ + @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return Integer.toString(randomInt()); // not in the set of values - } - - Object[] values = new Object[count]; - for (int i = 0; i < values.length; i++) { - values[i] = createBadValue(1); - } - return values; + protected Object createBadValue() { + return Integer.toString(randomInt()); // not in the set of values } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - return multiValue - ? new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, - VALUES, new int[] { 0, 1 }, 1.0f) - : new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, VALUES, 0, - 1.0f); + protected PropertyDescriptor createMultiProperty() { + return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, + VALUES, new int[] {0, 1}, 1.0f); } - /** - * Method createBadProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { + protected PropertyDescriptor createProperty() { + return new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, VALUES, 0, + 1.0f); + } - return multiValue - ? new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, - new Object[0], new int[] { 99 }, 1.0f) - : new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", new String[0], - VALUES, -1, 1.0f); + + @Override + protected PropertyDescriptor createBadProperty() { + + return new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", new String[0], + VALUES, -1, 1.0f); + } + + @Override + protected PropertyDescriptor createBadMultiProperty() { + return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, + new Object[0], new int[] {99}, 1.0f); } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java index 26a13b86e6..137be50b4b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.FloatMultiProperty; import net.sourceforge.pmd.lang.rule.properties.FloatProperty; @@ -16,93 +18,53 @@ import net.sourceforge.pmd.lang.rule.properties.FloatProperty; * * @author Brian Remedios */ -public class FloatPropertyTest extends AbstractPropertyDescriptorTester { +public class FloatPropertyTest extends AbstractPropertyDescriptorTester { private static final float MIN = 1.0f; private static final float MAX = 11.0f; private static final float SHIFT = 3.0f; + public FloatPropertyTest() { + super("Float"); + } + public static FloatProperty randomProperty(int nameLength, int descLength, boolean multiValue) { float defalt = randomFloat(0, 1000f); return new FloatProperty(randomString(nameLength), randomString(descLength), defalt - 1000f, defalt + 1000, - defalt, 0f); + defalt, 0f); } - public FloatPropertyTest() { - super("Float"); - } - - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ @Override - protected Object createValue(int count) { - - if (count == 1) { - return Float.valueOf(randomFloat(MIN, MAX)); - } - - Float[] values = new Float[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Float) createValue(1); - } - return values; + protected Float createValue() { + return randomFloat(MIN, MAX); } - /** - * Creates and returns (count) number of out-of-range float values - * - * @param count - * int - * @return Object - */ @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return Float.valueOf(randomBool() ? randomFloat(MIN - SHIFT, MIN) : randomFloat(MAX, MAX + SHIFT)); - } - - Float[] values = new Float[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Float) createBadValue(1); - } - return values; + protected Float createBadValue() { + return randomBool() ? randomFloat(MIN - SHIFT, MIN) : randomFloat(MAX, MAX + SHIFT); } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - return multiValue ? new FloatMultiProperty("testFloat", "Test float property", MIN, MAX, - new Float[] { -1f, 0f, 1f, 2f }, 1.0f) - : new FloatProperty("testFloat", "Test float property", MIN, MAX, 9.0f, 1.0f); + protected PropertyDescriptor createProperty() { + return new FloatProperty("testFloat", "Test float property", MIN, MAX, 9.0f, 1.0f); } - /** - * Method createBadProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { + protected PropertyDescriptor> createMultiProperty() { + return new FloatMultiProperty("testFloat", "Test float property", MIN, MAX, + new Float[] {-1f, 0f, 1f, 2f}, 1.0f); + } - return multiValue ? new FloatMultiProperty("testFloat", "Test float property", 0f, 5f, - new Float[] { -1f, 0f, 1f, 2f }, 1.0f) - : new FloatProperty("testFloat", "Test float property", 5f, 4f, 9.0f, 1.0f); + @Override + protected PropertyDescriptor createBadProperty() { + return new FloatProperty("testFloat", "Test float property", 5f, 4f, 9.0f, 1.0f); + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new FloatMultiProperty("testFloat", "Test float property", 0f, 5f, + new Float[] {-1f, 0f, 1f, 2f}, 1.0f); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java index f2a6fe00c4..24bfad08fd 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; @@ -18,7 +20,7 @@ import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; * * @author Brian Remedios */ -public class IntegerPropertyTest extends AbstractPropertyDescriptorTester { +public class IntegerPropertyTest extends AbstractPropertyDescriptorTester { private static final int MIN = 1; private static final int MAX = 12; @@ -28,80 +30,47 @@ public class IntegerPropertyTest extends AbstractPropertyDescriptorTester { super("Integer"); } - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ - @Override - protected Object createValue(int count) { - if (count == 1) { - return Integer.valueOf(randomInt(MIN, MAX)); - } - - Integer[] values = new Integer[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Integer) createValue(1); - } - return values; - } - - /** - * Creates and returns (count) number of out-of-range Integer values - * - * @param count - * int - * @return Object - */ - @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return Integer.valueOf(randomBool() ? randomInt(MIN - SHIFT, MIN) : randomInt(MAX, MAX + SHIFT)); - } - - Integer[] values = new Integer[count]; - for (int i = 0; i < values.length; i++) { - values[i] = (Integer) createBadValue(1); - } - return values; - } + /* @Override + @Test + public void testErrorForBadSingle() { + } // not until int properties get ranges @Override @Test - public void testErrorForBad() { + public void testErrorForBadMulti() { } // not until int properties get ranges - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ +*/ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - return multiValue - ? new IntegerMultiProperty("testInteger", "Test integer property", MIN, MAX, - new Integer[] { MIN, MIN + 1, MAX - 1, MAX }, 1.0f) - : new IntegerProperty("testInteger", "Test integer property", MIN, MAX, MAX - 1, 1.0f); + protected Integer createValue() { + return randomInt(MIN, MAX); } - /** - * Method createBadProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { + protected Integer createBadValue() { + return randomBool() ? randomInt(MIN - SHIFT, MIN) : randomInt(MAX, MAX + SHIFT); + } - return multiValue ? new IntegerMultiProperty("testInteger", "", MIN, MAX, new Integer[] { MIN - 1, MAX }, 1.0f) - : new IntegerProperty("", "Test integer property", MIN, MAX, MAX + 1, 1.0f); + @Override + protected PropertyDescriptor createProperty() { + return new IntegerProperty("testInteger", "Test integer property", MIN, MAX, MAX - 1, 1.0f); + } + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new IntegerMultiProperty("testInteger", "Test integer property", MIN, MAX, + new Integer[] { MIN, MIN + 1, MAX - 1, MAX }, 1.0f); + } + + @Override + protected PropertyDescriptor createBadProperty() { + return new IntegerProperty("", "Test integer property", MIN, MAX, MAX + 1, 1.0f); + + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new IntegerMultiProperty("testInteger", "", MIN, MAX, new Integer[] { MIN - 1, MAX }, 1.0f) ; } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java index a38ec43796..17d3fee01b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java @@ -9,6 +9,7 @@ import static org.junit.Assert.assertTrue; import java.lang.reflect.Method; import java.util.HashMap; +import java.util.List; import org.junit.Test; @@ -28,11 +29,13 @@ import net.sourceforge.pmd.util.ClassUtil; * * @author Brian Remedios */ -public class MethodPropertyTest extends AbstractPropertyDescriptorTester { +public class MethodPropertyTest extends AbstractPropertyDescriptorTester { - private static final String[] METHOD_SIGNATURES = new String[] { "String#indexOf(int)", "String#substring(int,int)", - "java.lang.String#substring(int,int)", "Integer#parseInt(String)", "java.util.HashMap#put(Object,Object)", - "HashMap#containsKey(Object)", }; + private static final Method[] allMethods = String.class.getDeclaredMethods(); + + private static final String[] METHOD_SIGNATURES = {"String#indexOf(int)", "String#substring(int,int)", + "java.lang.String#substring(int,int)", "Integer#parseInt(String)", "java.util.HashMap#put(Object,Object)", + "HashMap#containsKey(Object)",}; public MethodPropertyTest() { super("Method"); @@ -45,7 +48,7 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester { for (int i = 0; i < METHOD_SIGNATURES.length; i++) { method = MethodProperty.methodFrom(METHOD_SIGNATURES[i], MethodProperty.CLASS_METHOD_DELIMITER, - MethodProperty.METHOD_ARG_DELIMITER); + MethodProperty.METHOD_ARG_DELIMITER); assertNotNull("Unable to identify method: " + METHOD_SIGNATURES[i], method); } } @@ -57,7 +60,7 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester { for (int i = 0; i < METHOD_SIGNATURES.length; i++) { methods[i] = MethodProperty.methodFrom(METHOD_SIGNATURES[i], MethodProperty.CLASS_METHOD_DELIMITER, - MethodProperty.METHOD_ARG_DELIMITER); + MethodProperty.METHOD_ARG_DELIMITER); assertNotNull("Unable to identify method: " + METHOD_SIGNATURES[i], methods[i]); } @@ -65,63 +68,40 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester { for (int i = 0; i < methods.length; i++) { translatedMethod = MethodProperty.asStringFor(methods[i]); assertTrue("Translated method does not match", ClassUtil.withoutPackageName(METHOD_SIGNATURES[i]) - .equals(ClassUtil.withoutPackageName(translatedMethod))); + .equals(ClassUtil.withoutPackageName(translatedMethod))); } } @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { - - Method[] methods = String.class.getDeclaredMethods(); - - return multiValue - ? new MethodMultiProperty("methodProperty", "asdf", new Method[] { methods[2], methods[3] }, - new String[] { "java.util" }, 1.0f) - : new MethodProperty("methodProperty", "asdf", methods[1], new String[] { "java.util" }, 1.0f); + protected Method createValue() { + return randomChoice(allMethods); } @Override - protected Object createBadValue(int count) { - - Method[] allMethods = HashMap.class.getDeclaredMethods(); - - if (count == 1) { - return randomChoice(allMethods); - } - - Method[] methods = new Method[count]; - for (int i = 0; i < count; i++) { - methods[i] = allMethods[i]; - } - - return methods; + protected Method createBadValue() { + return randomChoice(HashMap.class.getDeclaredMethods()); } @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - Method[] methods = String.class.getDeclaredMethods(); - - return multiValue - ? new MethodMultiProperty("methodProperty", "asdf", new Method[] { methods[2], methods[3] }, - new String[] { "java.lang" }, 1.0f) - : new MethodProperty("methodProperty", "asdf", methods[1], new String[] { "java.lang" }, 1.0f); + protected PropertyDescriptor createProperty() { + return new MethodProperty("methodProperty", "asdf", allMethods[1], new String[] {"java.lang"}, 1.0f); } @Override - protected Object createValue(int count) { + protected PropertyDescriptor> createMultiProperty() { + return new MethodMultiProperty("methodProperty", "asdf", new Method[] {allMethods[2], allMethods[3]}, + new String[] {"java.lang"}, 1.0f); + } - Method[] allMethods = String.class.getDeclaredMethods(); + @Override + protected PropertyDescriptor createBadProperty() { + return new MethodProperty("methodProperty", "asdf", allMethods[1], new String[] {"java.util"}, 1.0f); - if (count == 1) { - return randomChoice(allMethods); - } + } - Method[] methods = new Method[count]; - for (int i = 0; i < count; i++) { - methods[i] = allMethods[i]; - } - - return methods; + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new MethodMultiProperty("methodProperty", "asdf", new Method[] {allMethods[2], allMethods[3]}, + new String[] {"java.util"}, 1.0f); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java index cb95a1428a..685705d0af 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java @@ -4,11 +4,11 @@ package net.sourceforge.pmd.properties; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; + +import java.util.Arrays; import org.junit.Before; import org.junit.Ignore; @@ -16,7 +16,6 @@ import org.junit.Test; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.cpd.ReportException; -import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.NumericConstants; /** @@ -37,8 +36,8 @@ public class PropertyAccessorTest { assertSame(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_INT), 0); rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_INT, - new Integer[] { NumericConstants.ZERO, NumericConstants.ONE }); - assertArrayEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_INT), new Integer[] { 0, 1 }); + Arrays.asList(NumericConstants.ZERO, NumericConstants.ONE)); + assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_INT), Arrays.asList(0, 1)); } @Test @@ -47,8 +46,8 @@ public class PropertyAccessorTest { rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_BOOL, Boolean.FALSE); assertFalse(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_BOOL)); - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL, new Boolean[] { Boolean.TRUE, Boolean.FALSE }); - assertArrayEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL), new Boolean[] { true, false }); + rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL, Arrays.asList(Boolean.TRUE, Boolean.FALSE)); + assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL), Arrays.asList(true, false)); } @Ignore @@ -79,8 +78,8 @@ public class PropertyAccessorTest { rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_STR, "brian"); assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_STR), "brian"); - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_STR, new String[] { "hello", "world" }); - assertTrue(CollectionUtil.arraysAreEqual(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_STR), - new String[] { "hello", "world" })); + rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_STR, Arrays.asList("hello", "world")); + assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_STR), + Arrays.asList("hello", "world")); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java index 5a3830fcfe..dc6c743317 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; import net.sourceforge.pmd.lang.rule.properties.StringProperty; @@ -16,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.StringProperty; * * @author Brian Remedios */ -public class StringPropertyTest extends AbstractPropertyDescriptorTester { +public class StringPropertyTest extends AbstractPropertyDescriptorTester { private static final int MAX_STRING_LENGTH = 52; private static final char DELIMITER = '|'; @@ -26,48 +28,6 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester { super("String"); } - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ - @Override - protected Object createValue(int count) { - - if (count == 1) { - return newString(); - } - - String[] values = new String[count]; - for (int i = 0; i < count; i++) { - values[i] = (String) createValue(1); - } - return values; - } - - /** - * Method createBadValue. - * - * @param count - * int - * @return Object - */ - @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return null; - } - - Object[] values = new Object[count]; - for (int i = 0; i < count; i++) { - values[i] = createBadValue(1); - } - return values; - } - /** * Method newString. * @@ -87,40 +47,44 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester { /** * Method randomCharIn. * - * @param chars - * char[] + * @param chars char[] + * * @return char */ private char randomCharIn(char[] chars) { return randomChar(chars); } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ + @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - return multiValue ? new StringMultiProperty("testString", "Test string property", - new String[] { "hello", "world" }, 1.0f, DELIMITER) - : new StringProperty("testString", "Test string property", "brian", 1.0f); + protected String createValue() { + return newString(); } - /** - * Method createBadProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { - return multiValue - ? new StringMultiProperty("testString", "Test string property", - new String[] { "hello", "world", "a" + DELIMITER + "b" }, 1.0f, DELIMITER) - : new StringProperty("", "Test string property", "brian", 1.0f); + protected String createBadValue() { + return null; + } + + @Override + protected PropertyDescriptor createProperty() { + return new StringProperty("testString", "Test string property", "brian", 1.0f); + } + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new StringMultiProperty("testString", "Test string property", + new String[] {"hello", "world"}, 1.0f, DELIMITER); + } + + @Override + protected PropertyDescriptor createBadProperty() { + return new StringProperty("", "Test string property", "brian", 1.0f); + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new StringMultiProperty("testString", "Test string property", + new String[] {"hello", "world", "a" + DELIMITER + "b"}, 1.0f, DELIMITER); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java index 3d6f3492ea..d2ddf8ac69 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.properties; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Observer; import java.util.Set; @@ -25,91 +26,48 @@ import net.sourceforge.pmd.lang.rule.properties.TypeProperty; * * @author Brian Remedios */ -public class TypePropertyTest extends AbstractPropertyDescriptorTester { +public class TypePropertyTest extends AbstractPropertyDescriptorTester { - private static final Class[] JAVA_LANG_CLASSES = new Class[] { String.class, Integer.class, Thread.class, - Object.class, Runtime.class, }; - private static final Class[] JAVA_UTIL_CLASSES = new Class[] { HashMap.class, Map.class, Comparator.class, Set.class, - Observer.class, }; + private static final Class[] JAVA_LANG_CLASSES = {String.class, Integer.class, Thread.class, + Object.class, Runtime.class,}; + private static final Class[] JAVA_UTIL_CLASSES = {HashMap.class, Map.class, Comparator.class, Set.class, + Observer.class,}; public TypePropertyTest() { super("Class"); } - /** - * Method createValue. - * - * @param count - * int - * @return Object - */ @Override - protected Object createValue(int count) { - - if (count == 1) { - return randomChoice(JAVA_LANG_CLASSES); - } - - Object[] values = new Object[count]; - for (int i = 0; i < values.length; i++) { - values[i] = createValue(1); - } - return values; + protected Class createValue() { + return randomChoice(JAVA_LANG_CLASSES); } - /** - * Method createBadValue. - * - * @param count - * int - * @return Object - */ @Override - protected Object createBadValue(int count) { - - if (count == 1) { - return randomChoice(JAVA_UTIL_CLASSES); - } - - Object[] values = new Object[count]; - for (int i = 0; i < values.length; i++) { - values[i] = createBadValue(1); - } - return values; + protected Class createBadValue() { + return randomChoice(JAVA_UTIL_CLASSES); } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createProperty(boolean multiValue) { - - return multiValue - ? new TypeMultiProperty("testType", "Test type property", JAVA_LANG_CLASSES, new String[] { "java.lang" }, - 1.0f) - : new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] { "java.lang" }, - 1.0f); + protected PropertyDescriptor createProperty() { + return new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] {"java.lang"}, + 1.0f); } - /** - * Method createProperty. - * - * @param multiValue - * boolean - * @return PropertyDescriptor - */ @Override - protected PropertyDescriptor createBadProperty(boolean multiValue) { - - return multiValue - ? new TypeMultiProperty("testType", "Test type property", new Class[] { Set.class }, - new String[] { "java.lang" }, 1.0f) - : new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] { "java.util" }, - 1.0f); + protected PropertyDescriptor> createMultiProperty() { + return new TypeMultiProperty("testType", "Test type property", JAVA_LANG_CLASSES, new String[] {"java.lang"}, + 1.0f); } + @Override + protected PropertyDescriptor createBadProperty() { + return new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] {"java.util"}, + 1.0f); + } + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new TypeMultiProperty("testType", "Test type property", new Class[] {Set.class}, + new String[] {"java.lang"}, 1.0f); + } } From 1104b6cd49b107a6a2b28a93a246b0c52bb224cb Mon Sep 17 00:00:00 2001 From: oowekyala Date: Mon, 26 Jun 2017 21:08:53 +0200 Subject: [PATCH 06/53] Debugged tests --- .../properties/AbstractPackagedProperty.java | 4 ++ .../AbstractSingleValueProperty.java | 4 +- .../rule/properties/BooleanMultiProperty.java | 23 +----- .../lang/rule/properties/BooleanProperty.java | 2 +- .../properties/CharacterMultiProperty.java | 3 +- .../rule/properties/IntegerMultiProperty.java | 3 +- .../lang/rule/properties/MethodProperty.java | 25 +------ .../BasicPropertyDescriptorFactory.java | 4 +- .../sourceforge/pmd/RuleSetFactoryTest.java | 70 +++++++++---------- 9 files changed, 52 insertions(+), 86 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index ba2afcbafb..04b088c02f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -89,6 +89,10 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro * @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) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index c56e550716..eee8aedbda 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -60,8 +60,8 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty @Override - public String asDelimitedString(T values, char delimiter) { - return values == null ? "" : values.toString(); + public String asDelimitedString(T value, char delimiter) { + return value == null ? "" : asString(value); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index ee1b8302da..aa344d6445 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -30,26 +30,12 @@ public class BooleanMultiProperty extends AbstractMultiValueProperty { } }; - /** - * Constructor for BooleanMultiProperty that allows for multiple values. - * - * @param theName String - * @param theDescription String - * @param defaultValues Boolean[] - * @param theUIOrder float - */ + public BooleanMultiProperty(String theName, String theDescription, Boolean[] defaultValues, float theUIOrder) { super(theName, theDescription, defaultValues, theUIOrder); } - /** - * Constructor for BooleanMultiProperty that allows for multiple values. - * - * @param theName String - * @param theDescription String - * @param defaultValues Boolean[] - * @param theUIOrder float - */ + public BooleanMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder) { super(theName, theDescription, defaultValues, theUIOrder); } @@ -65,9 +51,4 @@ public class BooleanMultiProperty extends AbstractMultiValueProperty { return Boolean.class; } - - @Override - public List valueFrom(String propertyString) throws IllegalArgumentException { - return null; - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index b980ad6b97..88d796a7a0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -59,7 +59,7 @@ public class BooleanProperty extends AbstractSingleValueProperty { @Override public Boolean createFrom(String propertyString) throws IllegalArgumentException { - return null; + return Boolean.valueOf(propertyString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index d3b975f889..ba26edea33 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -27,7 +27,8 @@ public class CharacterMultiProperty extends AbstractMultiValueProperty public IntegerMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - Integer[] defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, PrimitiveExtractor.INTEGER_EXTRACTOR); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, PrimitiveExtractor + .INTEGER_EXTRACTOR); return new IntegerMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Integer.parseInt(minMax[0]), Integer.parseInt(minMax[1]), defaultValues, 0f); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 80550b3e38..ae158b4056 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -41,33 +41,12 @@ public class MethodProperty extends AbstractPackagedProperty { private static final String ARRAY_FLAG = "[]"; private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); - /** - * Constructor for MethodProperty. - * - * @param theName String - * @param theDescription String - * @param theDefault Method - * @param legalPackageNames String[] - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); } - /** - * Constructor for MethodProperty. - * - * @param theName String - * @param theDescription String - * @param defaultMethodStr String - * @param legalPackageNames String[] - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ + public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder); @@ -253,7 +232,7 @@ public class MethodProperty extends AbstractPackagedProperty { @Override protected String packageNameOf(Method method) { - return method.getDeclaringClass().getName() + '.' + method.getName(); + return method == null ? null : method.getDeclaringClass().getName() + '.' + method.getName(); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index 38e72f8997..d17f183ee0 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -74,13 +74,13 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact // TODO change return type to List someday @SuppressWarnings("unckecked") - protected static U[] parsePrimitives(String toParse, char delimiter, PrimitiveExtractor extractor) { + protected static List parsePrimitives(String toParse, char delimiter, PrimitiveExtractor extractor) { String[] values = StringUtil.substringsOf(toParse, delimiter); List result = new ArrayList<>(); for (String s : values) { result.add(extractor.valueOf(s)); } - return (U[]) result.toArray(); + return result; } protected static Long[] longsIn(String numberString, char delimiter) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 77fea1611b..9a22269941 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -14,7 +14,9 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.junit.Assert; @@ -55,7 +57,7 @@ public class RuleSetFactoryTest { public void testExtendedReferences() throws Exception { InputStream in = ResourceLoader.loadResourceAsStream("net/sourceforge/pmd/rulesets/reference-ruleset.xml", this.getClass().getClassLoader()); - Assert.assertNotNull("Test ruleset not found - can't continue with test!", in); + assertNotNull("Test ruleset not found - can't continue with test!", in); in.close(); RuleSetFactory rsf = new RuleSetFactory(); @@ -168,34 +170,32 @@ public class RuleSetFactoryTest { @Test public void testStringMultiPropertyDefaultDelimiter() throws Exception { - Rule r = loadFirstRule("\n" + "\n" - + " Desc\n" - + " \n" + " Please move your class to the right folder(rest \n" - + "folder)\n" + " 2\n" + " \n" - + " \n" + " " + "" - + ""); - PropertyDescriptor prop = r.getPropertyDescriptor("packageRegEx"); - String[] values = (String[]) r.getProperty(prop); - Assert.assertArrayEquals(new String[] { "com.aptsssss", "com.abc" }, values); + Rule r = loadFirstRule("\n\n Desc\n" + + " \n" + + " Please move your class to the right folder(rest \nfolder)\n" + + " 2\n \n \n "); + PropertyDescriptor> prop = (PropertyDescriptor>) r.getPropertyDescriptor("packageRegEx"); + List values = r.getProperty(prop); + assertEquals(Arrays.asList("com.aptsssss", "com.abc"), values); } @Test public void testStringMultiPropertyDelimiter() throws Exception { - Rule r = loadFirstRule("\n" + "\n" - + " ruleset desc\n" - + " \n" + " Please move your class to the right folder(rest \n" - + "folder)\n" + " 2\n" + " \n" - + " \n" + " " - + "" + ""); - PropertyDescriptor prop = r.getPropertyDescriptor("packageRegEx"); - String[] values = (String[]) r.getProperty(prop); - Assert.assertArrayEquals(new String[] { "com.aptsssss", "com.abc" }, values); + Rule r = loadFirstRule("\n" + "\n " + + " ruleset desc\n " + + "\n" + + " Please move your class to the right folder(rest \nfolder)\n" + + " 2\n \n \n" + + " " + ""); + PropertyDescriptor> prop = (PropertyDescriptor>) r.getPropertyDescriptor("packageRegEx"); + List values = r.getProperty(prop); + assertEquals(Arrays.asList("com.aptsssss", "com.abc"), values); } @Test @@ -204,9 +204,9 @@ public class RuleSetFactoryTest { + " ruleset desc\n" + " " + ""); - Assert.assertEquals(1, rs.getRules().size()); + assertEquals(1, rs.getRules().size()); Rule rule = rs.getRuleByName("DummyBasicMockRule"); - Assert.assertNotNull(rule); + assertNotNull(rule); } @Test @@ -217,10 +217,10 @@ public class RuleSetFactoryTest { + " " + " d\n" + " 2\n" + " " + ""); - Assert.assertEquals(1, rs.getRules().size()); + assertEquals(1, rs.getRules().size()); Rule rule = rs.getRuleByName("NewName"); - Assert.assertNotNull(rule); - Assert.assertNull(rs.getRuleByName("OldName")); + assertNotNull(rule); + assertNull(rs.getRuleByName("OldName")); } @Test @@ -228,9 +228,9 @@ public class RuleSetFactoryTest { RuleSet rs = loadRuleSet("\n" + "\n" + " ruleset desc\n" + " " + ""); - Assert.assertEquals(1, rs.getRules().size()); + assertEquals(1, rs.getRules().size()); Rule rule = rs.getRuleByName("OldNameOfDummyBasicMockRule"); - Assert.assertNotNull(rule); + assertNotNull(rule); } @Test @@ -609,7 +609,7 @@ public class RuleSetFactoryTest { + " \n" + "\n"); RuleSetFactory ruleSetFactory = new RuleSetFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref1); - Assert.assertNull(ruleset.getRuleByName("DummyBasicMockRule")); + assertNull(ruleset.getRuleByName("DummyBasicMockRule")); RuleSetReferenceId ref2 = createRuleSetReferenceId( "\n" + "\n" + " \n" + "\n"); RuleSetFactory ruleSetFactory2 = new RuleSetFactory(); RuleSet ruleset2 = ruleSetFactory2.createRuleSet(ref2); - Assert.assertNotNull(ruleset2.getRuleByName("DummyBasicMockRule")); + assertNotNull(ruleset2.getRuleByName("DummyBasicMockRule")); RuleSetReferenceId ref3 = createRuleSetReferenceId( "\n" + "\n" + " \n" + "\n"); RuleSetFactory ruleSetFactory3 = new RuleSetFactory(); RuleSet ruleset3 = ruleSetFactory3.createRuleSet(ref3); - Assert.assertNotNull(ruleset3.getRuleByName("DummyBasicMockRule")); + assertNotNull(ruleset3.getRuleByName("DummyBasicMockRule")); } @org.junit.Rule From 68f869e81e594f8e1183c07bbefb03a85a9162b9 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Mon, 26 Jun 2017 23:51:50 +0200 Subject: [PATCH 07/53] Turned PropertyDescriptorFields into an enum Fully commented multi valued properties --- .../sourceforge/pmd/PropertyDescriptor.java | 5 +- .../pmd/PropertyDescriptorFactory.java | 4 +- .../pmd/PropertyDescriptorField.java | 59 ++++++ .../pmd/PropertyDescriptorFields.java | 47 ----- .../net/sourceforge/pmd/RuleSetFactory.java | 6 +- .../net/sourceforge/pmd/RuleSetWriter.java | 4 +- .../AbstractMultiNumericProperty.java | 43 +++-- .../AbstractMultiPackagedProperty.java | 26 ++- .../AbstractMultiValueProperty.java | 86 ++++----- .../properties/AbstractNumericProperty.java | 23 ++- .../properties/AbstractPackagedProperty.java | 8 +- .../rule/properties/AbstractProperty.java | 46 +++-- .../AbstractSingleValueProperty.java | 13 +- .../rule/properties/BooleanMultiProperty.java | 41 ++++- .../lang/rule/properties/BooleanProperty.java | 17 +- .../properties/CharacterMultiProperty.java | 70 +++---- .../rule/properties/CharacterProperty.java | 16 +- .../rule/properties/DoubleMultiProperty.java | 64 ++++--- .../lang/rule/properties/DoubleProperty.java | 5 + .../properties/EnumeratedMultiProperty.java | 89 ++++++--- .../rule/properties/EnumeratedProperty.java | 45 +++-- .../lang/rule/properties/FileProperty.java | 5 +- .../rule/properties/FloatMultiProperty.java | 59 +++--- .../lang/rule/properties/FloatProperty.java | 5 + .../rule/properties/IntegerMultiProperty.java | 77 ++++---- .../lang/rule/properties/IntegerProperty.java | 42 ++--- .../rule/properties/LongMultiProperty.java | 77 ++++---- .../lang/rule/properties/LongProperty.java | 4 + .../rule/properties/MethodMultiProperty.java | 6 +- .../lang/rule/properties/MethodProperty.java | 14 ++ .../properties/PropertyDescriptorFactory.java | 11 +- .../properties/PropertyDescriptorWrapper.java | 22 +++ .../rule/properties/StringMultiProperty.java | 57 +++--- .../lang/rule/properties/StringProperty.java | 10 +- .../rule/properties/TypeMultiProperty.java | 26 ++- .../lang/rule/properties/TypeProperty.java | 8 + .../BasicPropertyDescriptorFactory.java | 173 ++++++++---------- .../factories/PropertyDescriptorUtil.java | 5 +- .../properties/factories/ValueParser.java | 84 +++++++++ .../AbstractPropertyDescriptorTester.java | 12 +- 40 files changed, 869 insertions(+), 545 deletions(-) create mode 100755 pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java delete mode 100755 pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index b0091d98d5..8633213442 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -126,7 +126,8 @@ public interface PropertyDescriptor extends Comparable> * Returns a set of choice tuples if available, returns null if none are * defined. * - * @return Object[][] + * @return a set of choice tuples if available, returns null if none are + * defined. */ Set> choices(); @@ -164,5 +165,5 @@ public interface PropertyDescriptor extends Comparable> * * @return map */ - Map attributeValuesById(); + Map attributeValuesById(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index 61b4450f6a..f2d66cc9fa 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -27,7 +27,7 @@ public interface PropertyDescriptorFactory { * * @return Map */ - Map expectedFields(); + Map expectedFields(); /** * Create a property descriptor of the appropriate type using the values @@ -37,5 +37,5 @@ public interface PropertyDescriptorFactory { * the map of values * @return a new and initialized {@link PropertyDescriptor} */ - PropertyDescriptor createWith(Map valuesById); + PropertyDescriptor createWith(Map valuesById); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java new file mode 100755 index 0000000000..dbb761d557 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java @@ -0,0 +1,59 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; + +/** + * Field names for parsing the properties out of the ruleset xml files. + * + * @author Brian Remedios + * @see RuleSetFactory + */ +public enum PropertyDescriptorField { + + /** + * The type of the property. + * + * @see PropertyDescriptorUtil + */ + TYPE("type"), + /** The name of the property. */ + NAME("name"), + /** The description of the property. */ + DESCRIPTION("description"), + /** The description of the property. */ + DESC("description"), + /** The default value. */ + VALUE("value"), + /** The default value. */ + DEFAULT_VALUE("value"), + /** For multi-valued properties, this defines the delimiter of the single values. */ + DELIMITER("delimiter"), + /** The minium allowed value. */ + MIN("min"), + /** The maximum allowed value. */ + MAX("max"), + /** To limit the range of valid values, {@literal e.g.} to Enums. */ + LEGAL_PACKAGES("legalPackages"), + /** Labels for enumerated properties. */ + LABELS("labels"), + /** Choices for enumerated properties. */ + CHOICES("choices"), + /** Default index for enumerated properties. */ + DEFAULT_INDEX("defaultIndex"); + + final String representation; + + PropertyDescriptorField(String representation) { + this.representation = representation; + } + + @Override + public String toString() { + return representation; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java deleted file mode 100755 index 476f09e22b..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFields.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd; - -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; - -/** - * Field names for parsing the properties out of the ruleset xml files. - * - * @author Brian Remedios - * @see RuleSetFactory - */ -public class PropertyDescriptorFields { - - /** - * The type of the property. - * - * @see PropertyDescriptorUtil - */ - public static final String TYPE = "type"; - /** The name of the property. */ - public static final String NAME = "name"; - /** The description of the property. */ - public static final String DESCRIPTION = "description"; - /** The description of the property. */ - public static final String DESC = "description"; - /** The default value. */ - public static final String VALUE = "value"; - /** The default value. */ - public static final String DEFAULT_VALUE = "value"; - /** - * For multi-valued properties, this defines the delimiter of the single - * values. - */ - public static final String DELIMITER = "delimiter"; - /** The minium allowed value. */ - public static final String MIN = "min"; - /** The maximum allowed value. */ - public static final String MAX = "max"; - /** To limit the range of valid values, e.g. to Enums */ - public static final String LEGAL_PACKAGES = "legalPackages"; - - private PropertyDescriptorFields() { - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 70b42b55d0..378270427a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -848,15 +848,15 @@ public class RuleSetFactory { private static void parsePropertyNodeBR(Rule rule, Node propertyNode) { Element propertyElement = (Element) propertyNode; - String typeId = propertyElement.getAttribute(PropertyDescriptorFields.TYPE); - String strValue = propertyElement.getAttribute(PropertyDescriptorFields.VALUE); + String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE); + String strValue = propertyElement.getAttribute(PropertyDescriptorField.VALUE); if (StringUtil.isEmpty(strValue)) { strValue = valueFrom(propertyElement); } // Setting of existing property, or defining a new property? if (StringUtil.isEmpty(typeId)) { - String name = propertyElement.getAttribute(PropertyDescriptorFields.NAME); + String name = propertyElement.getAttribute(PropertyDescriptorField.NAME); PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); if (propertyDescriptor == null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 8df757af97..cd40879599 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -385,8 +385,8 @@ public class RuleSetWriter { final Element propertyElement = createPropertyValueElement(propertyDescriptor, propertyDescriptor.defaultValue()); - propertyElement.setAttribute(PropertyDescriptorFields.TYPE, - PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type())); + propertyElement.setAttribute(PropertyDescriptorField.TYPE, + PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type())); Map propertyValuesById = propertyDescriptor.attributeValuesById(); for (Map.Entry entry : propertyValuesById.entrySet()) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 75adb71d0a..adcd82bb06 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -4,47 +4,51 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.PropertyDescriptorFields.MAX; -import static net.sourceforge.pmd.PropertyDescriptorFields.MIN; +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; /** - * @param + * Base class for multi-valued numeric properties. + * + * @param The type of number * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty implements NumericPropertyDescriptor> { - - private Number lowerLimit; - private Number upperLimit; + private T lowerLimit; + private T upperLimit; /** - * Constructor for AbstractMultiNumericProperty.Object + * Constructor for a multi-valued numeric property using a list of defaults. * - * @param theName String - * @param theDescription String - * @param lower Number - * @param upper Number - * @param theDefault T - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault List of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public AbstractMultiNumericProperty(String theName, String theDescription, Number lower, Number upper, - List theDefault, float theUIOrder) { + public AbstractMultiNumericProperty(String theName, String theDescription, T min, T max, List theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); - if (lower.doubleValue() > upper.doubleValue()) { + if (min.doubleValue() > max.doubleValue()) { throw new IllegalArgumentException("Lower limit cannot be greater than the upper limit"); } - lowerLimit = lower; - upperLimit = upper; + lowerLimit = min; + upperLimit = max; } @@ -72,8 +76,9 @@ public abstract class AbstractMultiNumericProperty extends Abs return null; } + @Override - protected void addAttributesTo(Map attributes) { + protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); attributes.put(MIN, lowerLimit.toString()); attributes.put(MAX, upperLimit.toString()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index 17dbfe331b..a3ba48202e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -4,25 +4,33 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES; +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.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * @param + * Multi-valued property restricting the type of its values to some packages. + * + * @param The type of the values * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty { + /** Delimiter between values. */ protected static final char DELIMITER = '|'; - protected static final Map PACKAGED_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory - .expectedFieldTypesWith(new String[] {LEGAL_PACKAGES}, new Boolean[] {Boolean.FALSE}); + /** Required keys in the map. */ + protected static final Map PACKAGED_FIELD_TYPES_BY_KEY + = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, + new Boolean[] {false}); private static final char PACKAGE_NAME_DELIMITER = ' '; private String[] legalPackageNames; @@ -47,13 +55,15 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu legalPackageNames = theLegalPackageNames; } + protected static String[] packageNamesIn(Map params) { // TODO return null; } + @Override - protected void addAttributesTo(Map attributes) { + protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); attributes.put(LEGAL_PACKAGES, delimitedPackageNames()); @@ -77,6 +87,7 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu return sb.toString(); } + /** * 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. @@ -113,6 +124,7 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu throw new IllegalArgumentException("Invalid items: " + notAllowed); } + /** * Returns the name of the type of item. * @@ -146,6 +158,7 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu return "Disallowed " + itemTypeName() + ": " + name; } + /** * Returns the package name of the item. * @@ -155,12 +168,13 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu */ protected abstract String packageNameOf(T item); + /** * Returns the legal package names. * * @return The legal package names */ public String[] legalPackageNames() { - return legalPackageNames; + return Arrays.copyOf(legalPackageNames, legalPackageNames.length); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 9e0aafdc4b..a84ccb298f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -5,7 +5,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map.Entry; import java.util.Set; @@ -14,11 +14,12 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.Rule; /** - * Multi valued property. + * Multi-valued property. * * @param The type of the individual values. The multiple values are wrapped into a list. * * @author Clément Fournier + * @version 6.0.0 */ public abstract class AbstractMultiValueProperty extends AbstractProperty> { @@ -42,7 +43,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty extends AbstractProperty extends AbstractProperty values, char delimiter) { if (values == null) { @@ -133,6 +108,17 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty realValues = rule.getProperty(this); + if (realValues == null && !isRequired()) { + return null; + } + return errorFor(realValues); + } + + @Override public String errorFor(List values) { @@ -147,6 +133,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty extends AbstractProperty>> choices() { return null; } - /* This is the one overriden in PropertyDescriptor */ - @Override - public String propertyErrorFor(Rule rule) { - List realValues = rule.getProperty(this); - if (realValues == null && !isRequired()) { - return null; - } - return errorFor(realValues); - } - /** * Returns a string representation of the default value. * @@ -183,8 +161,9 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty extends AbstractProperty valueFrom(String valueString) throws IllegalArgumentException { String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter())); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index b70cbef6ac..38d7b7403c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -4,12 +4,13 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.PropertyDescriptorFields.MAX; -import static net.sourceforge.pmd.PropertyDescriptorFields.MIN; +import static net.sourceforge.pmd.PropertyDescriptorField.MAX; +import static net.sourceforge.pmd.PropertyDescriptorField.MIN; import java.util.Map; import net.sourceforge.pmd.NumericPropertyDescriptor; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -23,9 +24,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public abstract class AbstractNumericProperty extends AbstractSingleValueProperty implements NumericPropertyDescriptor { - public static final Map NUMBER_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory - .expectedFieldTypesWith(new String[] {MIN, MAX}, new Boolean[] {Boolean.TRUE, Boolean.TRUE}); - + public static final Map NUMBER_FIELD_TYPES_BY_KEY + = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, + new Boolean[] {true, true}); private Number lowerLimit; private Number upperLimit; @@ -43,15 +44,20 @@ public abstract class AbstractNumericProperty extends Abstract upperLimit = upper; } + /** * Returns a string representing the range defined by the two bounds. * + * @param low Lower bound + * @param up Upper bound + * * @return String */ - public static String rangeString(Number low, Number up) { + static String rangeString(Number low, Number up) { return "(" + low + " -> " + up + ")"; } + /** * Returns the minimum value that instances of the property can have * @@ -62,6 +68,7 @@ public abstract class AbstractNumericProperty extends Abstract return lowerLimit; } + /** * Returns the maximum value that instances of the property can have * @@ -72,6 +79,7 @@ public abstract class AbstractNumericProperty extends Abstract return upperLimit; } + /** * Returns a string describing any error the value may have when * characterized by the receiver. @@ -92,8 +100,9 @@ public abstract class AbstractNumericProperty extends Abstract return null; } + @Override - protected void addAttributesTo(Map attributes) { + protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); attributes.put(MIN, lowerLimit.toString()); attributes.put(MAX, upperLimit.toString()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index 04b088c02f..d78e91eb55 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES; +import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES; import java.util.Map; @@ -48,11 +48,13 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro legalPackageNames = theLegalPackageNames; } + protected static String[] packageNamesIn(Map params) { // TODO return null; } + @Override protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); @@ -79,6 +81,7 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro return sb.toString(); } + /** * 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. @@ -104,6 +107,7 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro throw new IllegalArgumentException("Invalid item: " + item); } + /** * Returns the name of the type of item. * @@ -137,6 +141,7 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro return "Disallowed " + itemTypeName() + ": " + name; } + /** * Returns the package name of the item. * @@ -146,6 +151,7 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro */ protected abstract String packageNameOf(T item); + /** * Returns the legal package names. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 68f07a9dd2..ee90634568 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -4,15 +4,15 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.PropertyDescriptorFields.DEFAULT_VALUE; -import static net.sourceforge.pmd.PropertyDescriptorFields.DESCRIPTION; -import static net.sourceforge.pmd.PropertyDescriptorFields.NAME; +import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; +import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION; +import static net.sourceforge.pmd.PropertyDescriptorField.NAME; import java.util.HashMap; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.PropertyDescriptorFields; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.StringUtil; /** @@ -55,6 +55,7 @@ public abstract class AbstractProperty implements PropertyDescriptor { this(theName, theDescription, theUIOrder, DEFAULT_DELIMITER); } + /** * Constructor for AbstractPMDProperty. * @@ -86,6 +87,7 @@ public abstract class AbstractProperty implements PropertyDescriptor { return arg; } + /** * Tests if two values are equal. * @@ -107,42 +109,49 @@ public abstract class AbstractProperty implements PropertyDescriptor { return name; } + @Override public String description() { return description; } + @Override public boolean isRequired() { return isRequired; } + @Override public float uiOrder() { return uiOrder; } + @Override public char multiValueDelimiter() { return multiValueDelimiter; } + @Override public final String asDelimitedString(T values) { return asDelimitedString(values, multiValueDelimiter()); } + /** - * Return the specified values as a single string using the delimiter. + * Return the specified values as a single string using the specified delimiter. * * @param values Values to format - * @param delimiter char + * @param delimiter Delimiter character * - * @return String + * @return Delimited string * * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(T) */ - public abstract String asDelimitedString(T values, char delimiter); + protected abstract String asDelimitedString(T values, char delimiter); + @Override public final int compareTo(PropertyDescriptor otherProperty) { @@ -171,6 +180,7 @@ public abstract class AbstractProperty implements PropertyDescriptor { return false; } + @Override public int hashCode() { return name.hashCode(); @@ -179,7 +189,9 @@ public abstract class AbstractProperty implements PropertyDescriptor { @Override public String toString() { - return "[PropertyDescriptor: name=" + name() + ", type=" + type() + ", value=" + defaultValue() + "]"; + return "[PropertyDescriptor: name=" + name() + "," + + " type=" + (isMultiValue() ? "List<" + type() + ">" : type()) + "," + + " value=" + defaultValue() + "]"; } @@ -190,20 +202,26 @@ public abstract class AbstractProperty implements PropertyDescriptor { */ protected abstract String defaultAsString(); + @Override - public Map attributeValuesById() { - Map values = new HashMap<>(); + public final Map attributeValuesById() { + Map values = new HashMap<>(); addAttributesTo(values); return values; } - protected void addAttributesTo(Map attributes) { + + /** + * Adds this property's attributes to the map. Subclasses can override this to add more Property fields. + * + * @param attributes The map to fill + */ + protected void addAttributesTo(Map attributes) { attributes.put(NAME, name); attributes.put(DESCRIPTION, description); attributes.put(DEFAULT_VALUE, defaultAsString()); if (isMultiValue()) { - attributes.put(PropertyDescriptorFields.DELIMITER, Character.toString(multiValueDelimiter())); + attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); } } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index eee8aedbda..e95bfc3787 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -21,6 +21,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty /** Default value. */ protected T defaultValue; + /** * Creates a single value property using the default delimiter {@link #DEFAULT_DELIMITER}. * @@ -43,6 +44,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return defaultValue; } + /** * Returns true if the default value is {@code null}. * @@ -52,18 +54,19 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return defaultValue == null; } + @Override public final boolean isMultiValue() { return false; } - @Override public String asDelimitedString(T value, char delimiter) { return value == null ? "" : asString(value); } + @Override public String propertyErrorFor(Rule rule) { T realValue = rule.getProperty(this); @@ -73,6 +76,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return errorFor(realValue); } + @Override public String errorFor(T value) { String typeError = typeErrorFor(value); @@ -82,6 +86,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return valueErrorFor(value); } + private String typeErrorFor(T value) { // TODO:cf consider subtypes!! if (value != null && !type().isAssignableFrom(value.getClass())) { @@ -91,24 +96,29 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty return null; } + protected String valueErrorFor(T value) { return value != null || defaultHasNullValue() ? null : "missing value"; } + protected String asString(T value) { return value == null ? "" : value.toString(); } + @Override protected final String defaultAsString() { return asString(defaultValue); } + @Override public Set> choices() { return null; } + /** * Parse a string and returns an instance of a value. * @@ -120,6 +130,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty // this is there to be symmetrical. + @Override public final T valueFrom(String valueString) throws IllegalArgumentException { return createFrom(valueString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index aa344d6445..a29580168c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -4,10 +4,14 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.BOOLEAN_PARSER; + +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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -17,32 +21,49 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class BooleanMultiProperty extends AbstractMultiValueProperty { - /** - * Factory. - */ - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>( - Boolean.class) { + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory>(Boolean.class) { @Override - public BooleanMultiProperty createWith(Map valuesById) { + public BooleanMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); - return new BooleanMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - booleanValuesIn(defaultValueIn(valuesById), delimiter), 0f); + return new BooleanMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER), + 0f); } }; + /** + * Constructor using an array of defaults. + * + * @param theName Name + * @param theDescription Description + * @param defaultValues List of defaults + * @param theUIOrder UI order + */ public BooleanMultiProperty(String theName, String theDescription, Boolean[] defaultValues, float theUIOrder) { - super(theName, theDescription, defaultValues, theUIOrder); + this(theName, theDescription, Arrays.asList(defaultValues), theUIOrder); } + /** + * Constructor using a list of defaults. + * + * @param theName Name + * @param theDescription Description + * @param defaultValues List of defaults + * @param theUIOrder UI order + */ public BooleanMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder) { super(theName, theDescription, defaultValues, theUIOrder); } + @Override protected Boolean createFrom(String toParse) { - return Boolean.valueOf(toParse); + return BOOLEAN_PARSER.valueOf(toParse); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 88d796a7a0..1e42c2b739 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.BOOLEAN_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -20,12 +23,15 @@ public class BooleanProperty extends AbstractSingleValueProperty { Boolean.class) { @Override - public BooleanProperty createWith(Map valuesById) { - return new BooleanProperty(nameIn(valuesById), descriptionIn(valuesById), - Boolean.valueOf(defaultValueIn(valuesById)), 0f); + public BooleanProperty createWith(Map valuesById) { + return new BooleanProperty(nameIn(valuesById), + descriptionIn(valuesById), + BOOLEAN_PARSER.valueOf(defaultValueIn(valuesById)), + 0f); } }; + /** * Constructor for BooleanProperty limited to a single value. * @@ -38,6 +44,7 @@ public class BooleanProperty extends AbstractSingleValueProperty { super(theName, theDescription, defaultValue, theUIOrder); } + /** * Constructor for BooleanProperty limited to a single value. Converts * default argument string into a boolean. @@ -57,9 +64,9 @@ public class BooleanProperty extends AbstractSingleValueProperty { return Boolean.class; } + @Override public Boolean createFrom(String propertyString) throws IllegalArgumentException { - return Boolean.valueOf(propertyString); + return BOOLEAN_PARSER.valueOf(propertyString); } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index ba26edea33..2d2509e01f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -5,29 +5,32 @@ package net.sourceforge.pmd.lang.rule.properties; 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory.PrimitiveExtractor; +import net.sourceforge.pmd.lang.rule.properties.factories.ValueParser; import net.sourceforge.pmd.util.StringUtil; /** - * Defines a property type that supports multiple Character values. + * Multi-valued character property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class CharacterMultiProperty extends AbstractMultiValueProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Character.class) { - @Override - public CharacterMultiProperty createWith(Map valuesById) { + public CharacterMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); return new CharacterMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - parsePrimitives(defaultValueIn(valuesById), delimiter, PrimitiveExtractor.CHARACTER_EXTRACTOR), + parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER), 0.0f, delimiter); } @@ -35,41 +38,39 @@ public class CharacterMultiProperty extends AbstractMultiValueProperty theDefaults, float theUIOrder, + /** + * Constructor using a list of defaults. + * + * @param theName Name + * @param theDescription Description + * @param defaultValues List of defaults + * @param theUIOrder UI order + * @param delimiter The delimiter to use + * + * @throws IllegalArgumentException if the delimiter is in the default values + */ + public CharacterMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder, char delimiter) { - super(theName, theDescription, theDefaults, theUIOrder, delimiter); + super(theName, theDescription, defaultValues, theUIOrder, delimiter); - if (theDefaults != null) { - for (Character c : theDefaults) { + if (defaultValues != null) { + for (Character c : defaultValues) { if (c == delimiter) { throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); } @@ -78,11 +79,18 @@ public class CharacterMultiProperty extends AbstractMultiValueProperty type() { return Character.class; } + @Override public List valueFrom(String valueString) throws IllegalArgumentException { String[] values = StringUtil.substringsOf(valueString, multiValueDelimiter()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 71f711ac07..9b7943ab1a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.CHARACTER_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -19,15 +22,15 @@ public class CharacterProperty extends AbstractSingleValueProperty { public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Character.class) { @Override - public CharacterProperty createWith(Map valuesById) { + public CharacterProperty createWith(Map valuesById) { return new CharacterProperty(nameIn(valuesById), descriptionIn(valuesById), - defaultValueIn(valuesById) == null ? null - : defaultValueIn(valuesById).charAt(0), + CHARACTER_PARSER.valueOf(defaultValueIn(valuesById)), 0f); } }; + /** * Constructor for CharacterProperty. * @@ -40,6 +43,7 @@ public class CharacterProperty extends AbstractSingleValueProperty { super(theName, theDescription, theDefault, theUIOrder); } + /** * Constructor for CharacterProperty. * @@ -65,12 +69,10 @@ public class CharacterProperty extends AbstractSingleValueProperty { * @throws IllegalArgumentException if the String doesn't have length 1 */ public static Character charFrom(String charStr) { - if (charStr == null || charStr.length() != 1) { - throw new IllegalArgumentException("missing/invalid character value"); - } - return charStr.charAt(0); + return CHARACTER_PARSER.valueOf(charStr); } + @Override public Class type() { return Character.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index b16cdfb637..6619933b01 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -5,70 +5,84 @@ 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.factories.ValueParser.DOUBLE_PARSER; 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * Defines a property type that supports multiple double-type property values - * within an upper and lower boundary. + * Multi-valued double property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class DoubleMultiProperty extends AbstractMultiNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public DoubleMultiProperty createWith(Map valuesById) { + public DoubleMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - Double[] defaultValues = doublesIn(numericDefaultValueIn(valuesById), delimiter); - return new DoubleMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Double.parseDouble(minMax[0]), - Double.parseDouble(minMax[1]), defaultValues, 0f); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER); + return new DoubleMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + DOUBLE_PARSER.valueOf(minMax[0]), + DOUBLE_PARSER.valueOf(minMax[1]), + defaultValues, + 0f); } }; + /** - * Constructor for DoubleProperty. + * Constructor using an array of defaults. * - * @param theName String - * @param theDescription String - * @param min Double - * @param max Double - * @param defaultValues Double[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues Array of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, Double[] defaultValues, - float theUIOrder) { + public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, + Double[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); } + /** - * Constructor for DoubleProperty. + * Constructor using a list of defaults. * - * @param theName String - * @param theDescription String - * @param min Double - * @param max Double - * @param defaultValues Double[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues List of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, List defaultValues, - float theUIOrder) { + public DoubleMultiProperty(String theName, String theDescription, Double min, Double max, + List defaultValues, float theUIOrder) { super(theName, theDescription, min, max, defaultValues, theUIOrder); } + @Override public Class type() { return Double.class; } + @Override protected Double createFrom(String value) { return Double.valueOf(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index dd0cb3b476..7f890b726b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -28,6 +28,7 @@ public class DoubleProperty extends AbstractNumericProperty { } }; + /** * Constructor for DoubleProperty. * @@ -45,6 +46,7 @@ public class DoubleProperty extends AbstractNumericProperty { super(theName, theDescription, min, max, theDefault, theUIOrder); } + /** * Constructor for DoubleProperty. * @@ -62,6 +64,7 @@ public class DoubleProperty extends AbstractNumericProperty { this(theName, theDescription, doubleFrom(minStr), doubleFrom(maxStr), doubleFrom(defaultStr), theUIOrder); } + /** * Parses a String into a Double. * @@ -73,11 +76,13 @@ public class DoubleProperty extends AbstractNumericProperty { return Double.valueOf(numberString); } + @Override public Class type() { return Double.class; } + @Override protected Double createFrom(String value) { return doubleFrom(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index 8f2e7cb031..f2ebc2bc42 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -5,52 +5,54 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.CollectionUtil; /** - * Defines a datatype with a set of preset values of any type as held within a - * pair of maps. While the values are not serialized out, the labels are and - * serve as keys to obtain the values. The choices() method provides the ordered - * selections to be used in an editor widget. + * Multi-valued property which can take only a fixed set of values of any type, then selected via String labels. The + * choices method returns the set of mappings between the labels and their values. * - * @param + * @param The type of the values * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Enumeration.class) { - @Override - public EnumeratedMultiProperty createWith(Map valuesById) { - - return new EnumeratedMultiProperty<>(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), - choicesIn(valuesById), indicesIn(valuesById), 0f); + public EnumeratedMultiProperty createWith(Map valuesById) { + return new EnumeratedMultiProperty<>(nameIn(valuesById), + descriptionIn(valuesById), + labelsIn(valuesById), + choicesIn(valuesById), + indicesIn(valuesById), + 0f); } }; - - protected Map choicesByLabel; - protected Map labelsByChoice; + private Map choicesByLabel; + private Map labelsByChoice; /** - * Constructor for EnumeratedProperty. + * Constructor using arrays to define the label-value mappings. The correct construction of the property depends + * on the correct ordering of the arrays. * - * @param theName String - * @param theDescription String - * @param theLabels String[] - * @param theChoices E[] - * @param choiceIndices int[] - * @param theUIOrder float - * - * @throws IllegalArgumentException + * @param theName Name + * @param theDescription Description + * @param theLabels Labels of the choices + * @param theChoices Values that can be chosen + * @param choiceIndices The indices of the default values. + * @param theUIOrder UI order */ public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, float theUIOrder) { @@ -59,15 +61,48 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); } + + /** + * 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 choices, + List defaultValues, float theUIOrder) { + super(theName, theDescription, defaultValues, theUIOrder); + + checkDefaults(defaultValues, choices); + + choicesByLabel = Collections.unmodifiableMap(choices); + labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); + } + + private static List selection(int[] choiceIndices, E[] theChoices) { List selected = new ArrayList<>(); for (int i : choiceIndices) { + if (i < 0 || i > theChoices.length) { + throw new IllegalArgumentException("Default value index is out of bounds: " + i); + } selected.add(theChoices[i]); } return selected; } + private static void checkDefaults(List defaults, Map choices) { + for (E elt : defaults) { + if (!choices.containsValue(elt)) { + throw new IllegalArgumentException("Invalid default value: no mapping to this value"); + } + } + } + + @Override public Class type() { return Enumeration.class; @@ -89,21 +124,25 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { return null; } + private E choiceFrom(String label) { E result = choicesByLabel.get(label); - if (result != null) { - return result; + if (result == null) { + throw new IllegalArgumentException(label); } - throw new IllegalArgumentException(label); + return result; } + @Override protected E createFrom(String toParse) { return choiceFrom(toParse); } + @Override public String asString(E item) { return labelsByChoice.get(item); } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index ecc662a615..165bcb801f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -4,12 +4,14 @@ package net.sourceforge.pmd.lang.rule.properties; +import java.util.Collections; import java.util.Enumeration; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.CollectionUtil; @@ -25,35 +27,36 @@ import net.sourceforge.pmd.util.CollectionUtil; */ public class EnumeratedProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Enumeration.class) { @Override - public EnumeratedProperty createWith(Map valuesById) { - return new EnumeratedProperty<>(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById), - choicesIn(valuesById), indexIn(valuesById), 0f); + public EnumeratedProperty createWith(Map valuesById) { + return new EnumeratedProperty<>(nameIn(valuesById), + descriptionIn(valuesById), + labelsIn(valuesById), // those are not implemented + choicesIn(valuesById), // ditto + indexIn(valuesById), // ditto + 0f); } }; - protected Map choicesByLabel; - protected Map labelsByChoice; + private Map choicesByLabel; + private Map labelsByChoice; + - /** - * Constructor for EnumeratedProperty. - * - * @param theName String - * @param theDescription String - * @param theLabels String[] - * @param theChoices E[] - * @param defaultIndex int - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int defaultIndex, float theUIOrder) { - super(theName, theDescription, theChoices[defaultIndex], theUIOrder); + this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), theChoices[defaultIndex], + theUIOrder); + } - choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices); + + public EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, + E defaultValue, float theUIOrder) { + super(theName, theDescription, defaultValue, theUIOrder); + + choicesByLabel = Collections.unmodifiableMap(labelsToChoices); labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); } @@ -89,11 +92,13 @@ public class EnumeratedProperty extends AbstractSingleValueProperty { return choiceFrom(value); } + @Override public String asString(E value) { return labelsByChoice.get(value); } + @Override public Set> choices() { return choicesByLabel.entrySet(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index 11abd8d418..955541af1a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -8,6 +8,7 @@ import java.io.File; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; @@ -19,7 +20,7 @@ public class FileProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(File.class) { @Override - public FileProperty createWith(Map valuesById) { + public FileProperty createWith(Map valuesById) { return new FileProperty(nameIn(valuesById), descriptionIn(valuesById), null, 0f); } }; @@ -29,11 +30,13 @@ public class FileProperty extends AbstractSingleValueProperty { super(theName, theDescription, theDefault, theUIOrder); } + @Override public Class type() { return File.class; } + @Override public File createFrom(String propertyString) { return StringUtil.isEmpty(propertyString) ? null : new File(propertyString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index fcc767fc82..d0ae958d26 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -5,65 +5,70 @@ 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.factories.ValueParser.FLOAT_PARSER; 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * Defines a property type that support float property values within an upper - * and lower boundary. + * Multi-valued float property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class FloatMultiProperty extends AbstractMultiNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public FloatMultiProperty createWith(Map valuesById) { + public FloatMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - Float[] defaultValues = floatsIn(numericDefaultValueIn(valuesById), delimiter); - return new FloatMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Float.parseFloat(minMax[0]), - Float.parseFloat(minMax[1]), defaultValues, 0f); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); + return new FloatMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + FLOAT_PARSER.valueOf(minMax[0]), + FLOAT_PARSER.valueOf(minMax[1]), + defaultValues, 0f); } }; + /** - * Constructor for FloatProperty that configures it to accept multiple - * values and any number of defaults. + * Constructor using an array of defaults. * - * @param theName String - * @param theDescription String - * @param min Float - * @param max Float - * @param defaultValues Float[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues Array of defaults + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public FloatMultiProperty(String theName, String theDescription, Float min, Float max, Float[] defaultValues, - float theUIOrder) { + public FloatMultiProperty(String theName, String theDescription, Float min, Float max, + Float[] defaultValues, float theUIOrder) { this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); } + /** - * Constructor for FloatProperty that configures it to accept multiple - * values and any number of defaults. + * Constructor using a list of defaults. * - * @param theName String - * @param theDescription String - * @param min Float - * @param max Float - * @param defaultValues Float[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues List of defaults + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public FloatMultiProperty(String theName, String theDescription, Float min, Float max, List defaultValues, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index f84c66f363..f0e6a4f7b1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -28,6 +28,7 @@ public class FloatProperty extends AbstractNumericProperty { } }; + /** * Constructor for FloatProperty that limits itself to a single value within * the specified limits. @@ -46,6 +47,7 @@ public class FloatProperty extends AbstractNumericProperty { super(theName, theDescription, Float.valueOf(min), Float.valueOf(max), Float.valueOf(theDefault), theUIOrder); } + /** * Constructor for FloatProperty that limits itself to a single value within * the specified limits. Converts string arguments into the Float values. @@ -64,6 +66,7 @@ public class FloatProperty extends AbstractNumericProperty { this(theName, theDescription, floatFrom(minStr), floatFrom(maxStr), floatFrom(defaultStr), theUIOrder); } + /** * Parses a String into a Float. * @@ -75,11 +78,13 @@ public class FloatProperty extends AbstractNumericProperty { return Float.valueOf(numberString); } + @Override public Class type() { return Float.class; } + @Override protected Float createFrom(String value) { return floatFrom(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 12ed81e0ca..77c86942ae 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -5,70 +5,76 @@ 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.factories.ValueParser.INTEGER_PARSER; 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * Defines a datatype that supports multiple Integer property values within an - * upper and lower boundary. + * Multi-valued integer property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class IntegerMultiProperty extends AbstractMultiNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public IntegerMultiProperty createWith(Map valuesById) { + public IntegerMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, PrimitiveExtractor - .INTEGER_EXTRACTOR); - return new IntegerMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Integer.parseInt(minMax[0]), - Integer.parseInt(minMax[1]), defaultValues, 0f); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); + return new IntegerMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + INTEGER_PARSER.valueOf(minMax[0]), + INTEGER_PARSER.valueOf(minMax[1]), + defaultValues, + 0f); } }; - /** - * Constructor for IntegerProperty. - * - * @param theName String - * @param theDescription String - * @param min Integer - * @param max Integer - * @param theDefaults Integer[] - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ - public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, Integer[] theDefaults, - float theUIOrder) { - - this(theName, theDescription, min, max, Arrays.asList(theDefaults), theUIOrder); - } /** - * Constructor for IntegerProperty. + * Constructor using an array of defaults. * - * @param theName String - * @param theDescription String - * @param min Integer - * @param max Integer - * @param theDefaults Integer[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues Array of defaults + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, - List theDefaults, float theUIOrder) { + Integer[] defaultValues, float theUIOrder) { + this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); + } - super(theName, theDescription, min, max, theDefaults, theUIOrder); + + /** + * Constructor using a list of defaults. + * + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues List of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + */ + public IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, + List defaultValues, float theUIOrder) { + + super(theName, theDescription, min, max, defaultValues, theUIOrder); } @@ -77,6 +83,7 @@ public class IntegerMultiProperty extends AbstractMultiNumericProperty return Integer.class; } + @Override protected Integer createFrom(String toParse) { return Integer.valueOf(toParse); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 209428235b..b36dc76381 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.INTEGER_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -21,16 +24,20 @@ public class IntegerProperty extends AbstractNumericProperty { = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public IntegerProperty createWith(Map valuesById) { + public IntegerProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); - return new IntegerProperty(nameIn(valuesById), descriptionIn(valuesById), Integer.valueOf(minMax[0]), - Integer.valueOf(minMax[1]), Integer.valueOf(numericDefaultValueIn(valuesById)), 0f); + return new IntegerProperty(nameIn(valuesById), + descriptionIn(valuesById), + INTEGER_PARSER.valueOf(minMax[0]), + INTEGER_PARSER.valueOf(minMax[1]), + INTEGER_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f); } }; + /** - * Constructor for IntegerProperty that limits itself to a single value - * within the specified limits. + * Constructor for IntegerProperty that limits itself to a single value within the specified limits. * * @param theName String * @param theDescription String @@ -41,29 +48,11 @@ public class IntegerProperty extends AbstractNumericProperty { * * @throws IllegalArgumentException */ - public IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, + public IntegerProperty(String theName, String theDescription, int min, int max, int theDefault, float theUIOrder) { super(theName, theDescription, min, max, theDefault, theUIOrder); } - /** - * Constructor for IntegerProperty that limits itself to a single value - * within the specified limits. Converts string arguments into the Float - * values. - * - * @param theName String - * @param theDescription String - * @param minStr String - * @param maxStr String - * @param defaultStr String - * @param theUIOrder UI order - * - * @throws IllegalArgumentException - */ - public IntegerProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, - float theUIOrder) { - this(theName, theDescription, intFrom(minStr), intFrom(maxStr), intFrom(defaultStr), theUIOrder); - } /** * Parses a String into an Integer. @@ -73,7 +62,7 @@ public class IntegerProperty extends AbstractNumericProperty { * @return Parsed Integer */ public static Integer intFrom(String numberString) { - return Integer.valueOf(numberString); + } @@ -82,8 +71,9 @@ public class IntegerProperty extends AbstractNumericProperty { return Integer.class; } + @Override protected Integer createFrom(String value) { - return intFrom(value); + return INTEGER_PARSER.valueOf(value); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 2cc1c7eba6..ff73afdf46 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -5,74 +5,83 @@ 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.factories.ValueParser.LONG_PARSER; 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * Defines a datatype that supports multiple Long property values within an - * upper and lower boundary. + * Multi-valued long property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class LongMultiProperty extends AbstractMultiNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public LongMultiProperty createWith(Map valuesById) { + public LongMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - Long[] defaultValues = longsIn(defaultValueIn(valuesById), delimiter); - return new LongMultiProperty(nameIn(valuesById), descriptionIn(valuesById), Long.parseLong(minMax[0]), - Long.parseLong(minMax[1]), defaultValues, 0f); + List defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); + return new LongMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + LONG_PARSER.valueOf(minMax[0]), + LONG_PARSER.valueOf(minMax[1]), + defaultValues, 0f); } }; - /** - * Constructor for LongProperty. - * - * @param theName String - * @param theDescription String - * @param min Long - * @param max Long - * @param theDefaults Long[] - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ - public LongMultiProperty(String theName, String theDescription, Long min, Long max, Long[] theDefaults, - float theUIOrder) { - super(theName, theDescription, min, max, Arrays.asList(theDefaults), theUIOrder); - } /** - * Constructor for LongProperty. + * Constructor using an array of defaults. * - * @param theName String - * @param theDescription String - * @param min Long - * @param max Long - * @param theDefaults Long[] - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues Array of defaults + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public LongMultiProperty(String theName, String theDescription, Long min, Long max, List theDefaults, - float theUIOrder) { - super(theName, theDescription, min, max, theDefaults, theUIOrder); + public LongMultiProperty(String theName, String theDescription, Long min, Long max, + Long[] defaultValues, float theUIOrder) { + super(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); } + + /** + * Constructor using a list of defaults. + * + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param defaultValues List of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + */ + public LongMultiProperty(String theName, String theDescription, Long min, Long max, + List defaultValues, float theUIOrder) { + super(theName, theDescription, min, max, defaultValues, theUIOrder); + } + + @Override public Class type() { return Long.class; } + @Override protected Long createFrom(String value) { return Long.valueOf(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index fe7dc5689e..ae02b6f042 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -28,6 +28,7 @@ public class LongProperty extends AbstractNumericProperty { } }; + /** * Constructor for LongProperty. * @@ -44,6 +45,7 @@ public class LongProperty extends AbstractNumericProperty { super(theName, theDescription, min, max, theDefault, theUIOrder); } + /** * Constructor for LongProperty that limits itself to a single value within * the specified limits. Converts string arguments into the Long values. @@ -62,6 +64,7 @@ public class LongProperty extends AbstractNumericProperty { this(theName, theDescription, longFrom(minStr), longFrom(maxStr), longFrom(defaultStr), theUIOrder); } + /** * Parses a String into a Long. * @@ -79,6 +82,7 @@ public class LongProperty extends AbstractNumericProperty { return Long.class; } + @Override protected Long createFrom(String toParse) { return Long.valueOf(toParse); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index c27ac8535d..bce66aeff8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -28,7 +28,6 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override public MethodMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); @@ -37,6 +36,7 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { } }; + /** * Constructor for MethodProperty. * @@ -53,11 +53,13 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); } + public MethodMultiProperty(String theName, String theDescription, Method[] theDefaults, String[] legalPackageNames, float theUIOrder) { this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); } + /** * Constructor for MethodProperty. * @@ -74,6 +76,7 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { super(theName, theDescription, methodsFrom(methodDefaults), legalPackageNames, theUIOrder); } + public MethodMultiProperty(String theName, String theDescription, String methodDefaults, Map otherParams, float theUIOrder) { this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); @@ -97,6 +100,7 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { return value == null ? "" : MethodProperty.asStringFor(value); } + @Override protected Method createFrom(String toParse) { return MethodProperty.methodFrom(toParse, MethodProperty.CLASS_METHOD_DELIMITER, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index ae158b4056..2b0338ae23 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -41,6 +41,7 @@ public class MethodProperty extends AbstractPackagedProperty { private static final String ARRAY_FLAG = "[]"; private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); + public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames, float theUIOrder) { super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); @@ -52,16 +53,19 @@ public class MethodProperty extends AbstractPackagedProperty { super(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder); } + public MethodProperty(String theName, String theDescription, String defaultMethodStr, Map otherParams, float theUIOrder) { this(theName, theDescription, methodFrom(defaultMethodStr), packageNamesIn(otherParams), theUIOrder); } + private static String shortestNameFor(Class cls) { String compactName = TYPE_SHORTCUTS.get(cls); return compactName == null ? cls.getName() : compactName; } + /** * Return the value of `method' as a string that can be easily recognized * and parsed when we see it again. @@ -76,6 +80,7 @@ public class MethodProperty extends AbstractPackagedProperty { return sb.toString(); } + private static void serializedTypeIdOn(Class type, StringBuilder sb) { Class arrayType = type.getComponentType(); @@ -86,6 +91,7 @@ public class MethodProperty extends AbstractPackagedProperty { sb.append(shortestNameFor(arrayType)).append(ARRAY_FLAG); } + /** * Serializes the method signature onto the specified buffer. * @@ -116,6 +122,7 @@ public class MethodProperty extends AbstractPackagedProperty { sb.append(METHOD_GROUP_DELIMITERS[1]); } + private static Class typeFor(String typeName) { Class type; @@ -140,6 +147,7 @@ public class MethodProperty extends AbstractPackagedProperty { } } + /** * Returns the method specified within the string argument after parsing out * its source class and any optional arguments. Callers need to specify the @@ -214,6 +222,7 @@ public class MethodProperty extends AbstractPackagedProperty { return ClassUtil.methodFor(type, methodName, argTypes); } + /** * Parses a String into a Method. * @@ -225,26 +234,31 @@ public class MethodProperty extends AbstractPackagedProperty { return methodFrom(methodStr, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER); } + @Override protected String asString(Method value) { return value == null ? "" : asStringFor(value); } + @Override protected String packageNameOf(Method method) { return method == null ? null : method.getDeclaringClass().getName() + '.' + method.getName(); } + @Override protected String itemTypeName() { return "method"; } + @Override public Class type() { return Method.class; } + @Override public Method createFrom(String valueString) throws IllegalArgumentException { return methodFrom(valueString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index b87b972b9d..b7c7244a5b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.INTEGER_PARSER; + import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; @@ -13,6 +15,7 @@ public class PropertyDescriptorFactory { private PropertyDescriptorFactory() { } + /** * Returns the String type of the PropertyDescriptor for use in XML * serialization. If the value is null the type cannot be @@ -39,12 +42,15 @@ public class PropertyDescriptorFactory { return typeName; } + + // TODO:cf Deprecate? PropertyDescriptors can already be made from a map public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, String delimiter, String min, String max, String value) { return new PropertyDescriptorWrapper<>( createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); } + private static PropertyDescriptor createRawPropertyDescriptor(String name, String description, String type, String delimiter, String min, String max, String value) { if ("Boolean".equals(type)) { @@ -77,7 +83,8 @@ public class PropertyDescriptorFactory { property.valueFrom(value), 0.0f); } else if ("Integer".equals(type)) { checkMinMax(name, type, min, max); - return new IntegerProperty(name, description, min, max, value, 0.0f); + return new IntegerProperty(name, description, INTEGER_PARSER.valueOf(min), INTEGER_PARSER.valueOf(max), + INTEGER_PARSER.valueOf(value), 0.0f); } else if ("List".equals(type)) { checkMinMax(name, type, min, max); IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, @@ -115,6 +122,7 @@ public class PropertyDescriptorFactory { } } + private static void checkDelimiter(String name, String type, String delimiter) { if (delimiter == null || delimiter.length() == 0) { throw new IllegalArgumentException( @@ -122,6 +130,7 @@ public class PropertyDescriptorFactory { } } + private static void checkMinMax(String name, String type, String min, String max) { if (StringUtil.isEmpty(min)) { throw new IllegalArgumentException( diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index 025ea02406..28ec56169b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -22,8 +22,10 @@ import net.sourceforge.pmd.Rule; * @param The type of the underlying PropertyDescriptor. */ public class PropertyDescriptorWrapper implements PropertyDescriptor { + private final PropertyDescriptor propertyDescriptor; + public PropertyDescriptorWrapper(PropertyDescriptor propertyDescriptor) { if (propertyDescriptor == null) { throw new IllegalArgumentException("PropertyDescriptor cannot be null."); @@ -31,70 +33,84 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { this.propertyDescriptor = propertyDescriptor; } + public PropertyDescriptor getPropertyDescriptor() { return propertyDescriptor; } + @Override public String asDelimitedString(T value) { return propertyDescriptor.asDelimitedString(value); } + @Override public Set> choices() { return propertyDescriptor.choices(); } + @Override public int compareTo(PropertyDescriptor o) { return propertyDescriptor.compareTo(o); } + @Override public T defaultValue() { return propertyDescriptor.defaultValue(); } + @Override public String description() { return propertyDescriptor.description(); } + @Override public String errorFor(T value) { return propertyDescriptor.errorFor(value); } + @Override public boolean isMultiValue() { return propertyDescriptor.isMultiValue(); } + @Override public boolean isRequired() { return propertyDescriptor.isRequired(); } + @Override public char multiValueDelimiter() { return propertyDescriptor.multiValueDelimiter(); } + @Override public String name() { return propertyDescriptor.name(); } + @Override public int preferredRowCount() { return propertyDescriptor.preferredRowCount(); } + @Override public String propertyErrorFor(Rule rule) { return propertyDescriptor.propertyErrorFor(rule); } + @SuppressWarnings("unchecked") @Override public Class type() { @@ -113,21 +129,25 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { return result; } + @Override public float uiOrder() { return propertyDescriptor.uiOrder(); } + @Override public T valueFrom(String propertyString) throws IllegalArgumentException { return propertyDescriptor.valueFrom(propertyString); } + @Override public Map attributeValuesById() { return propertyDescriptor.attributeValuesById(); } + @Override public boolean equals(Object obj) { if (obj instanceof PropertyDescriptorWrapper) { @@ -136,11 +156,13 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { return this.getPropertyDescriptor().equals(obj); } + @Override public int hashCode() { return this.getPropertyDescriptor().hashCode(); } + @Override public String toString() { return "wrapped:" + propertyDescriptor.toString(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 10db240a2d..eb1e0f5c96 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -4,12 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; - 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.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; @@ -18,54 +18,60 @@ import net.sourceforge.pmd.util.StringUtil; * strings must be filtered by the delimiter character. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class StringMultiProperty extends AbstractMultiValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(String - .class) { - + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY + = new BasicPropertyDescriptorFactory>(String.class) { @Override - public StringMultiProperty createWith(Map valuesById) { + public StringMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); - return new StringMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), 0.0f, delimiter); + return new StringMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), + 0.0f, + delimiter); } }; + /** - * Constructor for StringProperty. + * Constructor using an array of defaults. * - * @param theName String - * @param theDescription String - * @param theDefaults String[] - * @param theUIOrder float - * @param delimiter String + * @param theName Name + * @param theDescription Description + * @param defaultValues Array of defaults + * @param theUIOrder UI order + * @param delimiter The delimiter to use * * @throws IllegalArgumentException if a default value contains the delimiter * @throws NullPointerException if the defaults array is null */ - public StringMultiProperty(String theName, String theDescription, String[] theDefaults, float theUIOrder, + public StringMultiProperty(String theName, String theDescription, String[] defaultValues, float theUIOrder, char delimiter) { - this(theName, theDescription, Arrays.asList(theDefaults), theUIOrder, delimiter); + this(theName, theDescription, Arrays.asList(defaultValues), theUIOrder, delimiter); } + /** - * Constructor for StringProperty. + * Constructor using a list of defaults. * - * @param theName String - * @param theDescription String - * @param theDefaults String[] - * @param theUIOrder float - * @param delimiter String + * @param theName Name + * @param theDescription Description + * @param defaultValues List of defaults + * @param theUIOrder UI order + * @param delimiter The delimiter to useg * * @throws IllegalArgumentException if a default value contains the delimiter * @throws NullPointerException if the defaults array is null */ - public StringMultiProperty(String theName, String theDescription, List theDefaults, float theUIOrder, + public StringMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder, char delimiter) { - super(theName, theDescription, theDefaults, theUIOrder, delimiter); + super(theName, theDescription, defaultValues, theUIOrder, delimiter); - checkDefaults(theDefaults, delimiter); + checkDefaults(defaultValues, delimiter); } @@ -90,11 +96,13 @@ public class StringMultiProperty extends AbstractMultiValueProperty { } } + @Override public Class type() { return String.class; } + @Override public List valueFrom(String valueString) { return Arrays.asList(StringUtil.substringsOf(valueString, multiValueDelimiter())); @@ -134,6 +142,7 @@ public class StringMultiProperty extends AbstractMultiValueProperty { return null; } + @Override protected String createFrom(String toParse) { return toParse; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index b1dd360b26..20d8ecae72 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -16,17 +17,16 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class StringProperty extends AbstractSingleValueProperty { - /** - * Factory. - */ + /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { @Override - public StringProperty createWith(Map valuesById) { + public StringProperty createWith(Map valuesById) { return new StringProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), 0f); } }; + /** * Constructor for StringProperty. * @@ -39,11 +39,13 @@ public class StringProperty extends AbstractSingleValueProperty { super(theName, theDescription, theDefaultValue, theUIOrder); } + @Override public Class type() { return String.class; } + @Override public String createFrom(String valueString) { return valueString; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 719afb612c..c18ba128d2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; @@ -25,15 +26,18 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public TypeMultiProperty createWith(Map valuesById) { + public TypeMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); - return new TypeMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + return new TypeMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById), + legalPackageNamesIn(valuesById, delimiter), + 0f); } }; + /** * Constructor for TypeProperty. * @@ -51,6 +55,7 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { } + /** * Constructor for TypeProperty. * @@ -67,6 +72,7 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); } + /** * Constructor for TypeProperty. * @@ -84,10 +90,6 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { } - public TypeMultiProperty(String theName, String theDescription, String theTypeDefaults, - Map otherParams, float theUIOrder) { - this(theName, theDescription, typesFrom(theTypeDefaults), packageNamesIn(otherParams), theUIOrder); - } /** * Returns a list of Class objects parsed from the input string. @@ -96,7 +98,7 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { * * @return A list of class objects */ - public static List typesFrom(String classesStr) { + private static List typesFrom(String classesStr) { String[] values = StringUtil.substringsOf(classesStr, DELIMITER); List classes = new ArrayList<>(values.length); @@ -106,31 +108,37 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { return classes; } + @Override protected String packageNameOf(Class item) { return ((Class) item).getName(); } + @Override public Class type() { return Class.class; } + @Override protected String itemTypeName() { return "type"; } + @Override public String asString(Class value) { return value == null ? "" : value.getName(); } + @Override protected Class createFrom(String toParse) { throw new UnsupportedOperationException(); // not used } + @Override public List valueFrom(String valueString) { return typesFrom(valueString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index 1f42e13bd4..e59fbbde3a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -32,6 +32,7 @@ public class TypeProperty extends AbstractPackagedProperty { } }; + /** * Constructor for TypeProperty. * @@ -48,6 +49,7 @@ public class TypeProperty extends AbstractPackagedProperty { super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); } + /** * Constructor for TypeProperty using a string as default value. * @@ -64,6 +66,7 @@ public class TypeProperty extends AbstractPackagedProperty { this(theName, theDescription, classFrom(defaultTypeStr), legalPackageNames, theUIOrder); } + public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, float theUIOrder) { this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); @@ -87,26 +90,31 @@ public class TypeProperty extends AbstractPackagedProperty { } } + @Override protected String packageNameOf(Class item) { return item.getName(); } + @Override public Class type() { return Class.class; } + @Override protected String itemTypeName() { return "type"; } + @Override protected String asString(Class value) { return value == null ? "" : value.getName(); } + @Override public Class createFrom(String valueString) { return classFrom(valueString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index d17f183ee0..eb50db9175 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -4,23 +4,23 @@ package net.sourceforge.pmd.lang.rule.properties.factories; -import static net.sourceforge.pmd.PropertyDescriptorFields.DEFAULT_VALUE; -import static net.sourceforge.pmd.PropertyDescriptorFields.DELIMITER; -import static net.sourceforge.pmd.PropertyDescriptorFields.DESC; -import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES; -import static net.sourceforge.pmd.PropertyDescriptorFields.MAX; -import static net.sourceforge.pmd.PropertyDescriptorFields.MIN; -import static net.sourceforge.pmd.PropertyDescriptorFields.NAME; +import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; +import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; +import static net.sourceforge.pmd.PropertyDescriptorField.DESC; +import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES; +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 java.util.regex.Pattern; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.AbstractProperty; import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; @@ -32,36 +32,62 @@ import net.sourceforge.pmd.util.StringUtil; */ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { - protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom( - new String[] {NAME, DESC, DEFAULT_VALUE, DELIMITER}, new Boolean[] {true, true, true, false}); + protected static final Map CORE_FIELD_TYPES_BY_KEY + = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESC, DEFAULT_VALUE, DELIMITER}, new Boolean[] {true, true, true, false}); private final Class valueType; - private final Map fieldTypesByKey; + private final Map fieldTypesByKey; + public BasicPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY); } - public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { + + public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; - Map temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); + Map temp = new HashMap<>( + CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); temp.putAll(CORE_FIELD_TYPES_BY_KEY); temp.putAll(additionalFieldTypesByKey); fieldTypesByKey = Collections.unmodifiableMap(temp); } - protected static String minValueIn(Map valuesById) { + + private static String minValueIn(Map valuesById) { return valuesById.get(MIN); } - protected static String maxValueIn(Map valuesById) { + + private static String maxValueIn(Map valuesById) { return valuesById.get(MAX); } + + /** + * Parses a string into a list of values of type {@literal }. + * + * @param toParse The string to parse + * @param delimiter The delimiter to use + * @param extractor The function mapping a string to an instance of {@code } + * @param The type of the values to parse + * + * @return A list of values + */ + protected static List parsePrimitives(String toParse, char delimiter, ValueParser extractor) { + String[] values = StringUtil.substringsOf(toParse, delimiter); + List result = new ArrayList<>(); + for (String s : values) { + result.add(extractor.valueOf(s)); + } + return result; + } + + protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) { String[] values = StringUtil.substringsOf(booleanString, delimiter); @@ -72,16 +98,6 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return result; } - // TODO change return type to List someday - @SuppressWarnings("unckecked") - protected static List parsePrimitives(String toParse, char delimiter, PrimitiveExtractor extractor) { - String[] values = StringUtil.substringsOf(toParse, delimiter); - List result = new ArrayList<>(); - for (String s : values) { - result.add(extractor.valueOf(s)); - } - return result; - } protected static Long[] longsIn(String numberString, char delimiter) { String[] values = StringUtil.substringsOf(numberString, delimiter); @@ -97,6 +113,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return longs.toArray(new Long[longs.size()]); } + protected static Float[] floatsIn(String numberString, char delimiter) { String[] values = StringUtil.substringsOf(numberString, delimiter); List floats = new ArrayList<>(values.length); @@ -111,6 +128,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return floats.toArray(new Float[floats.size()]); } + protected static Double[] doublesIn(String numberString, char delimiter) { String[] values = StringUtil.substringsOf(numberString, delimiter); List doubles = new ArrayList<>(values.length); @@ -125,15 +143,18 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return doubles.toArray(new Double[doubles.size()]); } - protected static String[] labelsIn(Map valuesById) { + + protected static String[] labelsIn(Map valuesById) { return null; // TODO } - protected static Object[] choicesIn(Map valuesById) { + + protected static Object[] choicesIn(Map valuesById) { return null; // TODO } - protected static int indexIn(Map valuesById) { + + protected static int indexIn(Map valuesById) { return 0; // TODO } @@ -153,15 +174,18 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact // return items.toArray(builder.newArray(items.size())); // } - protected static int[] indicesIn(Map valuesById) { + + protected static int[] indicesIn(Map valuesById) { return null; // TODO } - protected static char delimiterIn(Map valuesById) { + + protected static char delimiterIn(Map valuesById) { return delimiterIn(valuesById, AbstractProperty.DEFAULT_DELIMITER); } - protected static char delimiterIn(Map valuesById, char defaultDelimiter) { + + protected static char delimiterIn(Map valuesById, char defaultDelimiter) { String characterStr = ""; if (valuesById.containsKey(DELIMITER)) { characterStr = valuesById.get(DELIMITER).trim(); @@ -172,7 +196,8 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return characterStr.charAt(0); } - protected static String[] minMaxFrom(Map valuesById) { + + protected static String[] minMaxFrom(Map valuesById) { String min = minValueIn(valuesById); String max = maxValueIn(valuesById); if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) { @@ -181,7 +206,8 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return new String[] {min, max}; } - protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { + + protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { String names = valuesById.get(LEGAL_PACKAGES); if (StringUtil.isEmpty(names)) { return null; @@ -189,8 +215,11 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return StringUtil.substringsOf(names, delimiter); } - public static Map expectedFieldTypesWith(String[] otherKeys, Boolean[] otherValues) { - Map largerMap = new HashMap<>(otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size()); + + public static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, Boolean[] + otherValues) { + Map largerMap = new HashMap<>( + otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size()); largerMap.putAll(CORE_FIELD_TYPES_BY_KEY); for (int i = 0; i < otherKeys.length; i++) { largerMap.put(otherKeys[i], otherValues[i]); @@ -198,95 +227,47 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return largerMap; } + @Override public Class valueType() { return valueType; } + @Override - public PropertyDescriptor createWith(Map valuesById) { + public PropertyDescriptor createWith(Map valuesById) { throw new RuntimeException("Unimplemented createWith() method in subclass"); } + @Override - public Map expectedFields() { + public Map expectedFields() { return fieldTypesByKey; } - protected String nameIn(Map valuesById) { + + protected String nameIn(Map valuesById) { return valuesById.get(NAME); } - protected String descriptionIn(Map valuesById) { + + protected String descriptionIn(Map valuesById) { return valuesById.get(DESC); } - protected String defaultValueIn(Map valuesById) { + + protected String defaultValueIn(Map valuesById) { return valuesById.get(DEFAULT_VALUE); } - protected String numericDefaultValueIn(Map valuesById) { + + protected String numericDefaultValueIn(Map valuesById) { String number = defaultValueIn(valuesById); return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 // reasonable if // undefined? } - /** - * Extracts a primitive from a string - * - * @param - */ - // FUTURE @FunctionalInterface - public interface PrimitiveExtractor { - /** Extracts characters. */ - PrimitiveExtractor CHARACTER_EXTRACTOR = new PrimitiveExtractor() { - @Override - public Character valueOf(String value) { - if (value.length() != 1) { - throw new IllegalArgumentException("missing/ambiguous character value"); - } - return value.charAt(0); - } - }; - - // FUTURE Integer::valueOf - /** Extracts integers. */ - PrimitiveExtractor INTEGER_EXTRACTOR = new PrimitiveExtractor() { - @Override - public Integer valueOf(String value) { - return Integer.valueOf(value); - } - }; - - // FUTURE Boolean::valueOf - /** Extracts booleans. */ - PrimitiveExtractor BOOLEAN_EXTRACTOR = new PrimitiveExtractor() { - @Override - public Boolean valueOf(String value) { - return Boolean.valueOf(value); - } - }; - - /** Extracts characters. */ - PrimitiveExtractor FLOAT_EXTRACTOR = new PrimitiveExtractor() { - @Override - public Float valueOf(String value) { - return Float.valueOf(value); - } - }; - - /** - * Extracts a primitive from a string. - * - * @param value The string to parse - * - * @return The primitive found - */ - U valueOf(String value); - - } - // protected static Map // factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) { // Map factoryMap = new HashMap> DESCRIPTOR_FACTORIES_BY_TYPE; + static { Map> temp = new HashMap<>(18); @@ -81,12 +81,15 @@ public class PropertyDescriptorUtil { DESCRIPTOR_FACTORIES_BY_TYPE = Collections.unmodifiableMap(temp); } + private PropertyDescriptorUtil() { } + public static PropertyDescriptorFactory factoryFor(String typeId) { return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId); } + public static String typeIdFor(Class valueType) { // a reverse lookup, not very efficient but fine for now diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java new file mode 100644 index 0000000000..bbb9733d44 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java @@ -0,0 +1,84 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.factories; + +/** + * Parses a value from a string. + * + * @param The type of the value to parse + */ +// FUTURE @FunctionalInterface +public interface ValueParser { + + + /** Extracts characters. */ + ValueParser CHARACTER_PARSER = new ValueParser() { + @Override + public Character valueOf(String value) { + if (value == null || value.length() != 1) { + throw new IllegalArgumentException("missing/ambiguous character value"); + } + return value.charAt(0); + } + }; + + // FUTURE Integer::valueOf + /** Extracts integers. */ + ValueParser INTEGER_PARSER = new ValueParser() { + @Override + public Integer valueOf(String value) { + return Integer.valueOf(value); + } + }; + + // FUTURE Boolean::valueOf + /** Extracts booleans. */ + ValueParser BOOLEAN_PARSER = new ValueParser() { + @Override + public Boolean valueOf(String value) { + return Boolean.valueOf(value); + } + }; + + // FUTURE Float::valueOf + /** Extracts floats. */ + ValueParser FLOAT_PARSER = new ValueParser() { + @Override + public Float valueOf(String value) { + return Float.valueOf(value); + } + }; + + // FUTURE Long::valueOf + /** Extracts longs. */ + ValueParser LONG_PARSER = new ValueParser() { + @Override + public Long valueOf(String value) { + return Long.valueOf(value); + } + }; + + // FUTURE Double::valueOf + /** Extracts doubles. */ + ValueParser DOUBLE_PARSER = new ValueParser() { + @Override + public Double valueOf(String value) { + return Double.valueOf(value); + } + }; + + + /** + * Extracts a primitive from a string. + * + * @param value The string to parse + * + * @return The primitive found + * + * @throws IllegalArgumentException if the value couldn't be parsed + */ + U valueOf(String value) throws IllegalArgumentException; + +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 814dbf341e..fb9be6dd86 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -19,7 +19,7 @@ import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; -import net.sourceforge.pmd.PropertyDescriptorFields; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; /** @@ -229,10 +229,10 @@ public abstract class AbstractPropertyDescriptorTester { private Map getPropertyDescriptorValues() { Map valuesById = new HashMap<>(); - valuesById.put(PropertyDescriptorFields.NAME, "test"); - valuesById.put(PropertyDescriptorFields.DESCRIPTION, "desc"); - valuesById.put(PropertyDescriptorFields.MIN, "0"); - valuesById.put(PropertyDescriptorFields.MAX, "10"); + valuesById.put(PropertyDescriptorField.NAME, "test"); + valuesById.put(PropertyDescriptorField.DESCRIPTION, "desc"); + valuesById.put(PropertyDescriptorField.MIN, "0"); + valuesById.put(PropertyDescriptorField.MAX, "10"); return valuesById; } @@ -263,7 +263,7 @@ public abstract class AbstractPropertyDescriptorTester { Map valuesById = getPropertyDescriptorValues(); String customDelimiter = "ä"; assertFalse(ALL_CHARS.contains(customDelimiter)); - valuesById.put(PropertyDescriptorFields.DELIMITER, customDelimiter); + valuesById.put(PropertyDescriptorField.DELIMITER, customDelimiter); PropertyDescriptor> prop = multiFactory.createWith(valuesById); List originalValue = createMultipleValues(MULTI_VALUE_COUNT); String asDelimitedString = prop.asDelimitedString(originalValue); From e1b12da1747de470397d4e02e01caaf4e2c81eed Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 27 Jun 2017 05:01:15 +0200 Subject: [PATCH 08/53] Some documentation --- .../AbstractMultiPackagedProperty.java | 2 +- .../AbstractMultiValueProperty.java | 18 +- .../properties/AbstractPackagedProperty.java | 37 +++-- .../rule/properties/AbstractProperty.java | 53 ++---- .../AbstractSingleValueProperty.java | 36 +++- .../rule/properties/BooleanMultiProperty.java | 20 +-- .../lang/rule/properties/BooleanProperty.java | 25 +-- .../properties/CharacterMultiProperty.java | 23 +-- .../rule/properties/CharacterProperty.java | 30 ++-- .../rule/properties/DoubleMultiProperty.java | 28 ++-- .../lang/rule/properties/DoubleProperty.java | 60 ++++--- .../properties/EnumeratedMultiProperty.java | 23 +-- .../rule/properties/EnumeratedProperty.java | 24 +-- .../lang/rule/properties/FileProperty.java | 2 + .../rule/properties/FloatMultiProperty.java | 26 +-- .../lang/rule/properties/FloatProperty.java | 63 +++---- .../rule/properties/IntegerMultiProperty.java | 4 +- .../lang/rule/properties/IntegerProperty.java | 41 +++-- .../rule/properties/LongMultiProperty.java | 26 +-- .../lang/rule/properties/LongProperty.java | 63 +++---- .../rule/properties/MethodMultiProperty.java | 19 ++- .../lang/rule/properties/MethodProperty.java | 155 +++++++++--------- .../properties/PropertyDescriptorWrapper.java | 13 +- .../rule/properties/StringMultiProperty.java | 56 +++---- .../lang/rule/properties/StringProperty.java | 15 +- .../rule/properties/TypeMultiProperty.java | 23 +-- .../lang/rule/properties/TypeProperty.java | 59 +++---- 27 files changed, 496 insertions(+), 448 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index a3ba48202e..ad1df51ac0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -56,7 +56,7 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu } - protected static String[] packageNamesIn(Map params) { + protected static String[] packageNamesIn(Map params) { // TODO return null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index a84ccb298f..cee9882bf2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -23,8 +23,15 @@ import net.sourceforge.pmd.Rule; */ public abstract class AbstractMultiValueProperty extends AbstractProperty> { + /** Default delimiter for multi-valued properties other than numeric ones. */ + static final char DEFAULT_DELIMITER = '|'; + + /** Default delimiter for numeric multi-valued properties. */ + static final char DEFAULT_NUMERIC_DELIMITER = ','; + /** The default value. */ protected final List defaultValue; + private char multiValueDelimiter = DEFAULT_DELIMITER; /** @@ -49,15 +56,16 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty theDefault, float theUIOrder, char delimiter) { - super(theName, theDescription, theUIOrder, delimiter); + super(theName, theDescription, theUIOrder); defaultValue = Collections.unmodifiableList(theDefault); + multiValueDelimiter = delimiter; } @@ -78,6 +86,12 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty + * @param The type of the values * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public abstract class AbstractPackagedProperty extends AbstractSingleValueProperty { - protected static final Map PACKAGED_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory - .expectedFieldTypesWith(new String[] {LEGAL_PACKAGES}, new Boolean[] {Boolean.FALSE}); + /** Required keys in the map. */ + protected static final Map PACKAGED_FIELD_TYPES_BY_KEY + = BasicPropertyDescriptorFactory.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; @@ -49,14 +56,22 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro } - protected static String[] packageNamesIn(Map params) { - // TODO - return null; + protected static String[] packageNamesIn(Map 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; } @Override - protected void addAttributesTo(Map attributes) { + protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); attributes.put(LEGAL_PACKAGES, delimitedPackageNames()); @@ -158,7 +173,7 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro * @return The legal package names */ public String[] legalPackageNames() { - return legalPackageNames; + return Arrays.copyOf(legalPackageNames, legalPackageNames.length); // defensive copy } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index ee90634568..64de9417dc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -18,56 +18,30 @@ import net.sourceforge.pmd.util.StringUtil; /** * Abstract class for properties. * - * @param The type of the values. + * @param The type of the values * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public abstract class AbstractProperty implements PropertyDescriptor { - /** - * Default delimiter for multi properties. Note: Numeric properties usual - * use the {@value #DEFAULT_NUMERIC_DELIMITER}. - */ - public static final char DEFAULT_DELIMITER = '|'; - - /** - * Default delimiter for numeric properties. - */ - public static final char DEFAULT_NUMERIC_DELIMITER = ','; - private final String name; private final String description; private final boolean isRequired; private final float uiOrder; - private char multiValueDelimiter = DEFAULT_DELIMITER; /** - * Creates an AbstractProperty using the default delimiter {@link #DEFAULT_DELIMITER}. + * Constructor for an abstract property. * - * @param theName Name of the property (must not be empty) - * @param theDescription Description (must not be empty) - * @param theUIOrder UI order (must be positive or zero) - * - * @throws IllegalArgumentException If name or description are empty, or UI order is negative. - */ - protected AbstractProperty(String theName, String theDescription, float theUIOrder) { - this(theName, theDescription, theUIOrder, DEFAULT_DELIMITER); - } - - - /** - * Constructor for AbstractPMDProperty. - * - * @param theName Name of the property (must not be empty) - * @param theDescription Description (must not be empty) - * @param theUIOrder UI order (must be positive or zero) - * @param delimiter The delimiter to separate multi values + * @param theName Name of the property + * @param theDescription Description + * @param theUIOrder UI order * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ protected AbstractProperty(String theName, String theDescription, - float theUIOrder, char delimiter) { + float theUIOrder) { if (theUIOrder < 0) { throw new IllegalArgumentException("Property attribute 'UI order' cannot be null or blank"); } @@ -76,11 +50,10 @@ public abstract class AbstractProperty implements PropertyDescriptor { description = checkNotEmpty(theDescription, DESCRIPTION); isRequired = false; // TODO - do we need this? uiOrder = theUIOrder; - multiValueDelimiter = delimiter; } - private static String checkNotEmpty(String arg, String argId) throws IllegalArgumentException { + private static String checkNotEmpty(String arg, PropertyDescriptorField argId) throws IllegalArgumentException { if (StringUtil.isEmpty(arg)) { throw new IllegalArgumentException("Property attribute '" + argId + "' cannot be null or blank"); } @@ -128,12 +101,6 @@ public abstract class AbstractProperty implements PropertyDescriptor { } - @Override - public char multiValueDelimiter() { - return multiValueDelimiter; - } - - @Override public final String asDelimitedString(T values) { return asDelimitedString(values, multiValueDelimiter()); @@ -212,7 +179,8 @@ public abstract class AbstractProperty implements PropertyDescriptor { /** - * Adds this property's attributes to the map. Subclasses can override this to add more Property fields. + * Adds this property's attributes to the map. Subclasses can override this to add more + * {@link PropertyDescriptorField}. * * @param attributes The map to fill */ @@ -224,4 +192,5 @@ public abstract class AbstractProperty implements PropertyDescriptor { attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); } } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index e95bfc3787..10f6bf5264 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -23,22 +23,28 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty /** - * Creates a single value property using the default delimiter {@link #DEFAULT_DELIMITER}. + * Creates a single value property. * - * @param theName Name of the property (must not be empty) - * @param theDescription Description (must not be empty) - * @param theUIOrder UI order (must be positive or zero) + * @param theName Name of the property + * @param theDescription Description + * @param theUIOrder UI order * @param theDefault Default value * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ protected AbstractSingleValueProperty(String theName, String theDescription, T theDefault, float theUIOrder) { - super(theName, theDescription, theUIOrder, DEFAULT_DELIMITER); + super(theName, theDescription, theUIOrder); defaultValue = theDefault; } + @Override + public final char multiValueDelimiter() { + return '\0'; + } + + @Override public final T defaultValue() { return defaultValue; @@ -87,7 +93,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty } - private String typeErrorFor(T value) { // TODO:cf consider subtypes!! + private String typeErrorFor(T value) { // TODO:cf consider subtypes? if (value != null && !type().isAssignableFrom(value.getClass())) { return value + " is not an instance of " + type(); @@ -97,11 +103,25 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty } + /** + * Checks the value for an error. + * + * @param value Value to check + * + * @return A diagnostic error message, or null if there's no problem + */ protected String valueErrorFor(T value) { return value != null || defaultHasNullValue() ? null : "missing value"; } + /** + * Returns a string representation of the value, even if it's null. + * + * @param value The value to describe + * + * @return A string representation of the value + */ protected String asString(T value) { return value == null ? "" : value.toString(); } @@ -126,9 +146,7 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty * * @return An instance of a value */ - protected abstract T createFrom(String toParse); - - // this is there to be symmetrical. + protected abstract T createFrom(String toParse); // this is there to be symmetrical to multi values @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index a29580168c..b0e209f6ce 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -22,17 +22,17 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class BooleanMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Boolean.class) { - @Override - public BooleanMultiProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new BooleanMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER), - 0f); - } - }; + @Override + public BooleanMultiProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new BooleanMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER), + 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 1e42c2b739..2f90d873d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -19,21 +19,20 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class BooleanProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Boolean.class) { - - @Override - public BooleanProperty createWith(Map valuesById) { - return new BooleanProperty(nameIn(valuesById), - descriptionIn(valuesById), - BOOLEAN_PARSER.valueOf(defaultValueIn(valuesById)), - 0f); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new BasicPropertyDescriptorFactory(Boolean.class) { + @Override + public BooleanProperty createWith(Map valuesById) { + return new BooleanProperty(nameIn(valuesById), + descriptionIn(valuesById), + BOOLEAN_PARSER.valueOf(defaultValueIn(valuesById)), + 0f); + } + }; // @formatter:on /** - * Constructor for BooleanProperty limited to a single value. + * Constructor. * * @param theName Name * @param theDescription Description @@ -53,6 +52,8 @@ public class BooleanProperty extends AbstractSingleValueProperty { * @param theDescription Description * @param defaultBoolStr String representing the default value. * @param theUIOrder UI order + * + * @deprecated ? */ public BooleanProperty(String theName, String theDescription, String defaultBoolStr, float theUIOrder) { this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 2d2509e01f..c6ccbc8613 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -24,17 +24,18 @@ import net.sourceforge.pmd.util.StringUtil; public class CharacterMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory>(Character.class) { - @Override - public CharacterMultiProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new CharacterMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER), - 0.0f, - delimiter); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new BasicPropertyDescriptorFactory>(Character.class) { + @Override + public CharacterMultiProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new CharacterMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER), + 0.0f, + delimiter); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 9b7943ab1a..6315b8a53b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -19,25 +19,25 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class CharacterProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(Character.class) { - - @Override - public CharacterProperty createWith(Map valuesById) { - return new CharacterProperty(nameIn(valuesById), - descriptionIn(valuesById), - CHARACTER_PARSER.valueOf(defaultValueIn(valuesById)), - 0f); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new BasicPropertyDescriptorFactory(Character.class) { + @Override + public CharacterProperty createWith(Map valuesById) { + return new CharacterProperty(nameIn(valuesById), + descriptionIn(valuesById), + CHARACTER_PARSER.valueOf(defaultValueIn(valuesById)), + 0f); + } + }; // @formatter:on /** - * Constructor for CharacterProperty. + * Constructor. * - * @param theName String - * @param theDescription String - * @param theDefault Character - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param theDefault Default value + * @param theUIOrder UI order */ public CharacterProperty(String theName, String theDescription, Character theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index 6619933b01..b585ea390c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -24,21 +24,21 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class DoubleMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public DoubleMultiProperty createWith(Map valuesById) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER); - return new DoubleMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - DOUBLE_PARSER.valueOf(minMax[0]), - DOUBLE_PARSER.valueOf(minMax[1]), - defaultValues, - 0f); - } - }; + @Override + public DoubleMultiProperty createWith(Map valuesById) { + String[] minMax = minMaxFrom(valuesById); + char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER); + return new DoubleMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + DOUBLE_PARSER.valueOf(minMax[0]), + DOUBLE_PARSER.valueOf(minMax[1]), + defaultValues, + 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 7f890b726b..707273d106 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.DOUBLE_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -17,29 +20,32 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class DoubleProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory( - Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - - @Override - public DoubleProperty createWith(Map valuesById) { - final String[] minMax = minMaxFrom(valuesById); - return new DoubleProperty(nameIn(valuesById), descriptionIn(valuesById), Double.valueOf(minMax[0]), - Double.valueOf(minMax[1]), Double.valueOf(numericDefaultValueIn(valuesById)), 0f); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { + @Override + public DoubleProperty createWith(Map valuesById) { + final String[] minMax = minMaxFrom(valuesById); + return new DoubleProperty(nameIn(valuesById), + descriptionIn(valuesById), + DOUBLE_PARSER.valueOf(minMax[0]), + DOUBLE_PARSER.valueOf(minMax[1]), + DOUBLE_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f); + } + }; // @formatter:on /** - * Constructor for DoubleProperty. + * Constructor that limits itself to a single value within the specified limits. * - * @param theName String - * @param theDescription String - * @param min double - * @param max double - * @param theDefault double - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, float theUIOrder) { @@ -48,16 +54,18 @@ public class DoubleProperty extends AbstractNumericProperty { /** - * Constructor for DoubleProperty. + * Constructor for DoubleProperty that limits itself to a single value within the specified limits. Converts string + * arguments into the Double values. * - * @param theName String - * @param theDescription String - * @param minStr String - * @param maxStr String - * @param defaultStr String - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param minStr Minimum value of the property + * @param maxStr Maximum value of the property + * @param defaultStr Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + * @deprecated ? */ public DoubleProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index f2ebc2bc42..7ff65688a4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -27,18 +27,19 @@ import net.sourceforge.pmd.util.CollectionUtil; public class EnumeratedMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Enumeration.class) { - @Override - public EnumeratedMultiProperty createWith(Map valuesById) { - return new EnumeratedMultiProperty<>(nameIn(valuesById), - descriptionIn(valuesById), - labelsIn(valuesById), - choicesIn(valuesById), - indicesIn(valuesById), - 0f); - } - }; + @Override + public EnumeratedMultiProperty createWith(Map valuesById) { + return new EnumeratedMultiProperty<>(nameIn(valuesById), + descriptionIn(valuesById), + labelsIn(valuesById), + choicesIn(valuesById), + indicesIn(valuesById), + 0f); + } + }; // @formatter:on + private Map choicesByLabel; private Map labelsByChoice; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 165bcb801f..786a046f56 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -28,19 +28,21 @@ import net.sourceforge.pmd.util.CollectionUtil; public class EnumeratedProperty extends AbstractSingleValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Enumeration.class) { - @Override - public EnumeratedProperty createWith(Map valuesById) { - return new EnumeratedProperty<>(nameIn(valuesById), - descriptionIn(valuesById), - labelsIn(valuesById), // those are not implemented - choicesIn(valuesById), // ditto - indexIn(valuesById), // ditto - 0f); - } - }; + @Override + public EnumeratedProperty createWith(Map valuesById) { + return new EnumeratedProperty<>(nameIn(valuesById), + descriptionIn(valuesById), + labelsIn(valuesById), // this is not implemented + choicesIn(valuesById), // ditto + indexIn(valuesById), // ditto + 0f); + } + }; // @formatter:on + + private Map choicesByLabel; private Map labelsByChoice; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index 955541af1a..8b81a1e6fe 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -13,6 +13,8 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto import net.sourceforge.pmd.util.StringUtil; /** + * Property taking a File object as its value. + * * @author Brian Remedios */ public class FileProperty extends AbstractSingleValueProperty { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index d0ae958d26..9c09ce0c85 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -24,20 +24,20 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class FloatMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public FloatMultiProperty createWith(Map valuesById) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); - return new FloatMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - FLOAT_PARSER.valueOf(minMax[0]), - FLOAT_PARSER.valueOf(minMax[1]), - defaultValues, 0f); - } - }; + @Override + public FloatMultiProperty createWith(Map valuesById) { + String[] minMax = minMaxFrom(valuesById); + char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); + return new FloatMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + FLOAT_PARSER.valueOf(minMax[0]), + FLOAT_PARSER.valueOf(minMax[1]), + defaultValues, 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index f0e6a4f7b1..ea8c477d8e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.FLOAT_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** @@ -17,30 +20,31 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class FloatProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { - - @Override - public FloatProperty createWith(Map valuesById) { - final String[] minMax = minMaxFrom(valuesById); - return new FloatProperty(nameIn(valuesById), descriptionIn(valuesById), Float.valueOf(minMax[0]), - Float.valueOf(minMax[1]), Float.valueOf(numericDefaultValueIn(valuesById)), 0f); - } - }; + @Override + public FloatProperty createWith(Map valuesById) { + final String[] minMax = minMaxFrom(valuesById); + return new FloatProperty(nameIn(valuesById), + descriptionIn(valuesById), + FLOAT_PARSER.valueOf(minMax[0]), + FLOAT_PARSER.valueOf(minMax[1]), + FLOAT_PARSER.valueOf(numericDefaultValueIn(valuesById)), 0f); + } + }; // @formatter:on /** - * Constructor for FloatProperty that limits itself to a single value within - * the specified limits. + * Constructor that limits itself to a single value within the specified limits. * - * @param theName String - * @param theDescription String - * @param min float - * @param max float - * @param theDefault float - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, float theUIOrder) { @@ -49,17 +53,18 @@ public class FloatProperty extends AbstractNumericProperty { /** - * Constructor for FloatProperty that limits itself to a single value within - * the specified limits. Converts string arguments into the Float values. + * Constructor for FloatProperty that limits itself to a single value within the specified limits. Converts string + * arguments into the Float values. * - * @param theName String - * @param theDescription String - * @param minStr String - * @param maxStr String - * @param defaultStr String - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param minStr Minimum value of the property + * @param maxStr Maximum value of the property + * @param defaultStr Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + * @deprecated ? */ public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { @@ -75,7 +80,7 @@ public class FloatProperty extends AbstractNumericProperty { * @return Parsed Float */ public static Float floatFrom(String numberString) { - return Float.valueOf(numberString); + return FLOAT_PARSER.valueOf(numberString); } @@ -87,6 +92,6 @@ public class FloatProperty extends AbstractNumericProperty { @Override protected Float createFrom(String value) { - return floatFrom(value); + return FLOAT_PARSER.valueOf(value); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 77c86942ae..933b7ee93d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -24,7 +24,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class IntegerMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerMultiProperty createWith(Map valuesById) { @@ -38,7 +38,7 @@ public class IntegerMultiProperty extends AbstractMultiNumericProperty defaultValues, 0f); } - }; + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index b36dc76381..f6a166df08 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -20,33 +20,32 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto */ public class IntegerProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - - @Override - public IntegerProperty createWith(Map valuesById) { - final String[] minMax = minMaxFrom(valuesById); - return new IntegerProperty(nameIn(valuesById), - descriptionIn(valuesById), - INTEGER_PARSER.valueOf(minMax[0]), - INTEGER_PARSER.valueOf(minMax[1]), - INTEGER_PARSER.valueOf(numericDefaultValueIn(valuesById)), - 0f); - } - }; + @Override + public IntegerProperty createWith(Map valuesById) { + final String[] minMax = minMaxFrom(valuesById); + return new IntegerProperty(nameIn(valuesById), + descriptionIn(valuesById), + INTEGER_PARSER.valueOf(minMax[0]), + INTEGER_PARSER.valueOf(minMax[1]), + INTEGER_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f); + } + }; // @formatter:on /** - * Constructor for IntegerProperty that limits itself to a single value within the specified limits. + * Constructor that limits itself to a single value within the specified limits. * - * @param theName String - * @param theDescription String - * @param min Integer - * @param max Integer - * @param theDefault Integer - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public IntegerProperty(String theName, String theDescription, int min, int max, int theDefault, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index ff73afdf46..686fd10f91 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -24,20 +24,20 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto public class LongMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public LongMultiProperty createWith(Map valuesById) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); - return new LongMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - LONG_PARSER.valueOf(minMax[0]), - LONG_PARSER.valueOf(minMax[1]), - defaultValues, 0f); - } - }; + @Override + public LongMultiProperty createWith(Map valuesById) { + String[] minMax = minMaxFrom(valuesById); + char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); + List defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); + return new LongMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + LONG_PARSER.valueOf(minMax[0]), + LONG_PARSER.valueOf(minMax[1]), + defaultValues, 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index ae02b6f042..f14f89721e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -4,42 +4,48 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.LONG_PARSER; + import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** - * Defines a datatype that supports the single Long property values within an - * upper and lower boundary. + * Single valued long property. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class LongProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { - - @Override - public LongProperty createWith(Map valuesById) { - final String[] minMax = minMaxFrom(valuesById); - return new LongProperty(nameIn(valuesById), descriptionIn(valuesById), Long.valueOf(minMax[0]), - Long.valueOf(minMax[1]), Long.valueOf(numericDefaultValueIn(valuesById)), 0f); - } - }; + @Override + public LongProperty createWith(Map valuesById) { + final String[] minMax = minMaxFrom(valuesById); + return new LongProperty(nameIn(valuesById), + descriptionIn(valuesById), + LONG_PARSER.valueOf(minMax[0]), + LONG_PARSER.valueOf(minMax[1]), + LONG_PARSER.valueOf(numericDefaultValueIn(valuesById)), 0f); + } + }; + // @formatter:on /** - * Constructor for LongProperty. + * Constructor that limits itself to a single value within the specified limits. * - * @param theName String - * @param theDescription String - * @param min Long - * @param max Long - * @param theDefault Long - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { super(theName, theDescription, min, max, theDefault, theUIOrder); @@ -47,17 +53,18 @@ public class LongProperty extends AbstractNumericProperty { /** - * Constructor for LongProperty that limits itself to a single value within - * the specified limits. Converts string arguments into the Long values. + * Constructor for LongProperty that limits itself to a single value within the specified limits. Converts string + * arguments into the Long values. * - * @param theName String - * @param theDescription String - * @param minStr String - * @param maxStr String - * @param defaultStr String - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param minStr Minimum value of the property + * @param maxStr Maximum value of the property + * @param defaultStr Default value + * @param theUIOrder UI order * - * @throws IllegalArgumentException + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + * @deprecated ? */ public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index bce66aeff8..3e4e85ff91 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; @@ -23,18 +24,20 @@ import net.sourceforge.pmd.util.StringUtil; * partial package names, i.e., ["java.lang", "com.mycompany" ]. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class MethodMultiProperty extends AbstractMultiPackagedProperty { - public static final PropertyDescriptorFactory FACTORY + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public MethodMultiProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new MethodMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); - } - }; + @Override + public MethodMultiProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new MethodMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), + legalPackageNamesIn(valuesById, delimiter), 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 2b0338ae23..38932cd271 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -9,6 +9,7 @@ import java.lang.reflect.Method; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.ClassUtil; import net.sourceforge.pmd.util.StringUtil; @@ -22,22 +23,26 @@ import net.sourceforge.pmd.util.StringUtil; * partial package names, i.e., ["java.lang", "com.mycompany" ].

* * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public class MethodProperty extends AbstractPackagedProperty { + public static final char CLASS_METHOD_DELIMITER = '#'; public static final char METHOD_ARG_DELIMITER = ','; public static final char[] METHOD_GROUP_DELIMITERS = {'(', ')'}; - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { - - @Override - public MethodProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new MethodProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); - } - }; + @Override + public MethodProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new MethodProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById), + legalPackageNamesIn(valuesById, delimiter), + 0f); + } + }; // @formatter:on private static final String ARRAY_FLAG = "[]"; private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); @@ -54,75 +59,6 @@ public class MethodProperty extends AbstractPackagedProperty { } - public MethodProperty(String theName, String theDescription, String defaultMethodStr, - Map otherParams, float theUIOrder) { - this(theName, theDescription, methodFrom(defaultMethodStr), packageNamesIn(otherParams), theUIOrder); - } - - - private static String shortestNameFor(Class cls) { - String compactName = TYPE_SHORTCUTS.get(cls); - return compactName == null ? cls.getName() : compactName; - } - - - /** - * 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(); - } - - - 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); - } - - - /** - * 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 Class typeFor(String typeName) { Class type; @@ -241,6 +177,69 @@ public class MethodProperty extends AbstractPackagedProperty { } + /** + * 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(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index 28ec56169b..867e8dad06 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -10,6 +10,7 @@ import java.util.Map.Entry; import java.util.Set; import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; /** @@ -34,11 +35,6 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } - public PropertyDescriptor getPropertyDescriptor() { - return propertyDescriptor; - } - - @Override public String asDelimitedString(T value) { return propertyDescriptor.asDelimitedString(value); @@ -143,7 +139,7 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { @Override - public Map attributeValuesById() { + public Map attributeValuesById() { return propertyDescriptor.attributeValuesById(); } @@ -157,6 +153,11 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } + public PropertyDescriptor getPropertyDescriptor() { + return propertyDescriptor; + } + + @Override public int hashCode() { return this.getPropertyDescriptor().hashCode(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index eb1e0f5c96..c724bf21cd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -23,18 +23,18 @@ import net.sourceforge.pmd.util.StringUtil; public class StringMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(String.class) { - @Override - public StringMultiProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new StringMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), - 0.0f, - delimiter); - } - }; + @Override + public StringMultiProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new StringMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), + 0.0f, + delimiter); + } + }; // @formatter:on /** @@ -109,6 +109,23 @@ public class StringMultiProperty extends AbstractMultiValueProperty { } + @Override + protected String valueErrorFor(String value) { + + if (value == null) { + return "missing value"; + } + + if (containsDelimiter(value)) { + return illegalCharMsg(); + } + + // TODO - eval against regex checkers + + return null; + } + + /** * Returns true if the multi value delimiter is present in the string. * @@ -126,23 +143,6 @@ public class StringMultiProperty extends AbstractMultiValueProperty { } - @Override - protected String valueErrorFor(String value) { - - if (value == null) { - return "missing value"; - } - - if (containsDelimiter(value)) { - return illegalCharMsg(); - } - - // TODO - eval against regex checkers - - return null; - } - - @Override protected String createFrom(String toParse) { return toParse; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 20d8ecae72..2ef06880e8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -19,7 +19,6 @@ public class StringProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { - @Override public StringProperty createWith(Map valuesById) { return new StringProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), 0f); @@ -28,15 +27,15 @@ public class StringProperty extends AbstractSingleValueProperty { /** - * Constructor for StringProperty. + * Constructor. * - * @param theName String - * @param theDescription String - * @param theDefaultValue String - * @param theUIOrder float + * @param theName Name + * @param theDescription Description + * @param defaultValue Default value + * @param theUIOrder UI order */ - public StringProperty(String theName, String theDescription, String theDefaultValue, float theUIOrder) { - super(theName, theDescription, theDefaultValue, theUIOrder); + public StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder) { + super(theName, theDescription, defaultValue, theUIOrder); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index c18ba128d2..340ccfa173 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -24,18 +24,19 @@ import net.sourceforge.pmd.util.StringUtil; */ public class TypeMultiProperty extends AbstractMultiPackagedProperty { - public static final PropertyDescriptorFactory FACTORY + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory>(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public TypeMultiProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new TypeMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), - 0f); - } - }; + @Override + public TypeMultiProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new TypeMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById), + legalPackageNamesIn(valuesById, delimiter), + 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index e59fbbde3a..b6844001e3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.ClassUtil; import net.sourceforge.pmd.util.StringUtil; @@ -21,33 +22,18 @@ import net.sourceforge.pmd.util.StringUtil; */ public class TypeProperty extends AbstractPackagedProperty { - public static final PropertyDescriptorFactory FACTORY + public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { - - @Override - public TypeProperty createWith(Map valuesById) { - char delimiter = delimiterIn(valuesById); - return new TypeProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); - } - }; - - - /** - * Constructor for TypeProperty. - * - * @param theName String - * @param theDescription String - * @param theDefault Class - * @param legalPackageNames String[] - * @param theUIOrder float - * - * @throws IllegalArgumentException - */ - public TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, - float theUIOrder) { - super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); - } + @Override + public TypeProperty createWith(Map valuesById) { + char delimiter = delimiterIn(valuesById); + return new TypeProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById), + legalPackageNamesIn(valuesById, delimiter), + 0f); + } + }; // @formatter:on /** @@ -67,9 +53,20 @@ public class TypeProperty extends AbstractPackagedProperty { } - public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, + /** + * Constructor for TypeProperty. + * + * @param theName String + * @param theDescription String + * @param theDefault Class + * @param legalPackageNames String[] + * @param theUIOrder float + * + * @throws IllegalArgumentException + */ + public TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, float theUIOrder) { - this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); + super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); } @@ -90,6 +87,12 @@ public class TypeProperty extends AbstractPackagedProperty { } } + // TODO:cf deprecate this + public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, + float theUIOrder) { + this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); + } + @Override protected String packageNameOf(Class item) { From df59eb8977bd2e51f9e396cc6a2cc62fd088b7a0 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 27 Jun 2017 05:55:17 +0200 Subject: [PATCH 09/53] Finally the enum transformation is complete --- .../pmd/PropertyDescriptorField.java | 14 +- .../net/sourceforge/pmd/RuleSetFactory.java | 8 +- .../net/sourceforge/pmd/RuleSetWriter.java | 10 +- .../AbstractMultiValueProperty.java | 4 +- .../rule/properties/CharacterProperty.java | 3 +- .../lang/rule/properties/IntegerProperty.java | 4 +- .../rule/properties/MethodMultiProperty.java | 4 +- .../BasicPropertyDescriptorFactory.java | 131 +++++------------- .../PropertyDescriptorFactory.java | 21 ++- .../PropertyDescriptorWrapper.java | 2 +- .../lang/rule/xpath/SaxonXPathRuleQuery.java | 2 +- .../AbstractPropertyDescriptorTester.java | 6 +- .../properties/EnumeratedPropertyTest.java | 90 ------------ .../SimpleEnumeratedPropertyTest.java | 105 ++++++++++++++ 14 files changed, 184 insertions(+), 220 deletions(-) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{ => factories}/PropertyDescriptorFactory.java (85%) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{ => factories}/PropertyDescriptorWrapper.java (98%) delete mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java index dbb761d557..b063f9fe7b 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java @@ -24,10 +24,6 @@ public enum PropertyDescriptorField { NAME("name"), /** The description of the property. */ DESCRIPTION("description"), - /** The description of the property. */ - DESC("description"), - /** The default value. */ - VALUE("value"), /** The default value. */ DEFAULT_VALUE("value"), /** For multi-valued properties, this defines the delimiter of the single values. */ @@ -45,15 +41,17 @@ public enum PropertyDescriptorField { /** Default index for enumerated properties. */ DEFAULT_INDEX("defaultIndex"); - final String representation; + final String attributeName; - PropertyDescriptorField(String representation) { - this.representation = representation; + + PropertyDescriptorField(String attributeName) { + this.attributeName = attributeName; } + @Override public String toString() { - return representation; + return attributeName; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 378270427a..d8b1e65f41 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -38,7 +38,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; +import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; import net.sourceforge.pmd.util.ResourceLoader; import net.sourceforge.pmd.util.StringUtil; @@ -848,15 +848,15 @@ public class RuleSetFactory { private static void parsePropertyNodeBR(Rule rule, Node propertyNode) { Element propertyElement = (Element) propertyNode; - String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE); - String strValue = propertyElement.getAttribute(PropertyDescriptorField.VALUE); + String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName); + String strValue = propertyElement.getAttribute(PropertyDescriptorField.DEFAULT_VALUE.attributeName); if (StringUtil.isEmpty(strValue)) { strValue = valueFrom(propertyElement); } // Setting of existing property, or defining a new property? if (StringUtil.isEmpty(typeId)) { - String name = propertyElement.getAttribute(PropertyDescriptorField.NAME); + String name = propertyElement.getAttribute(PropertyDescriptorField.NAME.attributeName); PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); if (propertyDescriptor == null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index cd40879599..050c4e5b2c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -33,7 +33,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.ImmutableLanguage; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; +import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; /** @@ -385,12 +385,12 @@ public class RuleSetWriter { final Element propertyElement = createPropertyValueElement(propertyDescriptor, propertyDescriptor.defaultValue()); - propertyElement.setAttribute(PropertyDescriptorField.TYPE, + propertyElement.setAttribute(PropertyDescriptorField.TYPE.attributeName, PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type())); - Map propertyValuesById = propertyDescriptor.attributeValuesById(); - for (Map.Entry entry : propertyValuesById.entrySet()) { - propertyElement.setAttribute(entry.getKey(), entry.getValue()); + Map propertyValuesById = propertyDescriptor.attributeValuesById(); + for (Map.Entry entry : propertyValuesById.entrySet()) { + propertyElement.setAttribute(entry.getKey().attributeName, entry.getValue()); } return propertyElement; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index cee9882bf2..5ff44c7453 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -24,10 +24,10 @@ import net.sourceforge.pmd.Rule; public abstract class AbstractMultiValueProperty extends AbstractProperty> { /** Default delimiter for multi-valued properties other than numeric ones. */ - static final char DEFAULT_DELIMITER = '|'; + public static final char DEFAULT_DELIMITER = '|'; /** Default delimiter for numeric multi-valued properties. */ - static final char DEFAULT_NUMERIC_DELIMITER = ','; + public static final char DEFAULT_NUMERIC_DELIMITER = ','; /** The default value. */ protected final List defaultValue; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 6315b8a53b..bf404d120c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -25,7 +25,8 @@ public class CharacterProperty extends AbstractSingleValueProperty { public CharacterProperty createWith(Map valuesById) { return new CharacterProperty(nameIn(valuesById), descriptionIn(valuesById), - CHARACTER_PARSER.valueOf(defaultValueIn(valuesById)), + defaultValueIn(valuesById) == null ? null + : defaultValueIn(valuesById).charAt(0), 0f); } }; // @formatter:on diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index f6a166df08..d9f4231a83 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -47,7 +47,7 @@ public class IntegerProperty extends AbstractNumericProperty { * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public IntegerProperty(String theName, String theDescription, int min, int max, int theDefault, + public IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, float theUIOrder) { super(theName, theDescription, min, max, theDefault, theUIOrder); } @@ -61,7 +61,7 @@ public class IntegerProperty extends AbstractNumericProperty { * @return Parsed Integer */ public static Integer intFrom(String numberString) { - + return INTEGER_PARSER.valueOf(numberString); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 3e4e85ff91..0ead079b7e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -79,9 +79,9 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { super(theName, theDescription, methodsFrom(methodDefaults), legalPackageNames, theUIOrder); } - + // TODO:cf deprecate this public MethodMultiProperty(String theName, String theDescription, String methodDefaults, - Map otherParams, float theUIOrder) { + Map otherParams, float theUIOrder) { this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index eb50db9175..cc794b6946 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -6,7 +6,7 @@ package net.sourceforge.pmd.lang.rule.properties.factories; import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; -import static net.sourceforge.pmd.PropertyDescriptorField.DESC; +import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION; import static net.sourceforge.pmd.PropertyDescriptorField.LEGAL_PACKAGES; import static net.sourceforge.pmd.PropertyDescriptorField.MAX; import static net.sourceforge.pmd.PropertyDescriptorField.MIN; @@ -21,11 +21,13 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.AbstractProperty; +import net.sourceforge.pmd.lang.rule.properties.AbstractMultiValueProperty; import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** + * Basic implementation of a property descriptor factory. + * * @param * * @author Brian Remedios @@ -33,7 +35,8 @@ import net.sourceforge.pmd.util.StringUtil; public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { protected static final Map CORE_FIELD_TYPES_BY_KEY - = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESC, DEFAULT_VALUE, DELIMITER}, new Boolean[] {true, true, true, false}); + = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESCRIPTION, DEFAULT_VALUE, DELIMITER}, + new Boolean[] {true, true, true, false}); private final Class valueType; @@ -49,8 +52,8 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; - Map temp = new HashMap<>( - CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); + Map temp + = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); temp.putAll(CORE_FIELD_TYPES_BY_KEY); temp.putAll(additionalFieldTypesByKey); @@ -58,16 +61,6 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } - private static String minValueIn(Map valuesById) { - return valuesById.get(MIN); - } - - - private static String maxValueIn(Map valuesById) { - return valuesById.get(MAX); - } - - /** * Parses a string into a list of values of type {@literal }. * @@ -88,69 +81,15 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } - protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) { - String[] values = StringUtil.substringsOf(booleanString, delimiter); - - Boolean[] result = new Boolean[values.length]; - for (int i = 0; i < values.length; i++) { - result[i] = Boolean.valueOf(values[i]); - } - return result; - } - - - protected static Long[] longsIn(String numberString, char delimiter) { - String[] values = StringUtil.substringsOf(numberString, delimiter); - List longs = new ArrayList<>(values.length); - for (String value : values) { - try { - Long newLong = Long.parseLong(value); - longs.add(newLong); - } catch (Exception ex) { - - } - } - return longs.toArray(new Long[longs.size()]); - } - - - protected static Float[] floatsIn(String numberString, char delimiter) { - String[] values = StringUtil.substringsOf(numberString, delimiter); - List floats = new ArrayList<>(values.length); - for (String value : values) { - try { - Float newFloat = Float.parseFloat(value); - floats.add(newFloat); - } catch (Exception ex) { - - } - } - return floats.toArray(new Float[floats.size()]); - } - - - protected static Double[] doublesIn(String numberString, char delimiter) { - String[] values = StringUtil.substringsOf(numberString, delimiter); - List doubles = new ArrayList<>(values.length); - for (String value : values) { - try { - Double newDouble = Double.parseDouble(value); - doubles.add(newDouble); - } catch (Exception ex) { - - } - } - return doubles.toArray(new Double[doubles.size()]); - } - - protected static String[] labelsIn(Map valuesById) { - return null; // TODO + return StringUtil.substringsOf(valuesById.get(PropertyDescriptorField.LABELS), + AbstractMultiValueProperty.DEFAULT_DELIMITER); } protected static Object[] choicesIn(Map valuesById) { - return null; // TODO + return null; // TODO: find a way to extract an arbitrary object from a string + // Maybe reason enough to only allow enums... } @@ -158,22 +97,6 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return 0; // TODO } - // protected static T[] primitivesFrom(String text, WrapperBuilder - // builder) { - // - // String[] values = text.split(","); // TODO - // List items = new ArrayList(values.length); - // for (String value : values) { - // try { - // Object newIten = builder.itemFrom(value); - // items.add(newIten); - // } catch (Exception ex) { - // - // } - // } - // return items.toArray(builder.newArray(items.size())); - // } - protected static int[] indicesIn(Map valuesById) { return null; // TODO @@ -181,7 +104,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact protected static char delimiterIn(Map valuesById) { - return delimiterIn(valuesById, AbstractProperty.DEFAULT_DELIMITER); + return delimiterIn(valuesById, AbstractMultiValueProperty.DEFAULT_DELIMITER); } @@ -190,7 +113,7 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact if (valuesById.containsKey(DELIMITER)) { characterStr = valuesById.get(DELIMITER).trim(); } - if (characterStr.isEmpty()) { + if (StringUtil.isEmpty(characterStr)) { return defaultDelimiter; } return characterStr.charAt(0); @@ -207,6 +130,16 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } + private static String minValueIn(Map valuesById) { + return valuesById.get(MIN); + } + + + private static String maxValueIn(Map valuesById) { + return valuesById.get(MAX); + } + + protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { String names = valuesById.get(LEGAL_PACKAGES); if (StringUtil.isEmpty(names)) { @@ -252,20 +185,18 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact protected String descriptionIn(Map valuesById) { - return valuesById.get(DESC); - } - - - protected String defaultValueIn(Map valuesById) { - return valuesById.get(DEFAULT_VALUE); + return valuesById.get(DESCRIPTION); } protected String numericDefaultValueIn(Map valuesById) { String number = defaultValueIn(valuesById); - return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 - // reasonable if - // undefined? + return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 reasonable if undefined? + } + + + protected String defaultValueIn(Map valuesById) { + return valuesById.get(DEFAULT_VALUE); } // protected static Map diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java similarity index 85% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java index b7c7244a5b..81db487a3c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java @@ -2,13 +2,32 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties; +package net.sourceforge.pmd.lang.rule.properties.factories; import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.INTEGER_PARSER; import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.lang.rule.properties.BooleanMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; +import net.sourceforge.pmd.lang.rule.properties.CharacterMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.CharacterProperty; +import net.sourceforge.pmd.lang.rule.properties.DoubleMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; +import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; +import net.sourceforge.pmd.lang.rule.properties.FloatMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.FloatProperty; +import net.sourceforge.pmd.lang.rule.properties.IntegerMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; +import net.sourceforge.pmd.lang.rule.properties.LongMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.LongProperty; +import net.sourceforge.pmd.lang.rule.properties.MethodMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.MethodProperty; +import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.StringProperty; +import net.sourceforge.pmd.lang.rule.properties.TypeMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.TypeProperty; import net.sourceforge.pmd.util.StringUtil; public class PropertyDescriptorFactory { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java similarity index 98% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java index 867e8dad06..8a7b1e1e7b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties; +package net.sourceforge.pmd.lang.rule.properties.factories; import java.util.List; import java.util.Map; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 7eb6deae8f..1c8910d03d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -17,7 +17,7 @@ import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; +import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.StringProperty; import net.sourceforge.pmd.lang.xpath.Initializer; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index fb9be6dd86..2d93493d26 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -227,8 +227,8 @@ public abstract class AbstractPropertyDescriptorTester { return (PropertyDescriptorFactory>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); } - private Map getPropertyDescriptorValues() { - Map valuesById = new HashMap<>(); + private Map getPropertyDescriptorValues() { + Map valuesById = new HashMap<>(); valuesById.put(PropertyDescriptorField.NAME, "test"); valuesById.put(PropertyDescriptorField.DESCRIPTION, "desc"); valuesById.put(PropertyDescriptorField.MIN, "0"); @@ -260,7 +260,7 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testFactoryMultiValueCustomDelimiter() { PropertyDescriptorFactory> multiFactory = getMultiFactory(); - Map valuesById = getPropertyDescriptorValues(); + Map valuesById = getPropertyDescriptorValues(); String customDelimiter = "ä"; assertFalse(ALL_CHARS.contains(customDelimiter)); valuesById.put(PropertyDescriptorField.DELIMITER, customDelimiter); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java deleted file mode 100644 index 847f75421c..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/EnumeratedPropertyTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.junit.Assume; -import org.junit.Test; - -import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; - -/** - * Evaluates the functionality of the EnumeratedProperty descriptor by testing - * its ability to catch creation errors (illegal args), flag invalid selections, - * and serialize/deserialize selection options. - * - * @author Brian Remedios - */ -public class EnumeratedPropertyTest extends AbstractPropertyDescriptorTester { - - private static final String[] KEYS = new String[] {"map", "emptyArray", "list", "string",}; - - private static final Object[] VALUES = new Object[] {new HashMap(), new Object[0], new ArrayList(), - "Hello World!",}; - - public EnumeratedPropertyTest() { - super("Enum"); - } - - - @Override - protected Object createValue() { - return randomChoice(VALUES); - } - - - @Override - protected Object createBadValue() { - return Integer.toString(randomInt()); // not in the set of values - } - - @Override - protected PropertyDescriptor createMultiProperty() { - return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, - VALUES, new int[] {0, 1}, 1.0f); - } - - @Override - protected PropertyDescriptor createProperty() { - return new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, VALUES, 0, - 1.0f); - } - - - @Override - protected PropertyDescriptor createBadProperty() { - - return new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", new String[0], - VALUES, -1, 1.0f); - } - - @Override - protected PropertyDescriptor createBadMultiProperty() { - return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, - new Object[0], new int[] {99}, 1.0f); - } - - @Override - @Test - public void testFactorySingleValue() { - Assume.assumeTrue("The EnumeratedProperty is not implemented completely yet", false); - } - - @Override - @Test - public void testFactoryMultiValueCustomDelimiter() { - Assume.assumeTrue("The EnumeratedProperty is not implemented completely yet", false); - } - - @Override - @Test - public void testFactoryMultiValueDefaultDelimiter() { - Assume.assumeTrue("The EnumeratedProperty is not implemented completely yet", false); - } -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java new file mode 100644 index 0000000000..9d60e20064 --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -0,0 +1,105 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties; + +import java.util.List; + +import org.junit.Assume; +import org.junit.Test; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; +import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; + +/** + * Evaluates the functionality of the EnumeratedProperty descriptor by testing + * its ability to catch creation errors (illegal args), flag invalid selections, + * and serialize/deserialize selection options. + * + * @author Brian Remedios + */ +public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTester { + + private static final String[] KEYS = {"bar", "na", "bee", "coo",}; + private static final Foo[] VALUES = Foo.values(); + + + public SimpleEnumeratedPropertyTest() { + super("Enum"); + } + + + @Override + protected Foo createValue() { + return randomChoice(Foo.values()); + } + + + @Override + protected Foo createBadValue() { + return null; // not in the set of values + } + + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new EnumeratedMultiProperty<>("testEnumerations", + "Test enumerations with complex types", + KEYS, + VALUES, + new int[] {0, 1}, 1.0f); + } + + + @Override + protected PropertyDescriptor createProperty() { + return new EnumeratedProperty<>("testEnumerations", + "Test enumerations with complex types", + KEYS, + VALUES, 0, + 1.0f); + } + + + @Override + protected PropertyDescriptor createBadProperty() { + return new EnumeratedProperty<>("testEnumerations", "Test enumerations with simple type", + new String[0], VALUES, -1, 1.0f); + } + + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with simple type", + KEYS, VALUES, new int[] {99}, 1.0f); + } + + + @Override + @Test + public void testFactorySingleValue() { + Assume.assumeTrue("The EnumeratedProperty factory is not implemented yet", false); + } + + + @Override + @Test + public void testFactoryMultiValueCustomDelimiter() { + Assume.assumeTrue("The EnumeratedProperty factory is not implemented yet", false); + } + + + @Override + @Test + public void testFactoryMultiValueDefaultDelimiter() { + Assume.assumeTrue("The EnumeratedProperty factory is not implemented yet", false); + } + + + enum Foo { + BAR, NA, BEE, COO + } +} From de1298f1fa96f17fb6fa9b821b66cb08f0dd67d2 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 27 Jun 2017 05:57:45 +0200 Subject: [PATCH 10/53] Corrected multinumeric properties --- .../lang/rule/properties/AbstractMultiNumericProperty.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index adcd82bb06..bfd501bf0b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -24,8 +24,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty implements NumericPropertyDescriptor> { - private T lowerLimit; - private T upperLimit; + private Number lowerLimit; + private Number upperLimit; /** @@ -40,7 +40,8 @@ public abstract class AbstractMultiNumericProperty extends Abs * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public AbstractMultiNumericProperty(String theName, String theDescription, T min, T max, List theDefault, float theUIOrder) { + public AbstractMultiNumericProperty(String theName, String theDescription, Number min, Number max, List theDefault, + float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); if (min.doubleValue() > max.doubleValue()) { From 2fe8ded6bda257583f9d155665d8b4c39bd11339 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 27 Jun 2017 14:15:14 +0200 Subject: [PATCH 11/53] Made properties final --- .../AbstractMultiNumericProperty.java | 6 +- .../AbstractMultiPackagedProperty.java | 82 ++++---- .../AbstractMultiValueProperty.java | 104 +++++----- .../properties/AbstractNumericProperty.java | 29 +-- .../properties/AbstractPackagedProperty.java | 94 ++++----- .../rule/properties/AbstractProperty.java | 42 ++-- .../AbstractSingleValueProperty.java | 46 ++--- .../rule/properties/BooleanMultiProperty.java | 2 +- .../lang/rule/properties/BooleanProperty.java | 29 +-- .../properties/CharacterMultiProperty.java | 2 +- .../rule/properties/CharacterProperty.java | 29 +-- .../rule/properties/DoubleMultiProperty.java | 2 +- .../lang/rule/properties/DoubleProperty.java | 39 ++-- .../properties/EnumeratedMultiProperty.java | 34 ++-- .../rule/properties/EnumeratedProperty.java | 19 +- .../lang/rule/properties/FileProperty.java | 3 +- .../rule/properties/FloatMultiProperty.java | 2 +- .../lang/rule/properties/FloatProperty.java | 39 ++-- .../rule/properties/IntegerMultiProperty.java | 2 +- .../lang/rule/properties/IntegerProperty.java | 26 +-- .../rule/properties/LongMultiProperty.java | 2 +- .../lang/rule/properties/LongProperty.java | 37 ++-- .../rule/properties/MethodMultiProperty.java | 27 +-- .../lang/rule/properties/MethodProperty.java | 188 +++++++++--------- .../rule/properties/StringMultiProperty.java | 2 +- .../lang/rule/properties/StringProperty.java | 3 +- .../rule/properties/TypeMultiProperty.java | 12 +- .../lang/rule/properties/TypeProperty.java | 3 +- .../BasicPropertyDescriptorFactory.java | 78 ++++---- 29 files changed, 488 insertions(+), 495 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index bfd501bf0b..5f7578c7cc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -21,11 +21,11 @@ import net.sourceforge.pmd.PropertyDescriptorField; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty +/* default */ abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty implements NumericPropertyDescriptor> { - private Number lowerLimit; - private Number upperLimit; + private final Number lowerLimit; + private final Number upperLimit; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index ad1df51ac0..3377d7811b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -23,7 +23,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty { +/* default */ abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty { /** Delimiter between values. */ protected static final char DELIMITER = '|'; @@ -56,38 +56,6 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu } - protected static String[] packageNamesIn(Map params) { - // TODO - return null; - } - - - @Override - protected void addAttributesTo(Map 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(); - } - - /** * 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. @@ -126,11 +94,39 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu /** - * Returns the name of the type of item. + * Returns the package name of the item. * - * @return The name of the type of item + * @param item Item + * + * @return Package name of the item */ - protected abstract String itemTypeName(); + protected abstract String packageNameOf(T item); + + + @Override + protected void addAttributesTo(Map 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(); + } @Override @@ -160,13 +156,11 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu /** - * Returns the package name of the item. + * Returns the name of the type of item. * - * @param item Item - * - * @return Package name of the item + * @return The name of the type of item */ - protected abstract String packageNameOf(T item); + protected abstract String itemTypeName(); /** @@ -177,4 +171,10 @@ public abstract class AbstractMultiPackagedProperty extends AbstractMultiValu public String[] legalPackageNames() { return Arrays.copyOf(legalPackageNames, legalPackageNames.length); } + + + protected static String[] packageNamesIn(Map params) { + // TODO + return null; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 5ff44c7453..a21cb5727f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.Rule; * @author Clément Fournier * @version 6.0.0 */ -public abstract class AbstractMultiValueProperty extends AbstractProperty> { +/* default */ abstract class AbstractMultiValueProperty extends AbstractProperty> { /** Default delimiter for multi-valued properties other than numeric ones. */ public static final char DEFAULT_DELIMITER = '|'; @@ -69,59 +69,12 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty defaultValue() { - return defaultValue; - } - - - private boolean defaultHasNullValue() { - return defaultValue == null || defaultValue.contains(null); - } - - @Override public final boolean isMultiValue() { return true; } - @Override - public char multiValueDelimiter() { - return multiValueDelimiter; - } - - - /** - * Returns a string representation of the value, even if it's null. - * - * @param value The value to describe - * - * @return A string representation of the value - */ - protected String asString(V value) { - return value == null ? "" : value.toString(); - } - - - @Override - public String asDelimitedString(List values, char delimiter) { - if (values == null) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - for (V value : values) { - sb.append(asString(value)).append(delimiter); - } - if (sb.length() > 0) { - sb.deleteCharAt(sb.length() - 1); - } - - return sb.toString(); - } - - /* This is the one overriden in PropertyDescriptor */ @Override public String propertyErrorFor(Rule rule) { @@ -160,6 +113,11 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty>> choices() { return null; @@ -176,14 +134,46 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty values, char delimiter) { + if (values == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + for (V value : values) { + sb.append(asString(value)).append(delimiter); + } + if (sb.length() > 0) { + sb.deleteCharAt(sb.length() - 1); + } + + return sb.toString(); + } + + + @Override + public List defaultValue() { + return defaultValue; + } + + + @Override + public char multiValueDelimiter() { + return multiValueDelimiter; + } + + /** - * Parse a string and returns an instance of a single value (not a list). + * Returns a string representation of the value, even if it's null. * - * @param toParse String to parse + * @param value The value to describe * - * @return An instance of a value + * @return A string representation of the value */ - protected abstract V createFrom(String toParse); + protected String asString(V value) { + return value == null ? "" : value.toString(); + } @Override @@ -198,4 +188,14 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty The type of value. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public abstract class AbstractNumericProperty extends AbstractSingleValueProperty +/* default */ abstract class AbstractNumericProperty extends AbstractSingleValueProperty implements NumericPropertyDescriptor { public static final Map NUMBER_FIELD_TYPES_BY_KEY @@ -45,19 +46,6 @@ public abstract class AbstractNumericProperty extends Abstract } - /** - * Returns a string representing the range defined by the two bounds. - * - * @param low Lower bound - * @param up Upper bound - * - * @return String - */ - static String rangeString(Number low, Number up) { - return "(" + low + " -> " + up + ")"; - } - - /** * Returns the minimum value that instances of the property can have * @@ -101,6 +89,19 @@ public abstract class AbstractNumericProperty extends Abstract } + /** + * Returns a string representing the range defined by the two bounds. + * + * @param low Lower bound + * @param up Upper bound + * + * @return String + */ + static String rangeString(Number low, Number up) { + return "(" + low + " -> " + up + ")"; + } + + @Override protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index 9fee30e0cb..7aab9da327 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -23,7 +23,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public abstract class AbstractPackagedProperty extends AbstractSingleValueProperty { +/* default */ abstract class AbstractPackagedProperty extends AbstractSingleValueProperty { /** Required keys in the map. */ protected static final Map PACKAGED_FIELD_TYPES_BY_KEY @@ -56,20 +56,42 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro } - protected static String[] packageNamesIn(Map params) { - String[] packageNames = StringUtil.substringsOf(params.get(LEGAL_PACKAGES), - PACKAGE_NAME_DELIMITER); + /** + * 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; + } - for (String name : packageNames) { - if (!packageNamePattern.matcher(name).matches()) { - throw new IllegalArgumentException("One name is not a package: '" + name + "'"); + String name = packageNameOf(item); + + for (String legalNamePrefixe : legalNamePrefixes) { + if (name.startsWith(legalNamePrefixe)) { + return; } } - return packageNames; + 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 attributes) { super.addAttributesTo(attributes); @@ -97,40 +119,6 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro } - /** - * 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 name of the type of item. - * - * @return The name of the type of item - */ - protected abstract String itemTypeName(); - - @Override protected String valueErrorFor(T value) { @@ -158,13 +146,11 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro /** - * Returns the package name of the item. + * Returns the name of the type of item. * - * @param item Item - * - * @return Package name of the item + * @return The name of the type of item */ - protected abstract String packageNameOf(T item); + protected abstract String itemTypeName(); /** @@ -176,4 +162,18 @@ public abstract class AbstractPackagedProperty extends AbstractSingleValuePro return Arrays.copyOf(legalPackageNames, legalPackageNames.length); // defensive copy } + + protected static String[] packageNamesIn(Map 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; + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 64de9417dc..b6a73bfedb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -23,7 +23,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public abstract class AbstractProperty implements PropertyDescriptor { +/* default */ abstract class AbstractProperty implements PropertyDescriptor { private final String name; private final String description; @@ -61,28 +61,6 @@ public abstract class AbstractProperty implements PropertyDescriptor { } - /** - * Tests if two values are equal. - * - * @param value First value - * @param otherValue Object - * - * @return True if the two values are equal. - * - * @deprecated Never used in pmd's codebase + is just an alias for Object#equals. - */ - @SuppressWarnings("PMD.CompareObjectsWithEquals") - public static boolean areEqual(Object value, Object otherValue) { - return value != null && value.equals(otherValue); - } - - - @Override - public String name() { - return name; - } - - @Override public String description() { return description; @@ -162,12 +140,10 @@ public abstract class AbstractProperty implements PropertyDescriptor { } - /** - * Returns a string representation of the default value. - * - * @return A string representation of the default value. - */ - protected abstract String defaultAsString(); + @Override + public String name() { + return name; + } @Override @@ -193,4 +169,12 @@ public abstract class AbstractProperty implements PropertyDescriptor { } } + + /** + * Returns a string representation of the default value. + * + * @return A string representation of the default value. + */ + protected abstract String defaultAsString(); + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 10f6bf5264..4219b6f8c3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -16,7 +16,7 @@ import net.sourceforge.pmd.Rule; * * @author Clément Fournier */ -public abstract class AbstractSingleValueProperty extends AbstractProperty { +/* default */ abstract class AbstractSingleValueProperty extends AbstractProperty { /** Default value. */ protected T defaultValue; @@ -51,16 +51,6 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty } - /** - * Returns true if the default value is {@code null}. - * - * @return True if the default value is {@code null}. - */ - private boolean defaultHasNullValue() { - return defaultValue == null; - } - - @Override public final boolean isMultiValue() { return false; @@ -73,6 +63,18 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty } + /** + * Returns a string representation of the value, even if it's null. + * + * @param value The value to describe + * + * @return A string representation of the value + */ + protected String asString(T value) { + return value == null ? "" : value.toString(); + } + + @Override public String propertyErrorFor(Rule rule) { T realValue = rule.getProperty(this); @@ -116,14 +118,12 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty /** - * Returns a string representation of the value, even if it's null. + * Returns true if the default value is {@code null}. * - * @param value The value to describe - * - * @return A string representation of the value + * @return True if the default value is {@code null}. */ - protected String asString(T value) { - return value == null ? "" : value.toString(); + private boolean defaultHasNullValue() { + return defaultValue == null; } @@ -139,6 +139,12 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty } + @Override + public final T valueFrom(String valueString) throws IllegalArgumentException { + return createFrom(valueString); + } + + /** * Parse a string and returns an instance of a value. * @@ -148,10 +154,4 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty */ protected abstract T createFrom(String toParse); // this is there to be symmetrical to multi values - - @Override - public final T valueFrom(String valueString) throws IllegalArgumentException { - return createFrom(valueString); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index b0e209f6ce..9a128912e5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -19,7 +19,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class BooleanMultiProperty extends AbstractMultiValueProperty { +public final class BooleanMultiProperty extends AbstractMultiValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 2f90d873d9..f6c59ab1f9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -16,8 +16,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * Defines a property type that supports single Boolean values. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class BooleanProperty extends AbstractSingleValueProperty { +public final class BooleanProperty extends AbstractSingleValueProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Boolean.class) { @@ -31,19 +32,6 @@ public class BooleanProperty extends AbstractSingleValueProperty { }; // @formatter:on - /** - * Constructor. - * - * @param theName Name - * @param theDescription Description - * @param defaultValue Default value - * @param theUIOrder UI order - */ - public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) { - super(theName, theDescription, defaultValue, theUIOrder); - } - - /** * Constructor for BooleanProperty limited to a single value. Converts * default argument string into a boolean. @@ -60,6 +48,19 @@ public class BooleanProperty extends AbstractSingleValueProperty { } + /** + * Constructor. + * + * @param theName Name + * @param theDescription Description + * @param defaultValue Default value + * @param theUIOrder UI order + */ + public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) { + super(theName, theDescription, defaultValue, theUIOrder); + } + + @Override public Class type() { return Boolean.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index c6ccbc8613..e348502320 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class CharacterMultiProperty extends AbstractMultiValueProperty { +public final class CharacterMultiProperty extends AbstractMultiValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index bf404d120c..75b29abc02 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -16,8 +16,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * Defines a property type that supports single Character values. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class CharacterProperty extends AbstractSingleValueProperty { +public final class CharacterProperty extends AbstractSingleValueProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Character.class) { @@ -32,19 +33,6 @@ public class CharacterProperty extends AbstractSingleValueProperty { }; // @formatter:on - /** - * 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) { - super(theName, theDescription, theDefault, theUIOrder); - } - - /** * Constructor for CharacterProperty. * @@ -60,6 +48,19 @@ public class CharacterProperty extends AbstractSingleValueProperty { } + /** + * 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) { + super(theName, theDescription, theDefault, theUIOrder); + } + + /** * Parses a String into a Character. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index b585ea390c..335e4c76e1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class DoubleMultiProperty extends AbstractMultiNumericProperty { +public final class DoubleMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 707273d106..82a29c4829 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -17,8 +17,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * within an upper and lower boundary. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class DoubleProperty extends AbstractNumericProperty { +public final class DoubleProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @@ -35,24 +36,6 @@ public class DoubleProperty extends AbstractNumericProperty { }; // @formatter:on - /** - * Constructor that limits itself to a single value within the specified limits. - * - * @param theName Name - * @param theDescription Description - * @param min Minimum value of the property - * @param max Maximum value of the property - * @param theDefault Default value - * @param theUIOrder UI order - * - * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - */ - public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, - float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); - } - - /** * Constructor for DoubleProperty that limits itself to a single value within the specified limits. Converts string * arguments into the Double values. @@ -73,6 +56,24 @@ public class DoubleProperty extends AbstractNumericProperty { } + /** + * Constructor that limits itself to a single value within the specified limits. + * + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + */ + public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, + float theUIOrder) { + super(theName, theDescription, min, max, theDefault, theUIOrder); + } + + /** * Parses a String into a Double. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index 7ff65688a4..d758892529 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -24,7 +24,7 @@ import net.sourceforge.pmd.util.CollectionUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class EnumeratedMultiProperty extends AbstractMultiValueProperty { +public final class EnumeratedMultiProperty extends AbstractMultiValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -40,8 +40,8 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { } }; // @formatter:on - private Map choicesByLabel; - private Map labelsByChoice; + private final Map choicesByLabel; + private final Map labelsByChoice; /** @@ -57,9 +57,7 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { */ public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, float theUIOrder) { - super(theName, theDescription, selection(choiceIndices, theChoices), theUIOrder); - choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices); - labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); + this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), selection(choiceIndices, theChoices), theUIOrder); } @@ -79,7 +77,7 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { checkDefaults(defaultValues, choices); choicesByLabel = Collections.unmodifiableMap(choices); - labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); + labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel)); } @@ -110,11 +108,6 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { } - private String nonLegalValueMsgFor(E value) { - return value + " is not a legal value"; - } - - @Override public String errorFor(List values) { for (E value : values) { @@ -126,6 +119,17 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { } + private String nonLegalValueMsgFor(E value) { + return value + " is not a legal value"; + } + + + @Override + protected E createFrom(String toParse) { + return choiceFrom(toParse); + } + + private E choiceFrom(String label) { E result = choicesByLabel.get(label); if (result == null) { @@ -135,12 +139,6 @@ public class EnumeratedMultiProperty extends AbstractMultiValueProperty { } - @Override - protected E createFrom(String toParse) { - return choiceFrom(toParse); - } - - @Override public String asString(E item) { return labelsByChoice.get(item); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 786a046f56..a423b4341a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -24,8 +24,9 @@ import net.sourceforge.pmd.util.CollectionUtil; * @param Type of the choices * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class EnumeratedProperty extends AbstractSingleValueProperty { +public final class EnumeratedProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -43,8 +44,8 @@ public class EnumeratedProperty extends AbstractSingleValueProperty { }; // @formatter:on - private Map choicesByLabel; - private Map labelsByChoice; + private final Map choicesByLabel; + private final Map labelsByChoice; public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, @@ -80,6 +81,12 @@ public class EnumeratedProperty extends AbstractSingleValueProperty { } + @Override + public E createFrom(String value) throws IllegalArgumentException { + return choiceFrom(value); + } + + private E choiceFrom(String label) { E result = choicesByLabel.get(label); if (result != null) { @@ -89,12 +96,6 @@ public class EnumeratedProperty extends AbstractSingleValueProperty { } - @Override - public E createFrom(String value) throws IllegalArgumentException { - return choiceFrom(value); - } - - @Override public String asString(E value) { return labelsByChoice.get(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index 8b81a1e6fe..c63e44bc64 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -16,8 +16,9 @@ import net.sourceforge.pmd.util.StringUtil; * Property taking a File object as its value. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class FileProperty extends AbstractSingleValueProperty { +public final class FileProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(File.class) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 9c09ce0c85..2b9e1533bf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class FloatMultiProperty extends AbstractMultiNumericProperty { +public final class FloatMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index ea8c477d8e..6d933d58a2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -18,8 +18,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class FloatProperty extends AbstractNumericProperty { +public final class FloatProperty extends AbstractNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override @@ -34,24 +35,6 @@ public class FloatProperty extends AbstractNumericProperty { }; // @formatter:on - /** - * Constructor that limits itself to a single value within the specified limits. - * - * @param theName Name - * @param theDescription Description - * @param min Minimum value of the property - * @param max Maximum value of the property - * @param theDefault Default value - * @param theUIOrder UI order - * - * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - */ - public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, - float theUIOrder) { - super(theName, theDescription, Float.valueOf(min), Float.valueOf(max), Float.valueOf(theDefault), theUIOrder); - } - - /** * Constructor for FloatProperty that limits itself to a single value within the specified limits. Converts string * arguments into the Float values. @@ -72,6 +55,24 @@ public class FloatProperty extends AbstractNumericProperty { } + /** + * Constructor that limits itself to a single value within the specified limits. + * + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + */ + public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, + float theUIOrder) { + super(theName, theDescription, Float.valueOf(min), Float.valueOf(max), Float.valueOf(theDefault), theUIOrder); + } + + /** * Parses a String into a Float. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 933b7ee93d..fc6b74753b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class IntegerMultiProperty extends AbstractMultiNumericProperty { +public final class IntegerMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index d9f4231a83..5e1a36dcfa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * * @author Brian Remedios */ -public class IntegerProperty extends AbstractNumericProperty { +public final class IntegerProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @@ -53,18 +53,6 @@ public class IntegerProperty extends AbstractNumericProperty { } - /** - * Parses a String into an Integer. - * - * @param numberString String to parse - * - * @return Parsed Integer - */ - public static Integer intFrom(String numberString) { - return INTEGER_PARSER.valueOf(numberString); - } - - @Override public Class type() { return Integer.class; @@ -75,4 +63,16 @@ public class IntegerProperty extends AbstractNumericProperty { protected Integer createFrom(String value) { return INTEGER_PARSER.valueOf(value); } + + + /** + * Parses a String into an Integer. + * + * @param numberString String to parse + * + * @return Parsed Integer + */ + public static Integer intFrom(String numberString) { + return INTEGER_PARSER.valueOf(numberString); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 686fd10f91..b096f09321 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -21,7 +21,7 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class LongMultiProperty extends AbstractMultiNumericProperty { +public final class LongMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index f14f89721e..95f55451e1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -18,8 +18,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class LongProperty extends AbstractNumericProperty { +public final class LongProperty extends AbstractNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override @@ -35,23 +36,6 @@ public class LongProperty extends AbstractNumericProperty { // @formatter:on - /** - * Constructor that limits itself to a single value within the specified limits. - * - * @param theName Name - * @param theDescription Description - * @param min Minimum value of the property - * @param max Maximum value of the property - * @param theDefault Default value - * @param theUIOrder UI order - * - * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - */ - public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); - } - - /** * Constructor for LongProperty that limits itself to a single value within the specified limits. Converts string * arguments into the Long values. @@ -72,6 +56,23 @@ public class LongProperty extends AbstractNumericProperty { } + /** + * Constructor that limits itself to a single value within the specified limits. + * + * @param theName Name + * @param theDescription Description + * @param min Minimum value of the property + * @param max Maximum value of the property + * @param theDefault Default value + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + */ + public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { + super(theName, theDescription, min, max, theDefault, theUIOrder); + } + + /** * Parses a String into a Long. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 0ead079b7e..12cba224fe 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -26,7 +26,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class MethodMultiProperty extends AbstractMultiPackagedProperty { +public final class MethodMultiProperty extends AbstractMultiPackagedProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -40,6 +40,12 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { }; // @formatter:on + public MethodMultiProperty(String theName, String theDescription, Method[] theDefaults, + String[] legalPackageNames, float theUIOrder) { + this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); + } + + /** * Constructor for MethodProperty. * @@ -57,12 +63,6 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { } - public MethodMultiProperty(String theName, String theDescription, Method[] theDefaults, - String[] legalPackageNames, float theUIOrder) { - this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); - } - - /** * Constructor for MethodProperty. * @@ -79,12 +79,6 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { super(theName, theDescription, methodsFrom(methodDefaults), legalPackageNames, theUIOrder); } - // TODO:cf deprecate this - public MethodMultiProperty(String theName, String theDescription, String methodDefaults, - Map otherParams, float theUIOrder) { - this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); - } - public static List methodsFrom(String methodsStr) { String[] values = StringUtil.substringsOf(methodsStr, DELIMITER); @@ -98,6 +92,13 @@ public class MethodMultiProperty extends AbstractMultiPackagedProperty { } + // TODO:cf deprecate this + public MethodMultiProperty(String theName, String theDescription, String methodDefaults, + Map otherParams, float theUIOrder) { + this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); + } + + @Override public String asString(Method value) { return value == null ? "" : MethodProperty.asStringFor(value); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 38932cd271..4f9a368ee4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -25,7 +25,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class MethodProperty extends AbstractPackagedProperty { +public final class MethodProperty extends AbstractPackagedProperty { public static final char CLASS_METHOD_DELIMITER = '#'; @@ -59,6 +59,99 @@ public class MethodProperty extends AbstractPackagedProperty { } + @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"; + } + + + @Override + public Class type() { + return Method.class; + } + + + @Override + public Method createFrom(String valueString) throws IllegalArgumentException { + return methodFrom(valueString); + } + + private static Class typeFor(String typeName) { Class type; @@ -169,97 +262,4 @@ public class MethodProperty extends AbstractPackagedProperty { public static Method methodFrom(String methodStr) { return methodFrom(methodStr, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER); } - - - @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"; - } - - - @Override - public Class type() { - return Method.class; - } - - - @Override - public Method createFrom(String valueString) throws IllegalArgumentException { - return methodFrom(valueString); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index c724bf21cd..a7ceb0abfe 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -20,7 +20,7 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public class StringMultiProperty extends AbstractMultiValueProperty { +public final class StringMultiProperty extends AbstractMultiValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 2ef06880e8..8ccf586128 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -14,8 +14,9 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto * Defines a datatype that supports single String values. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ -public class StringProperty extends AbstractSingleValueProperty { +public final class StringProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 340ccfa173..9aa7594b99 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -22,7 +22,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class TypeMultiProperty extends AbstractMultiPackagedProperty { +public final class TypeMultiProperty extends AbstractMultiPackagedProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -50,10 +50,9 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { * * @throws IllegalArgumentException */ - public TypeMultiProperty(String theName, String theDescription, List theDefaults, + public TypeMultiProperty(String theName, String theDescription, Class[] theDefaults, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); - + this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); } @@ -68,9 +67,10 @@ public class TypeMultiProperty extends AbstractMultiPackagedProperty { * * @throws IllegalArgumentException */ - public TypeMultiProperty(String theName, String theDescription, Class[] theDefaults, + public TypeMultiProperty(String theName, String theDescription, List theDefaults, String[] legalPackageNames, float theUIOrder) { - this(theName, theDescription, Arrays.asList(theDefaults), legalPackageNames, theUIOrder); + super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index b6844001e3..797e2842ac 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -20,7 +20,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class TypeProperty extends AbstractPackagedProperty { +public final class TypeProperty extends AbstractPackagedProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @@ -87,6 +87,7 @@ public class TypeProperty extends AbstractPackagedProperty { } } + // TODO:cf deprecate this public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java index cc794b6946..6727dc4aaa 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java @@ -61,6 +61,45 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } + @Override + public Class valueType() { + return valueType; + } + + + @Override + public PropertyDescriptor createWith(Map valuesById) { + throw new RuntimeException("Unimplemented createWith() method in subclass"); + } + + + @Override + public Map expectedFields() { + return fieldTypesByKey; + } + + + protected String nameIn(Map valuesById) { + return valuesById.get(NAME); + } + + + protected String descriptionIn(Map valuesById) { + return valuesById.get(DESCRIPTION); + } + + + protected String numericDefaultValueIn(Map valuesById) { + String number = defaultValueIn(valuesById); + return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 reasonable if undefined? + } + + + protected String defaultValueIn(Map valuesById) { + return valuesById.get(DEFAULT_VALUE); + } + + /** * Parses a string into a list of values of type {@literal }. * @@ -160,45 +199,6 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact return largerMap; } - - @Override - public Class valueType() { - return valueType; - } - - - @Override - public PropertyDescriptor createWith(Map valuesById) { - throw new RuntimeException("Unimplemented createWith() method in subclass"); - } - - - @Override - public Map expectedFields() { - return fieldTypesByKey; - } - - - protected String nameIn(Map valuesById) { - return valuesById.get(NAME); - } - - - protected String descriptionIn(Map valuesById) { - return valuesById.get(DESCRIPTION); - } - - - protected String numericDefaultValueIn(Map valuesById) { - String number = defaultValueIn(valuesById); - return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 reasonable if undefined? - } - - - protected String defaultValueIn(Map valuesById) { - return valuesById.get(DEFAULT_VALUE); - } - // protected static Map // factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) { // Map factoryMap = new HashMap Date: Tue, 27 Jun 2017 15:45:33 +0200 Subject: [PATCH 12/53] Split interfaces --- .../pmd/EnumeratedPropertyDescriptor.java | 26 ++++++++ .../pmd/MultiValuePropertyDescriptor.java | 26 ++++++++ .../sourceforge/pmd/PropertyDescriptor.java | 29 ++++----- .../pmd/PropertyDescriptorField.java | 2 +- .../net/sourceforge/pmd/RuleSetFactory.java | 17 +++--- .../net/sourceforge/pmd/RuleSetWriter.java | 5 +- .../pmd/SingleValuePropertyDescriptor.java | 14 +++++ .../sourceforge/pmd/lang/rule/XPathRule.java | 9 +-- .../AbstractMultiNumericProperty.java | 2 +- .../AbstractMultiPackagedProperty.java | 1 - .../AbstractMultiValueProperty.java | 40 ++++++++----- .../properties/AbstractNumericProperty.java | 1 - .../properties/AbstractPackagedProperty.java | 1 - .../rule/properties/AbstractProperty.java | 22 ------- .../AbstractSingleValueProperty.java | 25 ++------ .../BasicPropertyDescriptorFactory.java | 8 ++- .../rule/properties/BooleanMultiProperty.java | 3 +- .../lang/rule/properties/BooleanProperty.java | 3 +- .../properties/CharacterMultiProperty.java | 2 - .../rule/properties/CharacterProperty.java | 3 +- .../rule/properties/DoubleMultiProperty.java | 3 +- .../lang/rule/properties/DoubleProperty.java | 25 ++++---- .../properties/EnumeratedMultiProperty.java | 25 +++++--- .../rule/properties/EnumeratedProperty.java | 28 +++++---- .../lang/rule/properties/FileProperty.java | 1 - .../rule/properties/FloatMultiProperty.java | 3 +- .../lang/rule/properties/FloatProperty.java | 3 +- .../rule/properties/IntegerMultiProperty.java | 29 +++++---- .../lang/rule/properties/IntegerProperty.java | 5 +- .../rule/properties/LongMultiProperty.java | 3 +- .../lang/rule/properties/LongProperty.java | 3 +- .../rule/properties/MethodMultiProperty.java | 1 - .../lang/rule/properties/MethodProperty.java | 1 - .../PropertyDescriptorFactory.java | 28 ++------- .../PropertyDescriptorUtil.java | 23 +------ .../rule/properties/StringMultiProperty.java | 1 - .../lang/rule/properties/StringProperty.java | 1 - .../rule/properties/TypeMultiProperty.java | 1 - .../lang/rule/properties/TypeProperty.java | 1 - .../{factories => }/ValueParser.java | 2 +- .../EnumeratedPropertyDescriptorWrapper.java | 27 +++++++++ .../MultiValuePropertyDescriptorWrapper.java | 34 +++++++++++ .../PropertyDescriptorWrapper.java | 36 ++--------- .../SingleValuePropertyDescriptorWrapper.java | 25 ++++++++ .../lang/rule/xpath/SaxonXPathRuleQuery.java | 2 +- .../pmd/renderers/CodeClimateRenderer.java | 5 +- .../pmd/renderers/CodeClimateRule.java | 2 +- .../pmd/util/designer/Designer.java | 2 +- .../sourceforge/pmd/RuleSetFactoryTest.java | 1 - .../AbstractPropertyDescriptorTester.java | 2 +- .../pmd/properties/IntegerPropertyTest.java | 34 ++++++----- .../pmd/properties/MethodPropertyTest.java | 14 ++--- .../NonRuleWithAllPropertyTypes.java | 60 +++++++++---------- .../SimpleEnumeratedPropertyTest.java | 10 ++-- .../pmd/properties/TypePropertyTest.java | 4 +- 55 files changed, 363 insertions(+), 321 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{factories => }/BasicPropertyDescriptorFactory.java (97%) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{factories => }/PropertyDescriptorFactory.java (82%) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{factories => }/PropertyDescriptorUtil.java (65%) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{factories => }/ValueParser.java (97%) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{factories => wrappers}/PropertyDescriptorWrapper.java (80%) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java new file mode 100644 index 0000000000..0e0f7979dd --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java @@ -0,0 +1,26 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import java.util.Map; + +/** + * Interface defining an enumerated property descriptor. + * + * @param The type of the values + * @param The type of default values the descriptor can take (can be a List) + * + * @author Clément Fournier + */ +public interface EnumeratedPropertyDescriptor extends PropertyDescriptor { + + /** + * Returns a map of the label - value mappings defined by this descriptor. + * + * @return a map of the label - value mappings defined by this descriptor. + */ + Map mappings(); + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java new file mode 100644 index 0000000000..c12093aab7 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java @@ -0,0 +1,26 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +import java.util.List; + +/** + * @author Clément Fournier + */ +public interface MultiValuePropertyDescriptor extends PropertyDescriptor> { + + /** + * Return the character being used to delimit multiple property values + * within a single string. You must ensure that this character does not + * appear within any rule property values to avoid deserialization errors. + * + * @return char + */ + char multiValueDelimiter(); + + + @Override + Class type(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 8633213442..027d245cf9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; /** * Property value descriptor that defines the use & requirements for setting @@ -19,6 +17,7 @@ import java.util.Set; * @author Brian Remedios */ public interface PropertyDescriptor extends Comparable> { + /** * The name of the property without spaces as it serves as the key into the * property map. @@ -27,6 +26,7 @@ public interface PropertyDescriptor extends Comparable> */ String name(); + /** * Describes the property and the role it plays within the rule it is * specified for. Could be used in a tooltip. @@ -35,6 +35,7 @@ public interface PropertyDescriptor extends Comparable> */ String description(); + /** * Denotes the value datatype. For multi value properties, this is not the * List class but the list's component class. @@ -43,6 +44,7 @@ public interface PropertyDescriptor extends Comparable> */ Class type(); + /** * Returns whether the property is multi-valued, i.e. an array of strings, * @@ -55,6 +57,7 @@ public interface PropertyDescriptor extends Comparable> */ boolean isMultiValue(); + /** * Default value to use when the user hasn't specified one or when they wish * to revert to a known-good state. @@ -63,6 +66,7 @@ public interface PropertyDescriptor extends Comparable> */ T defaultValue(); + /** * Denotes whether the value is required before the rule can be executed. * Has no meaning for primitive types such as booleans, ints, etc. @@ -71,6 +75,7 @@ public interface PropertyDescriptor extends Comparable> */ boolean isRequired(); + /** * Validation function that returns a diagnostic error message for a sample * property value. Returns null if the value is acceptable. @@ -81,6 +86,7 @@ public interface PropertyDescriptor extends Comparable> */ String errorFor(T value); + /** * Denotes the relative order the property field should occupy if we are * using an auto-generated UI to display and edit property values. If the @@ -98,6 +104,7 @@ public interface PropertyDescriptor extends Comparable> */ float uiOrder(); + /** * If the property is multi-valued then return the separate values after * parsing the propertyString provided. If it isn't a multi-valued property @@ -112,6 +119,7 @@ public interface PropertyDescriptor extends Comparable> */ T valueFrom(String propertyString) throws IllegalArgumentException; + /** * Formats the object onto a string suitable for storage within the property * map. @@ -122,14 +130,6 @@ public interface PropertyDescriptor extends Comparable> */ String asDelimitedString(T value); - /** - * Returns a set of choice tuples if available, returns null if none are - * defined. - * - * @return a set of choice tuples if available, returns null if none are - * defined. - */ - Set> choices(); /** * A convenience method that returns an error string if the rule holds onto @@ -141,14 +141,6 @@ public interface PropertyDescriptor extends Comparable> */ String propertyErrorFor(Rule rule); - /** - * Return the character being used to delimit multiple property values - * within a single string. You must ensure that this character does not - * appear within any rule property values to avoid deserialization errors. - * - * @return char - */ - char multiValueDelimiter(); /** * If the datatype is a String then return the preferred number of rows to @@ -159,6 +151,7 @@ public interface PropertyDescriptor extends Comparable> */ int preferredRowCount(); + /** * Returns a map representing all the property attributes of the receiver in * string form. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java index b063f9fe7b..356b5e9a0e 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; /** * Field names for parsing the properties out of the ruleset xml files. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index d8b1e65f41..8c756eddd2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -19,7 +19,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.Adler32; import java.util.zip.CheckedInputStream; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -38,8 +37,8 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; import net.sourceforge.pmd.util.ResourceLoader; import net.sourceforge.pmd.util.StringUtil; @@ -868,17 +867,17 @@ public class RuleSetFactory { return; } - net.sourceforge.pmd.PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId); + net.sourceforge.pmd.PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId); if (pdFactory == null) { throw new RuntimeException("No property descriptor factory for type: " + typeId); } - Map valueKeys = pdFactory.expectedFields(); - Map values = new HashMap<>(valueKeys.size()); + Map valueKeys = pdFactory.expectedFields(); + Map values = new HashMap<>(valueKeys.size()); // populate a map of values for an individual descriptor - for (Map.Entry entry : valueKeys.entrySet()) { - String valueStr = propertyElement.getAttribute(entry.getKey()); + for (Map.Entry entry : valueKeys.entrySet()) { + String valueStr = propertyElement.getAttribute(entry.getKey().attributeName); if (entry.getValue() && StringUtil.isEmpty(valueStr)) { // TODO debug pt System.out.println("Missing required value for: " + entry.getKey()); @@ -887,7 +886,7 @@ public class RuleSetFactory { } PropertyDescriptor desc = pdFactory.createWith(values); - PropertyDescriptorWrapper wrapper = new PropertyDescriptorWrapper<>(desc); + PropertyDescriptorWrapper wrapper = new PropertyDescriptorWrapper<>(desc); // TODO:cf fix me rule.definePropertyDescriptor(wrapper); setValue(rule, desc, strValue); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 050c4e5b2c..edf7068713 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -9,7 +9,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; @@ -33,8 +32,8 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.ImmutableLanguage; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; /** * This class represents a way to serialize a RuleSet to an XML configuration diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java new file mode 100644 index 0000000000..5e8e1c486f --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java @@ -0,0 +1,14 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +/** + * @author Clément Fournier + */ +public interface SingleValuePropertyDescriptor extends PropertyDescriptor { + + @Override + Class type(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java index 677fd9fe51..8c5a92b330 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java @@ -22,15 +22,16 @@ import net.sourceforge.pmd.util.StringUtil; /** * Rule that tries to match an XPath expression against a DOM view of an AST. - * + * * This rule needs a "xpath" property value in order to function. */ public class XPathRule extends AbstractRule { public static final StringProperty XPATH_DESCRIPTOR = new StringProperty("xpath", "XPath expression", "", 1.0f); - public static final EnumeratedProperty VERSION_DESCRIPTOR = new EnumeratedProperty<>("version", - "XPath specification version", new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 }, - new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 }, 0, 2.0f); + public static final EnumeratedProperty VERSION_DESCRIPTOR + = new EnumeratedProperty<>("version", + "XPath specification version", new String[] {XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0}, + new String[] {XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0}, 0, String.class, 2.0f); private XPathRuleQuery xpathRuleQuery; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 5f7578c7cc..1bd17db07e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -40,7 +40,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ - public AbstractMultiNumericProperty(String theName, String theDescription, Number min, Number max, List theDefault, + AbstractMultiNumericProperty(String theName, String theDescription, Number min, Number max, List theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index 3377d7811b..cf433e480d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -13,7 +13,6 @@ import java.util.Map; import java.util.Set; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Multi-valued property restricting the type of its values to some packages. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index a21cb5727f..8fd54f78db 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -7,10 +7,11 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map.Entry; -import java.util.Set; +import java.util.Map; import java.util.regex.Pattern; +import net.sourceforge.pmd.MultiValuePropertyDescriptor; +import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; /** @@ -21,7 +22,8 @@ import net.sourceforge.pmd.Rule; * @author Clément Fournier * @version 6.0.0 */ -/* default */ abstract class AbstractMultiValueProperty extends AbstractProperty> { +/* default */ abstract class AbstractMultiValueProperty extends AbstractProperty> + implements MultiValuePropertyDescriptor { /** Default delimiter for multi-valued properties other than numeric ones. */ public static final char DEFAULT_DELIMITER = '|'; @@ -30,8 +32,8 @@ import net.sourceforge.pmd.Rule; public static final char DEFAULT_NUMERIC_DELIMITER = ','; /** The default value. */ - protected final List defaultValue; - private char multiValueDelimiter = DEFAULT_DELIMITER; + private final List defaultValue; + private final char multiValueDelimiter; /** @@ -44,7 +46,7 @@ import net.sourceforge.pmd.Rule; * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - public AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder) { + AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder) { this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER); } @@ -60,8 +62,8 @@ import net.sourceforge.pmd.Rule; * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - public AbstractMultiValueProperty(String theName, String theDescription, List theDefault, - float theUIOrder, char delimiter) { + AbstractMultiValueProperty(String theName, String theDescription, List theDefault, + float theUIOrder, char delimiter) { super(theName, theDescription, theUIOrder); defaultValue = Collections.unmodifiableList(theDefault); @@ -118,12 +120,6 @@ import net.sourceforge.pmd.Rule; } - @Override - public Set>> choices() { - return null; - } - - /** * Returns a string representation of the default value. * @@ -134,8 +130,7 @@ import net.sourceforge.pmd.Rule; } - @Override - public String asDelimitedString(List values, char delimiter) { + private String asDelimitedString(List values, char delimiter) { if (values == null) { return ""; } @@ -176,6 +171,12 @@ import net.sourceforge.pmd.Rule; } + @Override + public final String asDelimitedString(List values) { + return asDelimitedString(values, multiValueDelimiter()); + } + + @Override public List valueFrom(String valueString) throws IllegalArgumentException { String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter())); @@ -198,4 +199,11 @@ import net.sourceforge.pmd.Rule; */ protected abstract V createFrom(String toParse); + + @Override + protected void addAttributesTo(Map attributes) { + super.addAttributesTo(attributes); + attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 11c71be5ad..22affd060c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -11,7 +11,6 @@ import java.util.Map; import net.sourceforge.pmd.NumericPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Maintains a pair of boundary limit values between which all values managed by diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index 7aab9da327..c2c1d9e3b2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -11,7 +11,6 @@ import java.util.Map; import java.util.regex.Pattern; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index b6a73bfedb..bdbc47f9da 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -79,25 +79,6 @@ import net.sourceforge.pmd.util.StringUtil; } - @Override - public final String asDelimitedString(T values) { - return asDelimitedString(values, multiValueDelimiter()); - } - - - /** - * Return the specified values as a single string using the specified delimiter. - * - * @param values Values to format - * @param delimiter Delimiter character - * - * @return Delimited string - * - * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(T) - */ - protected abstract String asDelimitedString(T values, char delimiter); - - @Override public final int compareTo(PropertyDescriptor otherProperty) { float otherOrder = otherProperty.uiOrder(); @@ -164,9 +145,6 @@ import net.sourceforge.pmd.util.StringUtil; attributes.put(NAME, name); attributes.put(DESCRIPTION, description); attributes.put(DEFAULT_VALUE, defaultAsString()); - if (isMultiValue()) { - attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 4219b6f8c3..2c1f727ed7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -4,10 +4,8 @@ package net.sourceforge.pmd.lang.rule.properties; -import java.util.Map.Entry; -import java.util.Set; - import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.SingleValuePropertyDescriptor; /** * Single value property. @@ -16,10 +14,11 @@ import net.sourceforge.pmd.Rule; * * @author Clément Fournier */ -/* default */ abstract class AbstractSingleValueProperty extends AbstractProperty { +/* default */ abstract class AbstractSingleValueProperty extends AbstractProperty + implements SingleValuePropertyDescriptor { /** Default value. */ - protected T defaultValue; + private T defaultValue; /** @@ -39,12 +38,6 @@ import net.sourceforge.pmd.Rule; } - @Override - public final char multiValueDelimiter() { - return '\0'; - } - - @Override public final T defaultValue() { return defaultValue; @@ -58,8 +51,8 @@ import net.sourceforge.pmd.Rule; @Override - public String asDelimitedString(T value, char delimiter) { - return value == null ? "" : asString(value); + public String asDelimitedString(T value) { + return asString(value); } @@ -133,12 +126,6 @@ import net.sourceforge.pmd.Rule; } - @Override - public Set> choices() { - return null; - } - - @Override public final T valueFrom(String valueString) throws IllegalArgumentException { return createFrom(valueString); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java similarity index 97% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java index 6727dc4aaa..c6973ecd31 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.factories; +package net.sourceforge.pmd.lang.rule.properties; import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; @@ -21,7 +21,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.AbstractMultiValueProperty; import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; @@ -137,6 +136,11 @@ public class BasicPropertyDescriptorFactory implements PropertyDescriptorFact } + protected static Class classIn(Map valuesById) { + return Object.class; // TODO + } + + protected static int[] indicesIn(Map valuesById) { return null; // TODO } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index 9a128912e5..aa32bcfd71 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.BOOLEAN_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.BOOLEAN_PARSER; import java.util.Arrays; import java.util.List; @@ -12,7 +12,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a property type that supports multiple Boolean values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index f6c59ab1f9..5989a82d46 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.BOOLEAN_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.BOOLEAN_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a property type that supports single Boolean values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index e348502320..61c30b8e7b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -11,8 +11,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; -import net.sourceforge.pmd.lang.rule.properties.factories.ValueParser; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 75b29abc02..8659b1741a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.CHARACTER_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.CHARACTER_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a property type that supports single Character values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index 335e4c76e1..b6618737b5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -5,7 +5,7 @@ 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.factories.ValueParser.DOUBLE_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.DOUBLE_PARSER; import java.util.Arrays; import java.util.List; @@ -13,7 +13,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Multi-valued double property. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 82a29c4829..81844bacff 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.DOUBLE_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.DOUBLE_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a property type that support single double-type property values @@ -23,17 +22,17 @@ public final class DoubleProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public DoubleProperty createWith(Map valuesById) { - final String[] minMax = minMaxFrom(valuesById); - return new DoubleProperty(nameIn(valuesById), - descriptionIn(valuesById), - DOUBLE_PARSER.valueOf(minMax[0]), - DOUBLE_PARSER.valueOf(minMax[1]), - DOUBLE_PARSER.valueOf(numericDefaultValueIn(valuesById)), - 0f); - } - }; // @formatter:on + @Override + public DoubleProperty createWith(Map valuesById) { + final String[] minMax = minMaxFrom(valuesById); + return new DoubleProperty(nameIn(valuesById), + descriptionIn(valuesById), + DOUBLE_PARSER.valueOf(minMax[0]), + DOUBLE_PARSER.valueOf(minMax[1]), + DOUBLE_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index d758892529..4f84de0ae8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -10,9 +10,9 @@ import java.util.Enumeration; import java.util.List; import java.util.Map; +import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.CollectionUtil; /** @@ -24,7 +24,8 @@ import net.sourceforge.pmd.util.CollectionUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public final class EnumeratedMultiProperty extends AbstractMultiValueProperty { +public final class EnumeratedMultiProperty extends AbstractMultiValueProperty + implements EnumeratedPropertyDescriptor> { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -36,12 +37,14 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty labelsIn(valuesById), choicesIn(valuesById), indicesIn(valuesById), + classIn(valuesById), 0f); } }; // @formatter:on private final Map choicesByLabel; private final Map labelsByChoice; + private final Class valueType; /** @@ -56,8 +59,9 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param theUIOrder UI order */ public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, - int[] choiceIndices, float theUIOrder) { - this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), selection(choiceIndices, theChoices), theUIOrder); + int[] choiceIndices, Class valueType, float theUIOrder) { + this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), + selection(choiceIndices, theChoices), valueType, theUIOrder); } @@ -71,11 +75,12 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param theUIOrder UI order */ public EnumeratedMultiProperty(String theName, String theDescription, Map choices, - List defaultValues, float theUIOrder) { + List defaultValues, Class valueType, float theUIOrder) { super(theName, theDescription, defaultValues, theUIOrder); checkDefaults(defaultValues, choices); + this.valueType = valueType; choicesByLabel = Collections.unmodifiableMap(choices); labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel)); } @@ -103,8 +108,14 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty @Override - public Class type() { - return Enumeration.class; + public Map mappings() { + return choicesByLabel; + } + + + @Override + public Class type() { + return valueType; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index a423b4341a..113159bd8d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -7,12 +7,10 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Collections; import java.util.Enumeration; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.CollectionUtil; /** @@ -26,7 +24,8 @@ import net.sourceforge.pmd.util.CollectionUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -public final class EnumeratedProperty extends AbstractSingleValueProperty { +public final class EnumeratedProperty extends AbstractSingleValueProperty + implements EnumeratedPropertyDescriptor { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off @@ -39,6 +38,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty labelsIn(valuesById), // this is not implemented choicesIn(valuesById), // ditto indexIn(valuesById), // ditto + classIn(valuesById), 0f); } }; // @formatter:on @@ -46,27 +46,29 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty private final Map choicesByLabel; private final Map labelsByChoice; + private final Class valueType; public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, - int defaultIndex, float theUIOrder) { - this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), theChoices[defaultIndex], - theUIOrder); + int defaultIndex, Class valueType, float theUIOrder) { + this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), + theChoices[defaultIndex], valueType, theUIOrder); } public EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, - E defaultValue, float theUIOrder) { + E defaultValue, Class valueType, float theUIOrder) { super(theName, theDescription, defaultValue, theUIOrder); + this.valueType = valueType; choicesByLabel = Collections.unmodifiableMap(labelsToChoices); - labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel); + labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel)); } @Override - public Class type() { - return Object.class; + public Class type() { + return valueType; } @@ -103,8 +105,8 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty @Override - public Set> choices() { - return choicesByLabel.entrySet(); + public Map mappings() { + return choicesByLabel; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index c63e44bc64..4458d7cf31 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -9,7 +9,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 2b9e1533bf..caaf38d3d5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -5,7 +5,7 @@ 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.factories.ValueParser.FLOAT_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.FLOAT_PARSER; import java.util.Arrays; import java.util.List; @@ -13,7 +13,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Multi-valued float property. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 6d933d58a2..4689776e9c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.FLOAT_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.FLOAT_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a property type that supports single float property values within an diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index fc6b74753b..32965e1a31 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -5,7 +5,7 @@ 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.factories.ValueParser.INTEGER_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.INTEGER_PARSER; import java.util.Arrays; import java.util.List; @@ -13,7 +13,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Multi-valued integer property. @@ -26,19 +25,19 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public IntegerMultiProperty createWith(Map valuesById) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); - return new IntegerMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - INTEGER_PARSER.valueOf(minMax[0]), - INTEGER_PARSER.valueOf(minMax[1]), - defaultValues, - 0f); - } - }; // @formatter:on + @Override + public IntegerMultiProperty createWith(Map valuesById) { + String[] minMax = minMaxFrom(valuesById); + char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); + List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); + return new IntegerMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + INTEGER_PARSER.valueOf(minMax[0]), + INTEGER_PARSER.valueOf(minMax[1]), + defaultValues, + 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 5e1a36dcfa..e0f7a74929 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.INTEGER_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.INTEGER_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a datatype that supports single Integer property values within an @@ -22,7 +21,7 @@ public final class IntegerProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override + @Override public IntegerProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); return new IntegerProperty(nameIn(valuesById), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index b096f09321..642603239a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -5,7 +5,7 @@ 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.factories.ValueParser.LONG_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.LONG_PARSER; import java.util.Arrays; import java.util.List; @@ -13,7 +13,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Multi-valued long property. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index 95f55451e1..c94d3c5062 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.LONG_PARSER; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.LONG_PARSER; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Single valued long property. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 12cba224fe..e3763d07a9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -12,7 +12,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 4f9a368ee4..e9f48afa0d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -10,7 +10,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.ClassUtil; import net.sourceforge.pmd.util.StringUtil; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java similarity index 82% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index 81db487a3c..707b4d7ec2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -2,32 +2,12 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.factories; - -import static net.sourceforge.pmd.lang.rule.properties.factories.ValueParser.INTEGER_PARSER; +package net.sourceforge.pmd.lang.rule.properties; import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.lang.rule.properties.BooleanMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; -import net.sourceforge.pmd.lang.rule.properties.CharacterMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.CharacterProperty; -import net.sourceforge.pmd.lang.rule.properties.DoubleMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; -import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; -import net.sourceforge.pmd.lang.rule.properties.FloatMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.FloatProperty; -import net.sourceforge.pmd.lang.rule.properties.IntegerMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; -import net.sourceforge.pmd.lang.rule.properties.LongMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.LongProperty; -import net.sourceforge.pmd.lang.rule.properties.MethodMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.MethodProperty; -import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.StringProperty; -import net.sourceforge.pmd.lang.rule.properties.TypeMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.TypeProperty; +import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; import net.sourceforge.pmd.util.StringUtil; public class PropertyDescriptorFactory { @@ -102,8 +82,8 @@ public class PropertyDescriptorFactory { property.valueFrom(value), 0.0f); } else if ("Integer".equals(type)) { checkMinMax(name, type, min, max); - return new IntegerProperty(name, description, INTEGER_PARSER.valueOf(min), INTEGER_PARSER.valueOf(max), - INTEGER_PARSER.valueOf(value), 0.0f); + return new IntegerProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), ValueParser.INTEGER_PARSER.valueOf(max), + ValueParser.INTEGER_PARSER.valueOf(value), 0.0f); } else if ("List".equals(type)) { checkMinMax(name, type, min, max); IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java similarity index 65% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index 3192f31438..dfc41101ed 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.factories; +package net.sourceforge.pmd.lang.rule.properties; import java.util.Collections; import java.util.Comparator; @@ -11,27 +11,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; -import net.sourceforge.pmd.lang.rule.properties.BooleanMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; -import net.sourceforge.pmd.lang.rule.properties.CharacterMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.CharacterProperty; -import net.sourceforge.pmd.lang.rule.properties.DoubleMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; -import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; -import net.sourceforge.pmd.lang.rule.properties.FileProperty; -import net.sourceforge.pmd.lang.rule.properties.FloatMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.FloatProperty; -import net.sourceforge.pmd.lang.rule.properties.IntegerMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; -import net.sourceforge.pmd.lang.rule.properties.LongMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.LongProperty; -import net.sourceforge.pmd.lang.rule.properties.MethodMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.MethodProperty; -import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.StringProperty; -import net.sourceforge.pmd.lang.rule.properties.TypeMultiProperty; -import net.sourceforge.pmd.lang.rule.properties.TypeProperty; /** * @author Brian Remedios diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index a7ceb0abfe..2bc1997746 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -10,7 +10,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 8ccf586128..262fdf110a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -8,7 +8,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; /** * Defines a datatype that supports single String values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 9aa7594b99..142a38b18e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -11,7 +11,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.StringUtil; /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index 797e2842ac..2144c60342 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -8,7 +8,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory; import net.sourceforge.pmd.util.ClassUtil; import net.sourceforge.pmd.util.StringUtil; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java similarity index 97% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java index bbb9733d44..21cd075f4c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/ValueParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.factories; +package net.sourceforge.pmd.lang.rule.properties; /** * Parses a value from a string. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java new file mode 100644 index 0000000000..2cd32d4978 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java @@ -0,0 +1,27 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.wrappers; + +import java.util.Map; + +import net.sourceforge.pmd.EnumeratedPropertyDescriptor; + +/** + * @author Clément Fournier + */ +public class EnumeratedPropertyDescriptorWrapper extends PropertyDescriptorWrapper + implements EnumeratedPropertyDescriptor { + + public EnumeratedPropertyDescriptorWrapper(EnumeratedPropertyDescriptor propertyDescriptor) { + super(propertyDescriptor); + } + + + @Override + public Map mappings() { + return ((EnumeratedPropertyDescriptor) propertyDescriptor).mappings(); + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java new file mode 100644 index 0000000000..04c7aa7ac8 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java @@ -0,0 +1,34 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.wrappers; + +import java.util.List; + +import net.sourceforge.pmd.MultiValuePropertyDescriptor; + +/** + * @author Clément Fournier + */ +public class MultiValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper> + implements MultiValuePropertyDescriptor { + + public MultiValuePropertyDescriptorWrapper(MultiValuePropertyDescriptor propertyDescriptor) { + super(propertyDescriptor); + } + + + @Override + public Class type() { + return ((MultiValuePropertyDescriptor) propertyDescriptor).type(); + } + + + @Override + public char multiValueDelimiter() { + return ((MultiValuePropertyDescriptor) propertyDescriptor).multiValueDelimiter(); + } + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java similarity index 80% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java index 8a7b1e1e7b..e69b8daa32 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/factories/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java @@ -2,16 +2,14 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.factories; +package net.sourceforge.pmd.lang.rule.properties.wrappers; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorFactory; /** * This class serves as a wrapper class for a PropertyDescriptor instance. It @@ -24,7 +22,7 @@ import net.sourceforge.pmd.Rule; */ public class PropertyDescriptorWrapper implements PropertyDescriptor { - private final PropertyDescriptor propertyDescriptor; + protected final PropertyDescriptor propertyDescriptor; public PropertyDescriptorWrapper(PropertyDescriptor propertyDescriptor) { @@ -41,12 +39,6 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } - @Override - public Set> choices() { - return propertyDescriptor.choices(); - } - - @Override public int compareTo(PropertyDescriptor o) { return propertyDescriptor.compareTo(o); @@ -83,12 +75,6 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } - @Override - public char multiValueDelimiter() { - return propertyDescriptor.multiValueDelimiter(); - } - - @Override public String name() { return propertyDescriptor.name(); @@ -109,20 +95,8 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { @SuppressWarnings("unchecked") @Override - public Class type() { - Class clazz = propertyDescriptor.type(); - Class result = null; - try { - result = (Class) clazz; - } catch (ClassCastException e1) { - try { - result = (Class) List.class; - } catch (ClassCastException e2) { - - } - } - - return result; + public Class type() { + return propertyDescriptor.type(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java new file mode 100644 index 0000000000..c089f3c3cc --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java @@ -0,0 +1,25 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.wrappers; + +import net.sourceforge.pmd.SingleValuePropertyDescriptor; + +/** + * @author Clément Fournier + */ +public class SingleValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper + implements SingleValuePropertyDescriptor { + + public SingleValuePropertyDescriptorWrapper(SingleValuePropertyDescriptor propertyDescriptor) { + super(propertyDescriptor); + } + + + @Override + public Class type() { + return ((SingleValuePropertyDescriptor) propertyDescriptor).type(); + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 1c8910d03d..1dad391516 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -17,8 +17,8 @@ import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.StringProperty; +import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.xpath.Initializer; import net.sf.saxon.om.ValueRepresentation; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java index baf5861bc2..0147558f07 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java @@ -16,13 +16,14 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleViolation; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + /** * Renderer for Code Climate JSON format */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java index 12af712af6..bc323ddbda 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRule.java @@ -32,7 +32,7 @@ public interface CodeClimateRule extends Rule { "Security", "Style", }, new String[] { "Bug Risk", "Clarity", "Compatibility", "Complexity", "Duplication", "Performance", "Security", "Style", }, - new int[] { 7 }, 1.0f); + new int[] { 7 }, String.class, 1.0f); /** * Defines the remediation points for this rule. The remediation points are diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java index cd159f0dbc..4d4522e2a2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java @@ -865,7 +865,7 @@ public class Designer implements ClipboardOwner { private JPanel createXPathVersionPanel() { JPanel p = new JPanel(); p.add(new JLabel("XPath Version:")); - for (Entry values : XPathRule.VERSION_DESCRIPTOR.choices()) { + for (Entry values : XPathRule.VERSION_DESCRIPTOR.mappings().entrySet()) { JRadioButton b = new JRadioButton(); b.setText(values.getKey()); b.setActionCommand(b.getText()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 9a22269941..3623e0137b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -19,7 +19,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.junit.JavaUtilLoggingRule; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 2d93493d26..aa978f1b89 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -20,7 +20,7 @@ import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.lang.rule.properties.factories.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; /** * Base functionality for all concrete subclasses that evaluate type-specific diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java index 24bfad08fd..441700c39d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java @@ -6,8 +6,6 @@ package net.sourceforge.pmd.properties; import java.util.List; -import org.junit.Test; - import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.IntegerMultiProperty; import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; @@ -24,53 +22,59 @@ public class IntegerPropertyTest extends AbstractPropertyDescriptorTester createProperty() { return new IntegerProperty("testInteger", "Test integer property", MIN, MAX, MAX - 1, 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new IntegerMultiProperty("testInteger", "Test integer property", MIN, MAX, - new Integer[] { MIN, MIN + 1, MAX - 1, MAX }, 1.0f); + new Integer[] {MIN, MIN + 1, MAX - 1, MAX}, 1.0f); } + @Override protected PropertyDescriptor createBadProperty() { return new IntegerProperty("", "Test integer property", MIN, MAX, MAX + 1, 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { - return new IntegerMultiProperty("testInteger", "", MIN, MAX, new Integer[] { MIN - 1, MAX }, 1.0f) ; + return new IntegerMultiProperty("testInteger", "", MIN, MAX, new Integer[] {MIN - 1, MAX}, 1.0f); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java index 17d3fee01b..4ddaf0e5bb 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java @@ -31,11 +31,11 @@ import net.sourceforge.pmd.util.ClassUtil; */ public class MethodPropertyTest extends AbstractPropertyDescriptorTester { - private static final Method[] allMethods = String.class.getDeclaredMethods(); + private static final Method[] ALL_METHODS = String.class.getDeclaredMethods(); private static final String[] METHOD_SIGNATURES = {"String#indexOf(int)", "String#substring(int,int)", "java.lang.String#substring(int,int)", "Integer#parseInt(String)", "java.util.HashMap#put(Object,Object)", - "HashMap#containsKey(Object)",}; + "HashMap#containsKey(Object)", }; public MethodPropertyTest() { super("Method"); @@ -74,7 +74,7 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester @Override protected Method createValue() { - return randomChoice(allMethods); + return randomChoice(ALL_METHODS); } @Override @@ -84,24 +84,24 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester @Override protected PropertyDescriptor createProperty() { - return new MethodProperty("methodProperty", "asdf", allMethods[1], new String[] {"java.lang"}, 1.0f); + return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.lang"}, 1.0f); } @Override protected PropertyDescriptor> createMultiProperty() { - return new MethodMultiProperty("methodProperty", "asdf", new Method[] {allMethods[2], allMethods[3]}, + return new MethodMultiProperty("methodProperty", "asdf", new Method[] {ALL_METHODS[2], ALL_METHODS[3]}, new String[] {"java.lang"}, 1.0f); } @Override protected PropertyDescriptor createBadProperty() { - return new MethodProperty("methodProperty", "asdf", allMethods[1], new String[] {"java.util"}, 1.0f); + return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.util"}, 1.0f); } @Override protected PropertyDescriptor> createBadMultiProperty() { - return new MethodMultiProperty("methodProperty", "asdf", new Method[] {allMethods[2], allMethods[3]}, + return new MethodMultiProperty("methodProperty", "asdf", new Method[] {ALL_METHODS[2], ALL_METHODS[3]}, new String[] {"java.util"}, 1.0f); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java index 53d28f8b07..127eb80731 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java @@ -44,55 +44,48 @@ import net.sourceforge.pmd.util.ClassUtil; */ public class NonRuleWithAllPropertyTypes extends AbstractRule { - private static final Method STRING_LENGTH = ClassUtil.methodFor(String.class, "length", ClassUtil.EMPTY_CLASS_ARRAY); - private static final Method STRING_TO_LOWER_CASE = ClassUtil.methodFor(String.class, "toLowerCase", - ClassUtil.EMPTY_CLASS_ARRAY); - // descriptors are public to enable us to write external tests public static final StringProperty SINGLE_STR = new StringProperty("singleStr", "String value", "hello world", 3.0f); public static final StringMultiProperty MULTI_STR = new StringMultiProperty("multiStr", "Multiple string values", - new String[] { "hello", "world" }, 5.0f, '|'); - + new String[] {"hello", "world"}, 5.0f, '|'); public static final IntegerProperty SINGLE_INT = new IntegerProperty("singleInt", "Single integer value", 1, 10, 8, - 3.0f); + 3.0f); public static final IntegerMultiProperty MULTI_INT = new IntegerMultiProperty("multiInt", "Multiple integer values", - 0, 10, new Integer[] { 1, 2, 3, 4 }, 5.0f); - + 0, 10, new Integer[] {1, 2, 3, 4}, 5.0f); public static final LongProperty SINGLE_LONG = new LongProperty("singleLong", "Single long value", 1L, 10L, 8L, - 3.0f); + 3.0f); public static final LongMultiProperty MULTI_LONG = new LongMultiProperty("multiLong", "Multiple long values", 0L, - 10L, new Long[] { 1L, 2L, 3L, 4L }, 5.0f); - + 10L, new Long[] {1L, 2L, 3L, 4L}, 5.0f); public static final BooleanProperty SINGLE_BOOL = new BooleanProperty("singleBool", "Single boolean value", true, - 6.0f); + 6.0f); public static final BooleanMultiProperty MULTI_BOOL = new BooleanMultiProperty("multiBool", - "Multiple boolean values", new Boolean[] { true, false }, 5.0f); - + "Multiple boolean values", new Boolean[] {true, false}, 5.0f); public static final CharacterProperty SINGLE_CHAR = new CharacterProperty("singleChar", "Single character", 'a', - 5.0f); + 5.0f); public static final CharacterMultiProperty MULTI_CHAR = new CharacterMultiProperty("multiChar", - "Multiple characters", new Character[] { 'a', 'e', 'i', 'o', 'u' }, 6.0f, '|'); - + "Multiple characters", new Character[] {'a', 'e', 'i', 'o', 'u'}, 6.0f, '|'); public static final FloatProperty SINGLE_FLOAT = new FloatProperty("singleFloat", "Single float value", 9f, 10f, .9f, - 5.0f); + 5.0f); public static final FloatMultiProperty MULTI_FLOAT = new FloatMultiProperty("multiFloat", "Multiple float values", - 0f, 5f, new Float[] { 1f, 2f, 3f }, 6.0f); - + 0f, 5f, new Float[] {1f, 2f, 3f}, 6.0f); public static final TypeProperty SINGLE_TYPE = new TypeProperty("singleType", "Single type", String.class, - new String[] { "java.lang" }, 5.0f); + new String[] {"java.lang"}, 5.0f); public static final TypeMultiProperty MULTI_TYPE = new TypeMultiProperty("multiType", "Multiple types", - new Class[] { Integer.class, Object.class }, new String[] { "java.lang" }, 6.0f); - - public static final MethodProperty SINGLE_METHOD = new MethodProperty("singleMethod", "Single method", STRING_LENGTH, - new String[] { "java.lang" }, 5.0f); - public static final MethodMultiProperty MULTI_METHOD = new MethodMultiProperty("multiMethod", "Multiple methods", - new Method[] { STRING_LENGTH, STRING_TO_LOWER_CASE }, new String[] { "java.lang" }, 6.0f); - - public static final EnumeratedProperty ENUM_TYPE = new EnumeratedProperty<>("enumType", "Enumerated choices", - new String[] { "String", "Object" }, new Class[] { String.class, Object.class }, 1, 5.0f); + new Class[] {Integer.class, Object.class}, new String[] {"java.lang"}, 6.0f); + public static final EnumeratedProperty ENUM_TYPE = new EnumeratedProperty<>("enumType", + "Enumerated choices", + new String[] {"String", "Object"}, new Class[] {String.class, Object.class}, 1, Class.class, 5.0f); public static final EnumeratedMultiProperty MULTI_ENUM_TYPE = new EnumeratedMultiProperty<>("multiEnumType", - "Multiple enumerated choices", new String[] { "String", "Object" }, - new Class[] { String.class, Object.class }, new int[] { 0, 1 }, 5.0f); + "Multiple enumerated choices", new String[] {"String", "Object"}, + new Class[] {String.class, Object.class}, new int[] {0, 1}, Class.class, 5.0f); + private static final Method STRING_LENGTH = ClassUtil.methodFor(String.class, "length", ClassUtil.EMPTY_CLASS_ARRAY); + public static final MethodProperty SINGLE_METHOD = new MethodProperty("singleMethod", "Single method", STRING_LENGTH, + new String[] {"java.lang"}, 5.0f); + private static final Method STRING_TO_LOWER_CASE = ClassUtil.methodFor(String.class, "toLowerCase", + ClassUtil.EMPTY_CLASS_ARRAY); + public static final MethodMultiProperty MULTI_METHOD = new MethodMultiProperty("multiMethod", "Multiple methods", + new Method[] {STRING_LENGTH, STRING_TO_LOWER_CASE}, new String[] {"java.lang"}, 6.0f); + public NonRuleWithAllPropertyTypes() { super(); @@ -116,6 +109,7 @@ public class NonRuleWithAllPropertyTypes extends AbstractRule { definePropertyDescriptor(MULTI_ENUM_TYPE); } + @Override public void apply(List nodes, RuleContext ctx) { } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index 9d60e20064..eee817b468 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -23,7 +23,7 @@ import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; */ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTester { - private static final String[] KEYS = {"bar", "na", "bee", "coo",}; + private static final String[] KEYS = {"bar", "na", "bee", "coo"}; private static final Foo[] VALUES = Foo.values(); @@ -50,7 +50,7 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest "Test enumerations with complex types", KEYS, VALUES, - new int[] {0, 1}, 1.0f); + new int[] {0, 1}, Foo.class, 1.0f); } @@ -59,7 +59,7 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest return new EnumeratedProperty<>("testEnumerations", "Test enumerations with complex types", KEYS, - VALUES, 0, + VALUES, 0, Foo.class, 1.0f); } @@ -67,14 +67,14 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest @Override protected PropertyDescriptor createBadProperty() { return new EnumeratedProperty<>("testEnumerations", "Test enumerations with simple type", - new String[0], VALUES, -1, 1.0f); + new String[0], VALUES, -1, Foo.class, 1.0f); } @Override protected PropertyDescriptor> createBadMultiProperty() { return new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with simple type", - KEYS, VALUES, new int[] {99}, 1.0f); + KEYS, VALUES, new int[] {99}, Foo.class, 1.0f); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java index d2ddf8ac69..bf7fa53430 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java @@ -29,9 +29,9 @@ import net.sourceforge.pmd.lang.rule.properties.TypeProperty; public class TypePropertyTest extends AbstractPropertyDescriptorTester { private static final Class[] JAVA_LANG_CLASSES = {String.class, Integer.class, Thread.class, - Object.class, Runtime.class,}; + Object.class, Runtime.class, }; private static final Class[] JAVA_UTIL_CLASSES = {HashMap.class, Map.class, Comparator.class, Set.class, - Observer.class,}; + Observer.class, }; public TypePropertyTest() { super("Class"); From b103d8f01188670d95d407cc682a65bee5d812d0 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 28 Jun 2017 17:48:11 +0200 Subject: [PATCH 13/53] Specialised BasicPropertyDescriptorFactory --- .../apexunit/AbstractApexUnitTestRule.java | 4 +- .../complexity/AbstractNcssCountRule.java | 4 +- .../AvoidDeeplyNestedIfStmtsRule.java | 4 +- .../complexity/ExcessiveClassLengthRule.java | 4 +- .../ExcessiveParameterListRule.java | 4 +- .../complexity/ExcessivePublicCountRule.java | 4 +- .../complexity/NcssConstructorCountRule.java | 4 +- .../rule/complexity/NcssMethodCountRule.java | 4 +- .../rule/complexity/NcssTypeCountRule.java | 4 +- .../StdCyclomaticComplexityRule.java | 3 +- .../rule/complexity/TooManyFieldsRule.java | 3 +- .../AvoidDmlStatementsInLoopsRule.java | 4 +- .../performance/AvoidSoqlInLoopsRule.java | 4 +- .../apex/rule/security/ApexBadCryptoRule.java | 3 +- .../rule/security/ApexCRUDViolationRule.java | 2 +- .../lang/apex/rule/security/ApexCSRFRule.java | 4 +- .../security/ApexDangerousMethodsRule.java | 3 +- .../security/ApexInsecureEndpointRule.java | 3 +- .../rule/security/ApexOpenRedirectRule.java | 3 +- .../rule/security/ApexSOQLInjectionRule.java | 3 +- .../security/ApexSharingViolationsRule.java | 3 +- .../ApexSuggestUsingNamedCredRule.java | 3 +- .../security/ApexXSSFromEscapeFalseRule.java | 3 +- .../security/ApexXSSFromURLParamRule.java | 3 +- .../rule/style/AvoidGlobalModifierRule.java | 4 +- .../rule/style/AvoidLogicInTriggerRule.java | 3 +- .../style/ClassNamingConventionsRule.java | 4 +- .../style/MethodNamingConventionsRule.java | 4 +- ...ethodWithSameNameAsEnclosingClassRule.java | 3 +- .../style/VariableNamingConventionsRule.java | 46 ++++++------ .../pmd/PropertyDescriptorFactory.java | 3 + .../net/sourceforge/pmd/RuleSetWriter.java | 34 +++------ .../BasicPropertyDescriptorFactory.java | 2 +- .../rule/properties/BooleanMultiProperty.java | 4 +- .../lang/rule/properties/BooleanProperty.java | 4 +- .../properties/CharacterMultiProperty.java | 4 +- .../rule/properties/CharacterProperty.java | 4 +- .../rule/properties/DoubleMultiProperty.java | 4 +- .../lang/rule/properties/DoubleProperty.java | 4 +- .../properties/EnumeratedMultiProperty.java | 9 ++- .../rule/properties/EnumeratedProperty.java | 2 +- .../lang/rule/properties/FileProperty.java | 13 ++-- .../rule/properties/FloatMultiProperty.java | 4 +- .../lang/rule/properties/FloatProperty.java | 4 +- .../rule/properties/IntegerMultiProperty.java | 4 +- .../lang/rule/properties/IntegerProperty.java | 4 +- .../rule/properties/LongMultiProperty.java | 4 +- .../lang/rule/properties/LongProperty.java | 4 +- .../rule/properties/MethodMultiProperty.java | 4 +- .../lang/rule/properties/MethodProperty.java | 4 +- .../MultiValuePropertyDescriptorFactory.java | 32 +++++++++ .../properties/PropertyDescriptorUtil.java | 4 +- .../SingleValuePropertyDescriptorFactory.java | 31 ++++++++ .../rule/properties/StringMultiProperty.java | 4 +- .../lang/rule/properties/StringProperty.java | 13 ++-- .../rule/properties/TypeMultiProperty.java | 4 +- .../lang/rule/properties/TypeProperty.java | 5 +- .../pmd/properties/IntegerPropertyTest.java | 2 +- .../oom/rule/CyclomaticComplexityRule.java | 17 +++-- ...oidBranchingStatementAsLastInLoopRule.java | 71 +++++++++++-------- .../rule/basic/AvoidUsingHardCodedIPRule.java | 4 +- .../rule/comments/CommentContentRule.java | 29 ++++---- .../rule/comments/CommentRequiredRule.java | 18 ++--- .../rule/comments/HeaderCommentsRule.java | 2 +- .../coupling/LoosePackageCouplingRule.java | 7 +- .../java/rule/design/CloseResourceRule.java | 5 +- .../rule/design/GenericClassCounterRule.java | 13 +--- .../GuardLogStatementJavaUtilRule.java | 4 +- .../rule/logging/GuardLogStatementRule.java | 5 +- .../naming/VariableNamingConventionsRule.java | 45 ++++++------ .../ecmascript/EcmascriptParserOptions.java | 21 +++--- .../EcmascriptParserOptionsTest.java | 9 +-- .../pmd/AbstractRuleSetFactoryTest.java | 5 +- 73 files changed, 361 insertions(+), 255 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java index 5902df2768..d4bb22d466 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.apexunit; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; @@ -19,7 +21,7 @@ import apex.jorje.services.Version; public abstract class AbstractApexUnitTestRule extends AbstractApexRule { public AbstractApexUnitTestRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Bug Risk" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Bug Risk")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java index c2bdf71f42..9f6b69386c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.apex.ast.ASTContinueStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement; @@ -43,7 +45,7 @@ public abstract class AbstractNcssCountRule extends AbstractStatisticalApexRule this.nodeClass = nodeClass; setProperty(MINIMUM_DESCRIPTOR, 1000d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java index 9e3d56aab6..758080f9d3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; @@ -20,7 +22,7 @@ public class AvoidDeeplyNestedIfStmtsRule extends AbstractApexRule { public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); // Note: Remedy needs better OO design and therefore high effort setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java index 967ee88d8e..c4addbf62d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.AnnotationTypeInfos.IS_TEST; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; /** @@ -17,7 +19,7 @@ public class ExcessiveClassLengthRule extends ExcessiveLengthRule { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 1000d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java index 33d7f426db..192cea0aeb 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.util.NumericConstants; @@ -17,7 +19,7 @@ public class ExcessiveParameterListRule extends ExcessiveNodeCountRule { public ExcessiveParameterListRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 4d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java index 0e1ba3ff10..5f0406bf78 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java @@ -7,6 +7,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.PUBLIC; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclarationStatements; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -31,7 +33,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule { public ExcessivePublicCountRule() { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 20d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java index 9ed2f50619..9536f5729b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.stat.DataPoint; import net.sourceforge.pmd.util.NumericConstants; @@ -21,7 +23,7 @@ public class NcssConstructorCountRule extends AbstractNcssCountRule { public NcssConstructorCountRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 20d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java index dca48fea62..b0606c53ef 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.stat.DataPoint; import net.sourceforge.pmd.util.NumericConstants; @@ -21,7 +23,7 @@ public class NcssMethodCountRule extends AbstractNcssCountRule { public NcssMethodCountRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 40d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java index b6bf892da8..671d6df53e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -26,7 +28,7 @@ public class NcssTypeCountRule extends AbstractNcssCountRule { public NcssTypeCountRule() { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 500d); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 250); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java index f718e5aa33..9428990be3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; +import java.util.Arrays; import java.util.Stack; import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; @@ -78,7 +79,7 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule { definePropertyDescriptor(SHOW_CLASSES_COMPLEXITY_DESCRIPTOR); definePropertyDescriptor(SHOW_METHODS_COMPLEXITY_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 250); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java index 34b8350192..fa5fca8883 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,7 +32,7 @@ public class TooManyFieldsRule extends AbstractApexRule { public TooManyFieldsRule() { definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java index a6a08a81e4..cdeaf0ef25 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.performance; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlInsertStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlMergeStatement; @@ -21,7 +23,7 @@ import net.sourceforge.pmd.lang.ast.Node; public class AvoidDmlStatementsInLoopsRule extends AbstractApexRule { public AvoidDmlStatementsInLoopsRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Performance" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Performance")); // Note: Often more complicated as just moving the SOQL a few lines. // Involves Maps... setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java index f974cd15e1..345bcae677 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.performance; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement; import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement; import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement; @@ -16,7 +18,7 @@ import net.sourceforge.pmd.lang.ast.Node; public class AvoidSoqlInLoopsRule extends AbstractApexRule { public AvoidSoqlInLoopsRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Performance" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Performance")); // Note: Often more complicated as just moving the SOQL a few lines. // Involves Maps... setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java index ec78cd699e..deffa03d2d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -34,7 +35,7 @@ public class ApexBadCryptoRule extends AbstractApexRule { private final Set potentiallyStaticBlob = new HashSet<>(); public ApexBadCryptoRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index 654bb5bbdf..c715e5db57 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -90,7 +90,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private static final String[] RESERVED_KEYS_FLS = new String[] { "Schema", S_OBJECT_TYPE, }; public ApexCRUDViolationRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java index 7f9641c926..7c55adf594 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; @@ -20,7 +22,7 @@ public class ApexCSRFRule extends AbstractApexRule { public static final String INIT = "init"; public ApexCSRFRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java index 54fd0b4ddf..d80b21de92 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.regex.Pattern; @@ -39,7 +40,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { public ApexDangerousMethodsRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java index 8366c40a7a..b8819f35e2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -32,7 +33,7 @@ public class ApexInsecureEndpointRule extends AbstractApexRule { private final Set httpEndpointStrings = new HashSet<>(); public ApexInsecureEndpointRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java index ac4b3b188e..0c23b3a7f4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; import java.lang.reflect.Field; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -37,7 +38,7 @@ public class ApexOpenRedirectRule extends AbstractApexRule { public ApexOpenRedirectRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java index 5b372fa7f5..01365fa4e2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -49,7 +50,7 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { private final HashMap selectContainingVariables = new HashMap<>(); public ApexSOQLInjectionRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java index 7359e26dde..c2ff1787db 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.List; import java.util.WeakHashMap; @@ -26,7 +27,7 @@ public class ApexSharingViolationsRule extends AbstractApexRule { private WeakHashMap, Object> localCacheOfReportedNodes = new WeakHashMap<>(); public ApexSharingViolationsRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java index a256a4d2da..c8124e8f37 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -34,7 +35,7 @@ public class ApexSuggestUsingNamedCredRule extends AbstractApexRule { public ApexSuggestUsingNamedCredRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java index 53dff5bc6b..748d97e552 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTLiteralExpression; @@ -22,7 +23,7 @@ public class ApexXSSFromEscapeFalseRule extends AbstractApexRule { private static final String ADD_ERROR = "addError"; public ApexXSSFromEscapeFalseRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java index 1cb85f11d1..e96dc6b1a7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.security; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -50,7 +51,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { private final Set urlParameterStrings = new HashSet<>(); public ApexXSSFromURLParamRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Security" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java index 9b55610caa..742a8c140a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.GLOBAL; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; @@ -15,7 +17,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class AvoidGlobalModifierRule extends AbstractApexRule { public AvoidGlobalModifierRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java index 02b819e624..f6d871acbf 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.style; +import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement; @@ -13,7 +14,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class AvoidLogicInTriggerRule extends AbstractApexRule { public AvoidLogicInTriggerRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java index 15895262be..6d9554559b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.rule.style; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; @@ -11,7 +13,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class ClassNamingConventionsRule extends AbstractApexRule { public ClassNamingConventionsRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 5); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java index 08b78c6b3d..301d5be2c9 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.OVERRIDE; +import java.util.Arrays; + import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTProperty; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -14,7 +16,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class MethodNamingConventionsRule extends AbstractApexRule { public MethodNamingConventionsRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 1); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java index ea0544d0c2..177299ac01 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.apex.rule.style; +import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; @@ -13,7 +14,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class MethodWithSameNameAsEnclosingClassRule extends AbstractApexRule { public MethodWithSameNameAsEnclosingClassRule() { - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java index 4efeebaa67..911f288bb9 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java @@ -7,6 +7,9 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; +import java.util.Arrays; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.apex.ast.ASTField; import net.sourceforge.pmd.lang.apex.ast.ASTParameter; @@ -17,21 +20,20 @@ import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.util.CollectionUtil; public class VariableNamingConventionsRule extends AbstractApexRule { private boolean checkMembers; private boolean checkLocals; private boolean checkParameters; - private String[] staticPrefixes; - private String[] staticSuffixes; - private String[] memberPrefixes; - private String[] memberSuffixes; - private String[] localPrefixes; - private String[] localSuffixes; - private String[] parameterPrefixes; - private String[] parameterSuffixes; + private List staticPrefixes; + private List staticSuffixes; + private List memberPrefixes; + private List memberSuffixes; + private List localPrefixes; + private List localSuffixes; + private List parameterPrefixes; + private List parameterSuffixes; private static final BooleanProperty CHECK_MEMBERS_DESCRIPTOR = new BooleanProperty("checkMembers", "Check member variables", true, 1.0f); @@ -79,7 +81,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { definePropertyDescriptor(PARAMETER_PREFIXES_DESCRIPTOR); definePropertyDescriptor(PARAMETER_SUFFIXES_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, new String[] { "Style" }); + setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 5); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); @@ -139,7 +141,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { return checkName(parameterPrefixes, parameterSuffixes, node, false, isFinal, data); } - private Object checkName(String[] prefixes, String[] suffixes, ApexNode node, boolean isStatic, boolean isFinal, + private Object checkName(List prefixes, List suffixes, ApexNode node, boolean isStatic, boolean isFinal, Object data) { String varName = node.getImage(); @@ -174,15 +176,15 @@ public class VariableNamingConventionsRule extends AbstractApexRule { return data; } - private String normalizeVariableName(String varName, String[] prefixes, String[] suffixes) { + private String normalizeVariableName(String varName, List prefixes, List suffixes) { return stripSuffix(stripPrefix(varName, prefixes), suffixes); } - private String stripSuffix(String varName, String[] suffixes) { + private String stripSuffix(String varName, List suffixes) { if (suffixes != null) { - for (int i = 0; i < suffixes.length; i++) { - if (varName.endsWith(suffixes[i])) { - varName = varName.substring(0, varName.length() - suffixes[i].length()); + for (String suffix : suffixes) { + if (varName.endsWith(suffix)) { + varName = varName.substring(0, varName.length() - suffix.length()); break; } } @@ -190,11 +192,11 @@ public class VariableNamingConventionsRule extends AbstractApexRule { return varName; } - private String stripPrefix(String varName, String[] prefixes) { + private String stripPrefix(String varName, List prefixes) { if (prefixes != null) { - for (int i = 0; i < prefixes.length; i++) { - if (varName.startsWith(prefixes[i])) { - return varName.substring(prefixes[i].length()); + for (String prefix : prefixes) { + if (varName.startsWith(prefix)) { + return varName.substring(prefix.length()); } } } @@ -205,8 +207,8 @@ public class VariableNamingConventionsRule extends AbstractApexRule { for (PropertyDescriptor desc : getPropertyDescriptors()) { if (desc instanceof StringMultiProperty) { - String[] values = getProperty((StringMultiProperty) desc); - if (CollectionUtil.isNotEmpty(values)) { + List values = getProperty((StringMultiProperty) desc); + if (!values.isEmpty()) { return true; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index f2d66cc9fa..cbb1b4fd2e 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -9,6 +9,7 @@ import java.util.Map; /** * A factory to create {@link PropertyDescriptor}s based on a map of values. * + * @param the type of values property descriptor returned by this factory. This can be a list. * @author Brian Remedios */ public interface PropertyDescriptorFactory { @@ -21,6 +22,8 @@ public interface PropertyDescriptorFactory { */ Class valueType(); + boolean isMultiValue(); + /** * Denote the identifiers of the expected fields paired with booleans * denoting whether they are required (non-null) or not. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index edf7068713..47dbf5da56 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -265,21 +265,11 @@ public class RuleSetWriter { Element propertiesElement = null; if (propertyDescriptors != null) { - for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { // For - // each - // provided - // PropertyDescriptor + for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { + // For each provided PropertyDescriptor - if (propertyDescriptor instanceof PropertyDescriptorWrapper) { // Any - // wrapper - // property - // needs - // to - // go - // out - // as - // a - // definition. + if (propertyDescriptor instanceof PropertyDescriptorWrapper) { + // Any wrapper property needs to go out as a definition. if (propertiesElement == null) { propertiesElement = createPropertiesElement(); } @@ -288,17 +278,8 @@ public class RuleSetWriter { ((PropertyDescriptorWrapper) propertyDescriptor).getPropertyDescriptor()); propertiesElement.appendChild(propertyElement); } else { - if (propertiesByPropertyDescriptor != null) { // Otherwise, - // any - // property - // which has a - // value - // different - // than the - // default - // needs to go - // out as a - // value. + if (propertiesByPropertyDescriptor != null) { + // Otherwise, any property which has a value different than the default needs to go out as a value. Object defaultValue = propertyDescriptor.defaultValue(); Object value = propertiesByPropertyDescriptor.get(propertyDescriptor); if (value != defaultValue && (value == null || !value.equals(defaultValue))) { @@ -385,7 +366,8 @@ public class RuleSetWriter { final Element propertyElement = createPropertyValueElement(propertyDescriptor, propertyDescriptor.defaultValue()); propertyElement.setAttribute(PropertyDescriptorField.TYPE.attributeName, - PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type())); + PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type(), + propertyDescriptor.isMultiValue())); Map propertyValuesById = propertyDescriptor.attributeValuesById(); for (Map.Entry entry : propertyValuesById.entrySet()) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java index c6973ecd31..e6c5889d02 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java @@ -31,7 +31,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { +public abstract class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESCRIPTION, DEFAULT_VALUE, DELIMITER}, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index aa32bcfd71..3fc5e35d07 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -21,8 +21,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class BooleanMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Boolean.class) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Boolean.class) { @Override public BooleanMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 5989a82d46..294d383fd4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -19,8 +19,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class BooleanProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Boolean.class) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Boolean.class) { @Override public BooleanProperty createWith(Map valuesById) { return new BooleanProperty(nameIn(valuesById), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 61c30b8e7b..811f3352fd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -22,8 +22,8 @@ import net.sourceforge.pmd.util.StringUtil; public final class CharacterMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Character.class) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Character.class) { @Override public CharacterMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 8659b1741a..43af6603a8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -19,8 +19,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class CharacterProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Character.class) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Character.class) { @Override public CharacterProperty createWith(Map valuesById) { return new CharacterProperty(nameIn(valuesById), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index b6618737b5..7d4e90815a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -23,8 +23,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class DoubleMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 81844bacff..2b3f1da8ae 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -20,8 +20,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class DoubleProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index 4f84de0ae8..c0a62ce3f4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; import java.util.Collections; -import java.util.Enumeration; import java.util.List; import java.util.Map; @@ -14,6 +13,7 @@ import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.CollectionUtil; +import net.sourceforge.pmd.util.StringUtil; /** * Multi-valued property which can take only a fixed set of values of any type, then selected via String labels. The @@ -28,8 +28,8 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty implements EnumeratedPropertyDescriptor> { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Enumeration.class) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Object.class) { // TODO:cf is Object the right type? @Override public EnumeratedMultiProperty createWith(Map valuesById) { return new EnumeratedMultiProperty<>(nameIn(valuesById), @@ -142,6 +142,9 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty private E choiceFrom(String label) { + if (StringUtil.isEmpty(label)) { + return null; + } E result = choicesByLabel.get(label); if (result == null) { throw new IllegalArgumentException(label); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 113159bd8d..96a3ee6a22 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -29,7 +29,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Enumeration.class) { + = new SingleValuePropertyDescriptorFactory(Enumeration.class) { // TODO:cf Enumeration? Object? @Override public EnumeratedProperty createWith(Map valuesById) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index 4458d7cf31..bfed9815e1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -20,12 +20,13 @@ import net.sourceforge.pmd.util.StringUtil; public final class FileProperty extends AbstractSingleValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(File.class) { - @Override - public FileProperty createWith(Map valuesById) { - return new FileProperty(nameIn(valuesById), descriptionIn(valuesById), null, 0f); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(File.class) { + @Override + public FileProperty createWith(Map valuesById) { + return new FileProperty(nameIn(valuesById), descriptionIn(valuesById), null, 0f); + } + }; // @formatter:on public FileProperty(String theName, String theDescription, File theDefault, float theUIOrder) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index caaf38d3d5..99382bd738 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -23,8 +23,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class FloatMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public FloatMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 4689776e9c..5db204c0d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -20,8 +20,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class FloatProperty extends AbstractNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public FloatProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 32965e1a31..51f02f1588 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -23,8 +23,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class IntegerMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index e0f7a74929..5658f289aa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -19,8 +19,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class IntegerProperty extends AbstractNumericProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public IntegerProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 642603239a..12f7616385 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -23,8 +23,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class LongMultiProperty extends AbstractMultiNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public LongMultiProperty createWith(Map valuesById) { String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index c94d3c5062..7fbbe87581 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -20,8 +20,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class LongProperty extends AbstractNumericProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public LongProperty createWith(Map valuesById) { final String[] minMax = minMaxFrom(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index e3763d07a9..747c7ccf6c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -28,8 +28,8 @@ import net.sourceforge.pmd.util.StringUtil; public final class MethodMultiProperty extends AbstractMultiPackagedProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index e9f48afa0d..797e3922a2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -30,8 +30,8 @@ public final class MethodProperty extends AbstractPackagedProperty { public static final char CLASS_METHOD_DELIMITER = '#'; public static final char METHOD_ARG_DELIMITER = ','; public static final char[] METHOD_GROUP_DELIMITERS = {'(', ')'}; - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java new file mode 100644 index 0000000000..f935a65331 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java @@ -0,0 +1,32 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.PropertyDescriptorField; + +/** + * @author Clément Fournier + */ +public class MultiValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory> { + + public MultiValuePropertyDescriptorFactory(Class theValueType) { + super(theValueType); + } + + + public MultiValuePropertyDescriptorFactory(Class theValueType, Map + additionalFieldTypesByKey) { + super(theValueType, additionalFieldTypesByKey); + } + + + @Override + public boolean isMultiValue() { + return true; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index dfc41101ed..7cad68b59f 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -69,11 +69,11 @@ public class PropertyDescriptorUtil { } - public static String typeIdFor(Class valueType) { + public static String typeIdFor(Class valueType, boolean multiValue) { // a reverse lookup, not very efficient but fine for now for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { - if (entry.getValue().valueType() == valueType) { + if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) { return entry.getKey(); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java new file mode 100644 index 0000000000..2fa5c8c955 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java @@ -0,0 +1,31 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.Map; + +import net.sourceforge.pmd.PropertyDescriptorField; + +/** + * @author Clément Fournier + */ +public class SingleValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory { + + public SingleValuePropertyDescriptorFactory(Class theValueType) { + super(theValueType); + } + + + public SingleValuePropertyDescriptorFactory(Class theValueType, + Map additionalFieldTypesByKey) { + super(theValueType, additionalFieldTypesByKey); + } + + + @Override + public boolean isMultiValue() { + return false; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 2bc1997746..4030eae324 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -22,8 +22,8 @@ import net.sourceforge.pmd.util.StringUtil; public final class StringMultiProperty extends AbstractMultiValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(String.class) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(String.class) { @Override public StringMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 262fdf110a..83f8426b94 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -18,12 +18,13 @@ import net.sourceforge.pmd.PropertyDescriptorField; public final class StringProperty extends AbstractSingleValueProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(String.class) { - @Override - public StringProperty createWith(Map valuesById) { - return new StringProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), 0f); - } - }; + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(String.class) { + @Override + public StringProperty createWith(Map valuesById) { + return new StringProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), 0f); + } + }; // @formatter:on /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 142a38b18e..766b08f56f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -24,8 +24,8 @@ import net.sourceforge.pmd.util.StringUtil; public final class TypeMultiProperty extends AbstractMultiPackagedProperty { /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory>(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { + public static final PropertyDescriptorFactory> FACTORY // @formatter:off + = new MultiValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public TypeMultiProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index 2144c60342..d7ae7d3a56 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -21,8 +21,9 @@ import net.sourceforge.pmd.util.StringUtil; */ public final class TypeProperty extends AbstractPackagedProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new BasicPropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { + /** Factory. */ + public static final PropertyDescriptorFactory FACTORY // @formatter:off + = new SingleValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public TypeProperty createWith(Map valuesById) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java index 441700c39d..b8c644f6da 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java @@ -49,7 +49,7 @@ public class IntegerPropertyTest extends AbstractPropertyDescriptorTester VERSION_MAP; - private static final MetricVersion[] CYCLO_VERSIONS = {Metric.Version.STANDARD, CycloMetric.Version.IGNORE_BOOLEAN_PATHS}; + static { + VERSION_MAP = new HashMap<>(); + VERSION_MAP.put("standard", Version.STANDARD); + VERSION_MAP.put("ignoreBooleanPaths", CycloMetric.Version.IGNORE_BOOLEAN_PATHS); + } public static final EnumeratedProperty CYCLO_VERSION_DESCRIPTOR = new EnumeratedProperty<>( "cycloVersion", "Choose a variant of Cyclo or the standard", - VERSION_LABELS, CYCLO_VERSIONS, 0, 3.0f); + VERSION_MAP, Version.STANDARD, MetricVersion.class, 3.0f); private int reportLevel; private boolean showClassesComplexity = true; @@ -65,8 +71,7 @@ public class CyclomaticComplexityRule extends AbstractJavaRule { reportLevel = getProperty(REPORT_LEVEL_DESCRIPTOR); showClassesComplexity = getProperty(SHOW_CLASSES_COMPLEXITY_DESCRIPTOR); showMethodsComplexity = getProperty(SHOW_METHODS_COMPLEXITY_DESCRIPTOR); - Object version = getProperty(CYCLO_VERSION_DESCRIPTOR); - cycloVersion = version instanceof MetricVersion ? (MetricVersion) version : Version.STANDARD; + cycloVersion = getProperty(CYCLO_VERSION_DESCRIPTOR); super.visit(node, data); return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidBranchingStatementAsLastInLoopRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidBranchingStatementAsLastInLoopRule.java index 008195c95c..d405c61d08 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidBranchingStatementAsLastInLoopRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidBranchingStatementAsLastInLoopRule.java @@ -4,6 +4,12 @@ package net.sourceforge.pmd.lang.java.rule.basic; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import net.sourceforge.pmd.PropertySource; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; @@ -22,19 +28,27 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { public static final String CHECK_DO = "do"; public static final String CHECK_WHILE = "while"; - private static final String[] ALL_LOOP_TYPES_LABELS = new String[] { CHECK_FOR, CHECK_DO, CHECK_WHILE }; - private static final String[] ALL_LOOP_TYPES_VALUES = ALL_LOOP_TYPES_LABELS; - private static final int[] ALL_LOOP_TYPES_DEFAULTS = new int[] { 0, 1, 2 }; + private static final Map LOOP_TYPES_MAPPINGS; + private static final List DEFAULTS = Arrays.asList(CHECK_FOR, CHECK_DO, CHECK_WHILE); + + static { + Map mappings = new HashMap<>(); + mappings.put(CHECK_FOR, CHECK_FOR); + mappings.put(CHECK_DO, CHECK_DO); + mappings.put(CHECK_WHILE, CHECK_WHILE); + LOOP_TYPES_MAPPINGS = Collections.unmodifiableMap(mappings); + } public static final EnumeratedMultiProperty CHECK_BREAK_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkBreakLoopTypes", "Check for break statements in loop types", ALL_LOOP_TYPES_LABELS, - ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 1); + "checkBreakLoopTypes", "Check for break statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, + String.class, 1); public static final EnumeratedMultiProperty CHECK_CONTINUE_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkContinueLoopTypes", "Check for continue statements in loop types", ALL_LOOP_TYPES_LABELS, - ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 2); + "checkContinueLoopTypes", "Check for continue statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, + String.class, 2); public static final EnumeratedMultiProperty CHECK_RETURN_LOOP_TYPES = new EnumeratedMultiProperty<>( - "checkReturnLoopTypes", "Check for return statements in loop types", ALL_LOOP_TYPES_LABELS, - ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 3); + "checkReturnLoopTypes", "Check for return statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS, + String.class, 3); + public AvoidBranchingStatementAsLastInLoopRule() { definePropertyDescriptor(CHECK_BREAK_LOOP_TYPES); @@ -46,6 +60,7 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { addRuleChainVisit(ASTReturnStatement.class); } + @Override public Object visit(ASTBreakStatement node, Object data) { // skip breaks, that are within a switch statement @@ -55,15 +70,6 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { return check(CHECK_BREAK_LOOP_TYPES, node, data); } - @Override - public Object visit(ASTContinueStatement node, Object data) { - return check(CHECK_CONTINUE_LOOP_TYPES, node, data); - } - - @Override - public Object visit(ASTReturnStatement node, Object data) { - return check(CHECK_RETURN_LOOP_TYPES, node, data); - } protected Object check(EnumeratedMultiProperty property, Node node, Object data) { Node parent = node.getNthParent(5); @@ -83,22 +89,24 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { return data; } + protected boolean hasPropertyValue(EnumeratedMultiProperty property, String value) { - final Object[] values = getProperty(property); - for (int i = 0; i < values.length; i++) { - if (value.equals(values[i])) { - return true; - } - } - return false; + return getProperty(property).contains(value); } - public boolean checksNothing() { - return getProperty(CHECK_BREAK_LOOP_TYPES).length == 0 && getProperty(CHECK_CONTINUE_LOOP_TYPES).length == 0 - && getProperty(CHECK_RETURN_LOOP_TYPES).length == 0; + @Override + public Object visit(ASTContinueStatement node, Object data) { + return check(CHECK_CONTINUE_LOOP_TYPES, node, data); } + + @Override + public Object visit(ASTReturnStatement node, Object data) { + return check(CHECK_RETURN_LOOP_TYPES, node, data); + } + + /** * @see PropertySource#dysfunctionReason() */ @@ -106,4 +114,11 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule { public String dysfunctionReason() { return checksNothing() ? "All loop types are ignored" : null; } + + + public boolean checksNothing() { + + return getProperty(CHECK_BREAK_LOOP_TYPES).size() == 0 && getProperty(CHECK_CONTINUE_LOOP_TYPES).size() == 0 + && getProperty(CHECK_RETURN_LOOP_TYPES).size() == 0; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingHardCodedIPRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingHardCodedIPRule.java index 281f9c374c..735c9220a3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingHardCodedIPRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingHardCodedIPRule.java @@ -21,7 +21,7 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule { public static final EnumeratedMultiProperty CHECK_ADDRESS_TYPES_DESCRIPTOR = new EnumeratedMultiProperty<>( "checkAddressTypes", "Check for IP address types.", new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 }, - new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 }, new int[] { 0, 1, 2 }, 2.0f); + new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 }, new int[] { 0, 1, 2 }, String.class, 2.0f); // Provides 4 capture groups that can be used for additional validation protected static final String IPV4_REGEXP = "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})"; @@ -195,7 +195,7 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule { } public boolean hasChosenAddressTypes() { - return getProperty(CHECK_ADDRESS_TYPES_DESCRIPTOR).length > 0; + return getProperty(CHECK_ADDRESS_TYPES_DESCRIPTOR).size() > 0; } /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentContentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentContentRule.java index a788d6926e..85c34ae537 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentContentRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentContentRule.java @@ -18,7 +18,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.Comment; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** @@ -32,11 +31,11 @@ public class CommentContentRule extends AbstractCommentRule { private boolean caseSensitive; private boolean wordsAreRegex; - private String[] originalBadWords; - private String[] currentBadWords; + private List originalBadWords; + private List currentBadWords; // FIXME need some better defaults (or none?) - private static final String[] BAD_WORDS = new String[] { "idiot", "jerk" }; + private static final String[] BAD_WORDS = {"idiot", "jerk" }; public static final BooleanProperty WORDS_ARE_REGEX_DESCRIPTOR = new BooleanProperty("wordsAreRegex", "Use regular expressions", false, 1.0f); @@ -72,19 +71,21 @@ public class CommentContentRule extends AbstractCommentRule { if (caseSensitive) { currentBadWords = originalBadWords; } else { - currentBadWords = new String[originalBadWords.length]; - for (int i = 0; i < currentBadWords.length; i++) { - currentBadWords[i] = originalBadWords[i].toUpperCase(); + currentBadWords = new ArrayList<>(); + for (String badWord : originalBadWords) { + currentBadWords.add(badWord.toUpperCase()); } } } @Override public Set> ignoredProperties() { - return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ? NON_REGEX_PROPERTIES : Collections.EMPTY_SET; + return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ? NON_REGEX_PROPERTIES + : Collections.>emptySet(); } /** + * . * @see Rule#end(RuleContext) */ @Override @@ -94,7 +95,7 @@ public class CommentContentRule extends AbstractCommentRule { private List illegalTermsIn(Comment comment) { - if (currentBadWords.length == 0) { + if (currentBadWords.isEmpty()) { return Collections.emptyList(); } @@ -109,9 +110,9 @@ public class CommentContentRule extends AbstractCommentRule { List foundWords = new ArrayList<>(); - for (int i = 0; i < currentBadWords.length; i++) { - if (commentText.indexOf(currentBadWords[i]) >= 0) { - foundWords.add(originalBadWords[i]); + for (int i = 0; i < currentBadWords.size(); i++) { + if (commentText.contains(currentBadWords.get(i))) { + foundWords.add(originalBadWords.get(i)); } } @@ -154,8 +155,8 @@ public class CommentContentRule extends AbstractCommentRule { } public boolean hasDissallowedTerms() { - String[] terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR); - return CollectionUtil.isNotEmpty(terms); + List terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR); + return !terms.isEmpty(); } /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentRequiredRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentRequiredRule.java index 2a7e3bb365..7813187a57 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentRequiredRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentRequiredRule.java @@ -43,31 +43,31 @@ public class CommentRequiredRule extends AbstractCommentRule { public static final EnumeratedProperty HEADER_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( "headerCommentRequirement", "Header comments. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 0, 1.0f); + CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 1.0f); public static final EnumeratedProperty FIELD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( "fieldCommentRequirement", "Field comments. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 0, 2.0f); + CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 2.0f); public static final EnumeratedProperty PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( "publicMethodCommentRequirement", "Public method and constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 0, 3.0f); + CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 3.0f); public static final EnumeratedProperty PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( "protectedMethodCommentRequirement", "Protected method constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 0, 4.0f); + CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 4.0f); public static final EnumeratedProperty ENUM_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( "enumCommentRequirement", "Enum comments. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 0, 5.0f); + CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 5.0f); - public static final EnumeratedProperty SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty( - "serialVersionUIDCommentRequired", - "serial version UID commts. Possible values: " + Arrays.toString(CommentRequirement.values()), - CommentRequirement.labels(), CommentRequirement.values(), 1, 6.0f); + public static final EnumeratedProperty SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>( + "serialVersionUIDCommentRequired", + "serial version UID commts. Possible values: " + Arrays.toString(CommentRequirement.values()), + CommentRequirement.labels(), CommentRequirement.values(), 1, CommentRequirement.class, 6.0f); public CommentRequiredRule() { definePropertyDescriptor(HEADER_CMT_REQUIREMENT_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/HeaderCommentsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/HeaderCommentsRule.java index b94d92d9a5..5fac0e5770 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/HeaderCommentsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/HeaderCommentsRule.java @@ -48,7 +48,7 @@ public class HeaderCommentsRule extends AbstractCommentRule { public static final EnumeratedProperty HEADER_PLACEMENT_DESCRIPTOR = new EnumeratedProperty<>( "headerPlacement", "Placement of the header comment", RequiredHeaderPlacement.labels(), - RequiredHeaderPlacement.values(), 0, 3.0f); + RequiredHeaderPlacement.values(), 0, RequiredHeaderPlacement.class, 3.0f); public HeaderCommentsRule() { definePropertyDescriptor(REQUIRED_TERMS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LoosePackageCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LoosePackageCouplingRule.java index b7c9bac329..8a058a5050 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LoosePackageCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LoosePackageCouplingRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.rule.coupling; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -15,7 +14,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.util.CollectionUtil; /** * The loose package coupling Rule can be used to ensure coupling outside of a @@ -65,7 +63,7 @@ public class LoosePackageCouplingRule extends AbstractJavaRule { // Sort the restricted packages in reverse order. This will ensure the // child packages are in the list before their parent packages. - this.restrictedPackages = new ArrayList<>(Arrays.asList(super.getProperty(PACKAGES_DESCRIPTOR))); + this.restrictedPackages = new ArrayList<>(super.getProperty(PACKAGES_DESCRIPTOR)); Collections.sort(restrictedPackages, Collections.reverseOrder()); return data; @@ -132,8 +130,7 @@ public class LoosePackageCouplingRule extends AbstractJavaRule { public boolean checksNothing() { - return CollectionUtil.isEmpty(getProperty(PACKAGES_DESCRIPTOR)) - && CollectionUtil.isEmpty(getProperty(CLASSES_DESCRIPTOR)); + return getProperty(PACKAGES_DESCRIPTOR).isEmpty() && getProperty(CLASSES_DESCRIPTOR).isEmpty(); } /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java index 887c55c9c7..7f61080811 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.rule.design; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -77,13 +76,13 @@ public class CloseResourceRule extends AbstractJavaRule { @Override public Object visit(ASTCompilationUnit node, Object data) { if (closeTargets.isEmpty() && getProperty(CLOSE_TARGETS_DESCRIPTOR) != null) { - closeTargets.addAll(Arrays.asList(getProperty(CLOSE_TARGETS_DESCRIPTOR))); + closeTargets.addAll(getProperty(CLOSE_TARGETS_DESCRIPTOR)); } if (getProperty(USE_CLOSE_AS_DEFAULT_TARGET) && !closeTargets.contains("close")) { closeTargets.add("close"); } if (types.isEmpty() && getProperty(TYPES_DESCRIPTOR) != null) { - types.addAll(Arrays.asList(getProperty(TYPES_DESCRIPTOR))); + types.addAll(getProperty(TYPES_DESCRIPTOR)); } if (simpleTypes.isEmpty() && getProperty(TYPES_DESCRIPTOR) != null) { for (String type : getProperty(TYPES_DESCRIPTOR)) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java index 8ace6a78d0..e45db8c2c2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GenericClassCounterRule.java @@ -84,22 +84,13 @@ public class GenericClassCounterRule extends AbstractJavaRule { definePropertyDescriptor(THRESHOLD_DESCRIPTOR); } - private List arrayAsList(String[] array) { - List list = new ArrayList<>(array.length); - int nbItem = 0; - while (nbItem < array.length) { - list.add(array[nbItem++]); - } - return list; - } - protected void init() { // Creating the attribute name for the rule context counterLabel = this.getClass().getSimpleName() + ".number of match"; // Constructing the request from the input parameters - this.namesMatch = RegexHelper.compilePatternsFromList(arrayAsList(getProperty(NAME_MATCH_DESCRIPTOR))); + this.namesMatch = RegexHelper.compilePatternsFromList(getProperty(NAME_MATCH_DESCRIPTOR)); this.operand = getProperty(OPERAND_DESCRIPTOR); - this.typesMatch = RegexHelper.compilePatternsFromList(arrayAsList(getProperty(TYPE_MATCH_DESCRIPTOR))); + this.typesMatch = RegexHelper.compilePatternsFromList(getProperty(TYPE_MATCH_DESCRIPTOR)); String thresholdAsString = getProperty(THRESHOLD_DESCRIPTOR); this.threshold = Integer.valueOf(thresholdAsString); // Initializing list of match diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementJavaUtilRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementJavaUtilRule.java index a4b3cef746..e1eca01b9c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementJavaUtilRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementJavaUtilRule.java @@ -29,8 +29,8 @@ public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule { return data; } - String[] logLevels = getProperty(LOG_LEVELS); - String[] guardMethods = getProperty(GUARD_METHODS); + String[] logLevels = getProperty(LOG_LEVELS).toArray(new String[0]); // TODO:cf convert to list + String[] guardMethods = getProperty(GUARD_METHODS).toArray(new String[0]); if (super.guardStmtByLogLevel.isEmpty() && logLevels.length > 0 && guardMethods.length > 0) { configureGuards(logLevels, guardMethods); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementRule.java index b4a1d20bf0..13e4acf283 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java.rule.logging; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -96,8 +95,8 @@ public class GuardLogStatementRule extends AbstractOptimizationRule implements R protected void extractProperties() { if (guardStmtByLogLevel.isEmpty()) { - List logLevels = new ArrayList<>(Arrays.asList(super.getProperty(LOG_LEVELS))); - List guardMethods = new ArrayList<>(Arrays.asList(super.getProperty(GUARD_METHODS))); + List logLevels = new ArrayList<>(super.getProperty(LOG_LEVELS)); + List guardMethods = new ArrayList<>(super.getProperty(GUARD_METHODS)); if (guardMethods.isEmpty() && !logLevels.isEmpty()) { throw new IllegalArgumentException("Can't specify guardMethods without specifiying logLevels."); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/VariableNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/VariableNamingConventionsRule.java index c190b2a621..70516a59d5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/VariableNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/VariableNamingConventionsRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.naming; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; @@ -19,7 +21,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty; -import net.sourceforge.pmd.util.CollectionUtil; public class VariableNamingConventionsRule extends AbstractJavaRule { @@ -27,14 +28,14 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { private boolean checkLocals; private boolean checkParameters; private boolean checkNativeMethodParameters; - private String[] staticPrefixes; - private String[] staticSuffixes; - private String[] memberPrefixes; - private String[] memberSuffixes; - private String[] localPrefixes; - private String[] localSuffixes; - private String[] parameterPrefixes; - private String[] parameterSuffixes; + private List staticPrefixes; + private List staticSuffixes; + private List memberPrefixes; + private List memberSuffixes; + private List localPrefixes; + private List localSuffixes; + private List parameterPrefixes; + private List parameterSuffixes; private static final BooleanProperty CHECK_MEMBERS_DESCRIPTOR = new BooleanProperty("checkMembers", "Check member variables", true, 1.0f); @@ -152,7 +153,7 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { return data; } - private Object checkVariableDeclarators(String[] prefixes, String[] suffixes, Node root, boolean isStatic, + private Object checkVariableDeclarators(List prefixes, List suffixes, Node root, boolean isStatic, boolean isFinal, Object data) { for (ASTVariableDeclarator variableDeclarator : root.findChildrenOfType(ASTVariableDeclarator.class)) { for (ASTVariableDeclaratorId variableDeclaratorId : variableDeclarator @@ -163,7 +164,7 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { return data; } - private Object checkVariableDeclaratorId(String[] prefixes, String[] suffixes, Node root, boolean isStatic, + private Object checkVariableDeclaratorId(List prefixes, List suffixes, Node root, boolean isStatic, boolean isFinal, ASTVariableDeclaratorId variableDeclaratorId, Object data) { // Get the variable name @@ -199,15 +200,15 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { return data; } - private String normalizeVariableName(String varName, String[] prefixes, String[] suffixes) { + private String normalizeVariableName(String varName, List prefixes, List suffixes) { return stripSuffix(stripPrefix(varName, prefixes), suffixes); } - private String stripSuffix(String varName, String[] suffixes) { + private String stripSuffix(String varName, List suffixes) { if (suffixes != null) { - for (int i = 0; i < suffixes.length; i++) { - if (varName.endsWith(suffixes[i])) { - varName = varName.substring(0, varName.length() - suffixes[i].length()); + for (String suffix : suffixes) { + if (varName.endsWith(suffix)) { + varName = varName.substring(0, varName.length() - suffix.length()); break; } } @@ -215,11 +216,11 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { return varName; } - private String stripPrefix(String varName, String[] prefixes) { + private String stripPrefix(String varName, List prefixes) { if (prefixes != null) { - for (int i = 0; i < prefixes.length; i++) { - if (varName.startsWith(prefixes[i])) { - return varName.substring(prefixes[i].length()); + for (String prefix : prefixes) { + if (varName.startsWith(prefix)) { + return varName.substring(prefix.length()); } } } @@ -230,8 +231,8 @@ public class VariableNamingConventionsRule extends AbstractJavaRule { for (PropertyDescriptor desc : getPropertyDescriptors()) { if (desc instanceof StringMultiProperty) { - String[] values = getProperty((StringMultiProperty) desc); - if (CollectionUtil.isNotEmpty(values)) { + List values = getProperty((StringMultiProperty) desc); + if (!values.isEmpty()) { return true; } } diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java index e40bb86fe3..2173b60556 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptions.java @@ -43,10 +43,11 @@ public class EcmascriptParserOptions extends ParserOptions { } } - private static final String[] VERSION_LABELS = new String[] { Version.VERSION_DEFAULT.getLabel(), - Version.VERSION_1_0.getLabel(), Version.VERSION_1_1.getLabel(), Version.VERSION_1_2.getLabel(), - Version.VERSION_1_3.getLabel(), Version.VERSION_1_4.getLabel(), Version.VERSION_1_5.getLabel(), - Version.VERSION_1_6.getLabel(), Version.VERSION_1_7.getLabel(), Version.VERSION_1_8.getLabel(), }; + private static final String[] VERSION_LABELS = {Version.VERSION_DEFAULT.getLabel(), + Version.VERSION_1_0.getLabel(), Version.VERSION_1_1.getLabel(), Version.VERSION_1_2.getLabel(), + Version.VERSION_1_3.getLabel(), Version.VERSION_1_4.getLabel(), Version.VERSION_1_5.getLabel(), + Version.VERSION_1_6.getLabel(), Version.VERSION_1_7.getLabel(), + Version.VERSION_1_8.getLabel(), }; // Note: The UI order values are chosen to be larger than those built into // XPathRule. @@ -58,24 +59,22 @@ public class EcmascriptParserOptions extends ParserOptions { public static final EnumeratedProperty RHINO_LANGUAGE_VERSION = new EnumeratedProperty<>( "rhinoLanguageVersion", "Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.", VERSION_LABELS, - Version.values(), 0, 5.0f); + Version.values(), 0, Version.class, 5.0f); private boolean recordingComments; private boolean recordingLocalJsDocComments; private Version rhinoLanguageVersion; public EcmascriptParserOptions() { - this.recordingComments = RECORDING_COMMENTS_DESCRIPTOR.defaultValue().booleanValue(); - this.recordingLocalJsDocComments = RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR.defaultValue().booleanValue(); - this.rhinoLanguageVersion = (Version) RHINO_LANGUAGE_VERSION - .valueFrom((String) RHINO_LANGUAGE_VERSION.defaultValue()); + this.recordingComments = RECORDING_COMMENTS_DESCRIPTOR.defaultValue(); + this.recordingLocalJsDocComments = RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR.defaultValue(); + this.rhinoLanguageVersion = RHINO_LANGUAGE_VERSION.defaultValue(); } public EcmascriptParserOptions(Rule rule) { this.recordingComments = rule.getProperty(RECORDING_COMMENTS_DESCRIPTOR); this.recordingLocalJsDocComments = rule.getProperty(RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR); - this.rhinoLanguageVersion = (Version) RHINO_LANGUAGE_VERSION - .valueFrom((String) rule.getProperty(RHINO_LANGUAGE_VERSION)); + this.rhinoLanguageVersion = rule.getProperty(RHINO_LANGUAGE_VERSION); } public boolean isRecordingComments() { diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java index e323a8dfb8..3580e88418 100644 --- a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/EcmascriptParserOptionsTest.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; import net.sourceforge.pmd.lang.ParserOptions; +import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions.Version; import net.sourceforge.pmd.lang.ecmascript.rule.AbstractEcmascriptRule; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; @@ -46,10 +47,10 @@ public class EcmascriptParserOptionsTest { rule.setProperty(EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR, false); assertFalse(((EcmascriptParserOptions) rule.getParserOptions()).isRecordingLocalJsDocComments()); - rule.setProperty(EcmascriptParserOptions.RHINO_LANGUAGE_VERSION, "default"); + rule.setProperty(EcmascriptParserOptions.RHINO_LANGUAGE_VERSION, Version.VERSION_DEFAULT); assertEquals(EcmascriptParserOptions.Version.VERSION_DEFAULT, ((EcmascriptParserOptions) rule.getParserOptions()).getRhinoLanguageVersion()); - rule.setProperty(EcmascriptParserOptions.RHINO_LANGUAGE_VERSION, "1.8"); + rule.setProperty(EcmascriptParserOptions.RHINO_LANGUAGE_VERSION, Version.VERSION_1_8); assertEquals(EcmascriptParserOptions.Version.VERSION_1_8, ((EcmascriptParserOptions) rule.getParserOptions()).getRhinoLanguageVersion()); } @@ -66,8 +67,8 @@ public class EcmascriptParserOptionsTest { @Test public void testEqualsHashcode() throws Exception { - BooleanProperty[] properties = new BooleanProperty[] { EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR, - EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR, }; + BooleanProperty[] properties = {EcmascriptParserOptions.RECORDING_COMMENTS_DESCRIPTOR, + EcmascriptParserOptions.RECORDING_LOCAL_JSDOC_COMMENTS_DESCRIPTOR, }; for (int i = 0; i < properties.length; i++) { BooleanProperty property = properties[i]; diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java index 38c7c12b59..d076e07a23 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; - import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -212,6 +211,7 @@ public abstract class AbstractRuleSetFactoryTest { for (String fileName : ruleSetFileNames) { testRuleSet(fileName); } + } // Gets all test PMD Ruleset XML files @@ -397,8 +397,7 @@ public abstract class AbstractRuleSetFactoryTest { Rule rule2 = ((List) ruleSet2.getRules()).get(i); assertFalse(message + ", Different RuleReference", - rule1 instanceof RuleReference && !(rule2 instanceof RuleReference) - || !(rule1 instanceof RuleReference) && rule2 instanceof RuleReference); + rule1 instanceof RuleReference != rule2 instanceof RuleReference); if (rule1 instanceof RuleReference) { RuleReference ruleReference1 = (RuleReference) rule1; From 6a3b394aa05f593882fe3ab10ecd3d84e585a165 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 28 Jun 2017 23:59:22 +0200 Subject: [PATCH 14/53] Solve plugin errors --- .../pmd/EnumeratedPropertyDescriptor.java | 1 + .../properties/EnumeratedMultiProperty.java | 13 ++++++ .../rule/properties/EnumeratedProperty.java | 13 ++++++ .../EnumeratedPropertyDescriptorWrapper.java | 6 +++ .../net/sourceforge/pmd/util/ClassUtil.java | 22 +++++++++ .../sourceforge/pmd/util/CollectionUtil.java | 45 ++++++++++++++----- .../net/sourceforge/pmd/util/StringUtil.java | 1 + 7 files changed, 90 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java index 0e0f7979dd..0435099932 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java @@ -23,4 +23,5 @@ public interface EnumeratedPropertyDescriptor extends PropertyDescriptor mappings(); + Object[][] choices(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index c0a62ce3f4..170dbf4fc2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -113,6 +114,18 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty } + @Override + public Object[][] choices() { + Object[][] res = new Object[choicesByLabel.size()][2]; + int i = 0; + for (Entry e : choicesByLabel.entrySet()) { + res[i++][0] = e.getKey(); + res[i][1] = e.getValue(); + } + return res; + } + + @Override public Class type() { return valueType; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 96a3ee6a22..bda22ed7fb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Collections; import java.util.Enumeration; import java.util.Map; +import java.util.Map.Entry; import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -109,4 +110,16 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty return choicesByLabel; } + + @Override + public Object[][] choices() { + Object[][] res = new Object[choicesByLabel.size()][2]; + int i = 0; + for (Entry e : choicesByLabel.entrySet()) { + res[i++][0] = e.getKey(); + res[i][1] = e.getValue(); + } + return res; + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java index 2cd32d4978..a2537fff01 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java @@ -24,4 +24,10 @@ public class EnumeratedPropertyDescriptorWrapper extends PropertyDescripto return ((EnumeratedPropertyDescriptor) propertyDescriptor).mappings(); } + + @Override + public Object[][] choices() { + return ((EnumeratedPropertyDescriptor) propertyDescriptor).choices(); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/ClassUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/ClassUtil.java index 9c11f5d867..334bc02994 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/ClassUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/ClassUtil.java @@ -158,4 +158,26 @@ public final class ClassUtil { } return methodGroups; } + + + /** + * Return the methods as a map keyed by their common declaration types. + * + * @param methods + * + * @return methods grouped by declaring type name + */ + public static Map> asMethodGroupsByTypeName(List methods) { + + Map> methodGroups = new HashMap<>(methods.size()); + + for (Method m : methods) { + String clsName = asShortestName(m.getDeclaringClass()); + if (!methodGroups.containsKey(clsName)) { + methodGroups.put(clsName, new ArrayList()); + } + methodGroups.get(clsName).add(m); + } + return methodGroups; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java index 2eb1ed7582..d7f63b9dc6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java @@ -24,14 +24,14 @@ import java.util.Set; public final class CollectionUtil { @SuppressWarnings("PMD.UnnecessaryFullyQualifiedName") - public static final TypeMap COLLECTION_INTERFACES_BY_NAMES = new TypeMap(new Class[] { java.util.List.class, - java.util.Collection.class, java.util.Map.class, java.util.Set.class, }); + public static final TypeMap COLLECTION_INTERFACES_BY_NAMES = new TypeMap(List.class, Collection.class, Map.class, Set.class); + + @SuppressWarnings({"PMD.LooseCoupling", "PMD.UnnecessaryFullyQualifiedName" }) + public static final TypeMap COLLECTION_CLASSES_BY_NAMES + = new TypeMap(ArrayList.class, java.util.LinkedList.class, java.util.Vector.class, HashMap.class, + java.util.LinkedHashMap.class, java.util.TreeMap.class, java.util.TreeSet.class, + HashSet.class, java.util.LinkedHashSet.class, java.util.Hashtable.class); - @SuppressWarnings({ "PMD.LooseCoupling", "PMD.UnnecessaryFullyQualifiedName" }) - public static final TypeMap COLLECTION_CLASSES_BY_NAMES = new TypeMap(new Class[] { java.util.ArrayList.class, - java.util.LinkedList.class, java.util.Vector.class, java.util.HashMap.class, java.util.LinkedHashMap.class, - java.util.TreeMap.class, java.util.TreeSet.class, java.util.HashSet.class, java.util.LinkedHashSet.class, - java.util.Hashtable.class, }); private CollectionUtil() { } @@ -44,11 +44,11 @@ public final class CollectionUtil { * @param target * @return int */ - public static int addWithoutDuplicates(Collection source, Collection target) { + public static int addWithoutDuplicates(Collection source, Collection target) { int added = 0; - for (String item : source) { + for (T item : source) { if (target.contains(item)) { continue; } @@ -269,10 +269,10 @@ public final class CollectionUtil { public static boolean areSemanticEquals(T[] a, T[] b) { if (a == null) { - return isEmpty(b); + return b == null || b.length == 0; } if (b == null) { - return isEmpty(a); + return a.length == 0; } if (a.length != b.length) { @@ -288,6 +288,29 @@ public final class CollectionUtil { return true; } + + public static boolean areSemanticEquals(List a, List b) { + + if (a == null) { + return b == null || b.isEmpty(); + } + if (b == null) { + return a.isEmpty(); + } + + if (a.size() != b.size()) { + return false; + } + + for (int i = 0; i < a.size(); i++) { + if (!areEqual(a.get(i), b.get(i))) { + return false; + } + } + + return true; + } + /** * If the newValue is already held within the values array then the values * array is returned, otherwise a new array is created appending the diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java index 187dbb0c52..fe9e7ac160 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java @@ -587,6 +587,7 @@ public final class StringUtil { return sb.toString(); } + /** * Returns an empty array of string * From a30449d475e4557eecb9d9dab6dadd7c8cd79bdf Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 30 Jun 2017 16:25:14 +0200 Subject: [PATCH 15/53] Enhanced wrappers --- .../pmd/AbstractPropertySource.java | 55 ++++++------------- .../pmd/EnumeratedPropertyDescriptor.java | 12 +++- .../pmd/MultiValuePropertyDescriptor.java | 11 +++- .../pmd/NumericPropertyDescriptor.java | 5 +- .../sourceforge/pmd/PropertyDescriptor.java | 22 +++++--- .../pmd/PropertyDescriptorFactory.java | 13 ++++- .../net/sourceforge/pmd/PropertySource.java | 53 +++++++++--------- .../net/sourceforge/pmd/RuleSetFactory.java | 10 +--- .../net/sourceforge/pmd/RuleSetWriter.java | 2 +- .../pmd/SingleValuePropertyDescriptor.java | 6 ++ .../AbstractMultiNumericProperty.java | 8 ++- .../AbstractMultiValueProperty.java | 6 ++ .../properties/AbstractNumericProperty.java | 7 +++ .../rule/properties/AbstractProperty.java | 11 +++- .../AbstractSingleValueProperty.java | 6 ++ .../BasicPropertyDescriptorFactory.java | 7 --- .../lang/rule/properties/BooleanProperty.java | 1 + .../properties/EnumeratedMultiProperty.java | 8 ++- .../rule/properties/EnumeratedProperty.java | 7 ++- .../EnumeratedPropertyDescriptorWrapper.java | 6 +- ...ValueNumericPropertyDescriptorWrapper.java | 33 +++++++++++ .../MultiValuePropertyDescriptorFactory.java | 16 +++++- .../MultiValuePropertyDescriptorWrapper.java | 7 +-- .../properties/PropertyDescriptorFactory.java | 4 +- .../PropertyDescriptorWrapper.java | 29 ++++++++-- ...ValueNumericPropertyDescriptorWrapper.java | 31 +++++++++++ .../SingleValuePropertyDescriptorFactory.java | 12 +++- .../SingleValuePropertyDescriptorWrapper.java | 6 +- .../lang/rule/xpath/SaxonXPathRuleQuery.java | 4 +- 29 files changed, 274 insertions(+), 124 deletions(-) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{wrappers => }/EnumeratedPropertyDescriptorWrapper.java (69%) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{wrappers => }/MultiValuePropertyDescriptorWrapper.java (69%) rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{wrappers => }/PropertyDescriptorWrapper.java (79%) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java rename pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/{wrappers => }/SingleValuePropertyDescriptorWrapper.java (61%) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java index e9ee2d60d5..c371492e1a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java @@ -7,9 +7,9 @@ package net.sourceforge.pmd; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import net.sourceforge.pmd.util.CollectionUtil; @@ -27,6 +27,7 @@ public abstract class AbstractPropertySource implements PropertySource { /** The values for each property. */ protected Map, Object> propertyValuesByDescriptor = new HashMap<>(); + /** * Creates a copied list of the property descriptors and returns it. * @@ -36,6 +37,7 @@ public abstract class AbstractPropertySource implements PropertySource { return new ArrayList<>(propertyDescriptors); } + /** * Creates a copied map of the values of the properties and returns it. * @@ -45,17 +47,13 @@ public abstract class AbstractPropertySource implements PropertySource { return new HashMap<>(propertyValuesByDescriptor); } - /** - * {@inheritDoc} - */ + @Override public Set> ignoredProperties() { return Collections.emptySet(); } - /** - * {@inheritDoc} - */ + @Override public void definePropertyDescriptor(PropertyDescriptor propertyDescriptor) { // Check to ensure the property does not already exist. @@ -70,6 +68,7 @@ public abstract class AbstractPropertySource implements PropertySource { Collections.sort(propertyDescriptors); } + /** * Gets the name of the property source. This is e.g. the rule name or the * report name. @@ -78,9 +77,7 @@ public abstract class AbstractPropertySource implements PropertySource { */ public abstract String getName(); - /** - * {@inheritDoc} - */ + @Override public PropertyDescriptor getPropertyDescriptor(String name) { for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { @@ -91,9 +88,7 @@ public abstract class AbstractPropertySource implements PropertySource { return null; } - /** - * {@inheritDoc} - */ + @Override public boolean hasDescriptor(PropertyDescriptor descriptor) { @@ -104,17 +99,13 @@ public abstract class AbstractPropertySource implements PropertySource { return propertyValuesByDescriptor.containsKey(descriptor); } - /** - * {@inheritDoc} - */ + @Override public List> getPropertyDescriptors() { return propertyDescriptors; } - /** - * {@inheritDoc} - */ + @Override public T getProperty(PropertyDescriptor propertyDescriptor) { checkValidPropertyDescriptor(propertyDescriptor); @@ -127,15 +118,14 @@ public abstract class AbstractPropertySource implements PropertySource { return result; } - /** - * {@inheritDoc} - */ + @Override public void setProperty(PropertyDescriptor propertyDescriptor, T value) { checkValidPropertyDescriptor(propertyDescriptor); propertyValuesByDescriptor.put(propertyDescriptor, value); } + private void checkValidPropertyDescriptor(PropertyDescriptor propertyDescriptor) { if (!propertyDescriptors.contains(propertyDescriptor)) { throw new IllegalArgumentException( @@ -143,9 +133,7 @@ public abstract class AbstractPropertySource implements PropertySource { } } - /** - * {@inheritDoc} - */ + @Override public Map, Object> getPropertiesByPropertyDescriptor() { if (propertyDescriptors.isEmpty()) { @@ -166,9 +154,7 @@ public abstract class AbstractPropertySource implements PropertySource { return propertiesByPropertyDescriptor; } - /** - * {@inheritDoc} - */ + @Override public boolean usesDefaultValues() { @@ -177,10 +163,7 @@ public abstract class AbstractPropertySource implements PropertySource { return true; } - Iterator, Object>> iter = valuesByProperty.entrySet().iterator(); - - while (iter.hasNext()) { - Map.Entry, Object> entry = iter.next(); + for (Entry, Object> entry : valuesByProperty.entrySet()) { if (!CollectionUtil.areEqual(entry.getKey().defaultValue(), entry.getValue())) { return false; } @@ -189,17 +172,13 @@ public abstract class AbstractPropertySource implements PropertySource { return true; } - /** - * {@inheritDoc} - */ + @Override public void useDefaultValueFor(PropertyDescriptor desc) { propertyValuesByDescriptor.remove(desc); } - /** - * {@inheritDoc} - */ + @Override public String dysfunctionReason() { return null; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java index 0435099932..53ffaabafc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java @@ -13,15 +13,23 @@ import java.util.Map; * @param The type of default values the descriptor can take (can be a List) * * @author Clément Fournier + * @since 6.0.0 */ public interface EnumeratedPropertyDescriptor extends PropertyDescriptor { /** - * Returns a map of the label - value mappings defined by this descriptor. + * Returns an immutable map of the label - value mappings defined by this descriptor. * - * @return a map of the label - value mappings defined by this descriptor. + * @return an immutable map of the label - value mappings defined by this descriptor. */ Map mappings(); + + /** + * Returns a set of choice tuples if available. This is kept for compatibility with the eclipse plugin, even + * though it returns the same information as {@link #mappings()} (only it returns them ordered). + * + * @return An array of the label value mappings. The first column is the labels, the second is the value. + */ Object[][] choices(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java index c12093aab7..c010060f9d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java @@ -7,14 +7,19 @@ package net.sourceforge.pmd; import java.util.List; /** + * Specializes property descriptors for single valued descriptors. For this type of property, the return value of the + * {@link #type()} method must be the class literal of the type parameter of the interface {@link PropertyDescriptor}. + * + * @param The type of value this descriptor works with. This is the type of the list's component. + * * @author Clément Fournier + * @since 6.0.0 */ public interface MultiValuePropertyDescriptor extends PropertyDescriptor> { /** - * Return the character being used to delimit multiple property values - * within a single string. You must ensure that this character does not - * appear within any rule property values to avoid deserialization errors. + * Return the character being used to delimit multiple property values within a single string. You must ensure that + * this character does not appear within any rule property values to avoid deserialization errors. * * @return char */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index 8fcd554e0c..15146e0242 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -8,9 +8,9 @@ package net.sourceforge.pmd; * Defines a descriptor type whose instance values are required lie within * specified upper and lower limits. * - * @author Brian Remedios - * * @param type of the property value + * + * @author Brian Remedios */ public interface NumericPropertyDescriptor extends PropertyDescriptor { @@ -21,6 +21,7 @@ public interface NumericPropertyDescriptor extends PropertyDescriptor { */ Number upperLimit(); + /** * Returns the minimum value that instances of the property can have. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 027d245cf9..f3dfb8a662 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -12,9 +12,18 @@ import java.util.Map; * descriptor instances are static and immutable they provide validation, * serialization, and default values for any specific datatypes. * - * @param type of the property's value + *

This interface is primarily specialized according to whether the property is + * multi-valued or single-valued, see {@link SingleValuePropertyDescriptor} and + * {@link MultiValuePropertyDescriptor}. + * + *

Several interfaces further specialize the behaviour of descriptors to accommodate + * specific types of descriptors, see {@link NumericPropertyDescriptor} and + * {@link EnumeratedPropertyDescriptor}. + * + * @param type of the property's value. This is a list type for multi-valued properties. * * @author Brian Remedios + * @version Refactored June 2017 (6.0.0) */ public interface PropertyDescriptor extends Comparable> { @@ -40,7 +49,7 @@ public interface PropertyDescriptor extends Comparable> * Denotes the value datatype. For multi value properties, this is not the * List class but the list's component class. * - * @return Class + * @return Class literal of the value type */ Class type(); @@ -106,14 +115,11 @@ public interface PropertyDescriptor extends Comparable> /** - * If the property is multi-valued then return the separate values after - * parsing the propertyString provided. If it isn't a multi-valued property - * then the value will be returned within an array of size[1]. - * // TODO:cf API change. This will return a T if single valued, and a list if multi valued. + * Retunrs the value represented by this string. * - * @param propertyString String + * @param propertyString The string to parse * - * @return Object + * @return The value represented by the string * * @throws IllegalArgumentException if the given string cannot be parsed */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index cbb1b4fd2e..746f26df48 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -10,6 +10,7 @@ import java.util.Map; * A factory to create {@link PropertyDescriptor}s based on a map of values. * * @param the type of values property descriptor returned by this factory. This can be a list. + * * @author Brian Remedios */ public interface PropertyDescriptorFactory { @@ -22,8 +23,15 @@ public interface PropertyDescriptorFactory { */ Class valueType(); + + /** + * Returns true if the wrapped property descriptor is multi-valued. + * + * @return true if the wrapped property descriptor is multi-valued. + */ boolean isMultiValue(); + /** * Denote the identifiers of the expected fields paired with booleans * denoting whether they are required (non-null) or not. @@ -32,12 +40,13 @@ public interface PropertyDescriptorFactory { */ Map expectedFields(); + /** * Create a property descriptor of the appropriate type using the values * provided. * - * @param valuesById - * the map of values + * @param valuesById the map of values + * * @return a new and initialized {@link PropertyDescriptor} */ PropertyDescriptor createWith(Map valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java index ecabc141b7..e208f8a8e7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java @@ -19,23 +19,23 @@ public interface PropertySource { /** * Define a new property via a PropertyDescriptor. * - * @param propertyDescriptor - * The property descriptor. - * @throws IllegalArgumentException - * If there is already a property defined the same name. + * @param propertyDescriptor The property descriptor. + * + * @throws IllegalArgumentException If there is already a property defined the same name. */ void definePropertyDescriptor(PropertyDescriptor propertyDescriptor) throws IllegalArgumentException; + /** * Get the PropertyDescriptor for the given property name. * - * @param name - * The name of the property. - * @return The PropertyDescriptor for the named property, null - * if there is no such property defined. + * @param name The name of the property. + * + * @return The PropertyDescriptor for the named property, null if there is no such property defined. */ PropertyDescriptor getPropertyDescriptor(String name); + /** * Get the PropertyDescriptors for all defined properties. The properties * are returned sorted by UI order. @@ -44,29 +44,28 @@ public interface PropertySource { */ List> getPropertyDescriptors(); + /** * Get the typed value for the given property. * - * @param - * The underlying type of the property descriptor. - * @param propertyDescriptor - * The property descriptor. + * @param The underlying type of the property descriptor. + * @param propertyDescriptor The property descriptor. + * * @return The property value. */ T getProperty(PropertyDescriptor propertyDescriptor); + /** * Set the property value specified (will be type-checked) * - * @param - * The underlying type of the property descriptor. - * @param propertyDescriptor - * The property descriptor. - * @param value - * The value to set. + * @param The underlying type of the property descriptor. + * @param propertyDescriptor The property descriptor. + * @param value The value to set. */ void setProperty(PropertyDescriptor propertyDescriptor, T value); + /** * Returns all the current property values for the receiver or an immutable * empty map if none are specified. @@ -75,33 +74,34 @@ public interface PropertySource { */ Map, Object> getPropertiesByPropertyDescriptor(); + /** * Returns whether this Rule has the specified PropertyDescriptor. * - * @param descriptor - * The PropertyDescriptor for which to check. - * @return boolean true if the descriptor is present, - * false otherwise. + * @param descriptor The PropertyDescriptor for which to check. + * + * @return boolean true if the descriptor is present, false otherwise. */ boolean hasDescriptor(PropertyDescriptor descriptor); + /** * Returns whether this Rule uses default values for properties. * - * @return boolean true if the properties all have default - * values, false otherwise. + * @return boolean true if the properties all have default values, false otherwise. */ boolean usesDefaultValues(); + /** * Clears out any user-specified value for the property allowing it to use * the default value in the descriptor. * - * @param desc - * the property to clear out + * @param desc the property to clear out */ void useDefaultValueFor(PropertyDescriptor desc); + /** * Return the properties that are effectively ignored due to the * configuration of the rule and values held by other properties. This can @@ -111,6 +111,7 @@ public interface PropertySource { */ Set> ignoredProperties(); + /** * Returns a description of why the receiver may be dysfunctional. Usually * due to missing property values or some kind of conflict between values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 8c756eddd2..50982078fa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -38,7 +38,7 @@ import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; -import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.util.ResourceLoader; import net.sourceforge.pmd.util.StringUtil; @@ -485,12 +485,6 @@ public class RuleSetFactory { * * @param ruleSetReferenceId * The RuleSetReferenceId of the RuleSet being parsed. - * @param ruleSet - * The RuleSet being constructed. - * @param ruleNode - * Must be a rule element node. - * @param ruleSetReferenceId - * The RuleSetReferenceId of the RuleSet being parsed. * @param ruleSetBuilder * The RuleSet being constructed. * @param ruleNode @@ -886,7 +880,7 @@ public class RuleSetFactory { } PropertyDescriptor desc = pdFactory.createWith(values); - PropertyDescriptorWrapper wrapper = new PropertyDescriptorWrapper<>(desc); // TODO:cf fix me + PropertyDescriptorWrapper wrapper = PropertyDescriptorWrapper.getWrapper(desc); rule.definePropertyDescriptor(wrapper); setValue(rule, desc, strValue); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 47dbf5da56..2b4f421db0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -33,7 +33,7 @@ import net.sourceforge.pmd.lang.rule.ImmutableLanguage; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; -import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; /** * This class represents a way to serialize a RuleSet to an XML configuration diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java index 5e8e1c486f..d758acc3c1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SingleValuePropertyDescriptor.java @@ -5,7 +5,13 @@ package net.sourceforge.pmd; /** + * Specializes property descriptors for single valued descriptors. For this type of property, the return value of the + * {@link #type()} method must be the class literal of the type parameter of the interface {@link PropertyDescriptor}. + * + * @param The type of value this descriptor works with. Cannot be a list. + * * @author Clément Fournier + * @since 6.0.0 */ public interface SingleValuePropertyDescriptor extends PropertyDescriptor { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 1bd17db07e..44b2a39524 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -41,7 +41,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ AbstractMultiNumericProperty(String theName, String theDescription, Number min, Number max, List theDefault, - float theUIOrder) { + float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); if (min.doubleValue() > max.doubleValue()) { @@ -84,4 +84,10 @@ import net.sourceforge.pmd.PropertyDescriptorField; attributes.put(MIN, lowerLimit.toString()); attributes.put(MAX, upperLimit.toString()); } + + + @Override + /* default */ PropertyDescriptorWrapper> getWrapper() { + return new MultiValueNumericPropertyDescriptorWrapper<>(this); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 8fd54f78db..95b69b97de 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -206,4 +206,10 @@ import net.sourceforge.pmd.Rule; attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); } + + @Override + /* default */ PropertyDescriptorWrapper> getWrapper() { + return new MultiValuePropertyDescriptorWrapper<>(this); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 22affd060c..4f27829d8a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -107,4 +107,11 @@ import net.sourceforge.pmd.PropertyDescriptorField; attributes.put(MIN, lowerLimit.toString()); attributes.put(MAX, upperLimit.toString()); } + + + @Override + /* default */ PropertyDescriptorWrapper getWrapper() { + return new SingleValueNumericPropertyDescriptorWrapper<>(this); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index bdbc47f9da..c7d8a307dc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -18,7 +18,7 @@ import net.sourceforge.pmd.util.StringUtil; /** * Abstract class for properties. * - * @param The type of the values + * @param The type of the property's value. This is a list type for multi-valued properties * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) @@ -155,4 +155,13 @@ import net.sourceforge.pmd.util.StringUtil; */ protected abstract String defaultAsString(); + + /** + * Gets a wrapper for this property. This method ensures that a wrapper of a property always implements the same + * interfaces as that property using double dispatch. + * + * @return A wrapper for this property. + */ + /* default */ abstract PropertyDescriptorWrapper getWrapper(); + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 2c1f727ed7..1d01801f16 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -141,4 +141,10 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; */ protected abstract T createFrom(String toParse); // this is there to be symmetrical to multi values + + @Override + /* default */ PropertyDescriptorWrapper getWrapper() { + return new SingleValuePropertyDescriptorWrapper<>(this); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java index e6c5889d02..cbfd86114c 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java @@ -18,7 +18,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.CollectionUtil; @@ -66,12 +65,6 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr } - @Override - public PropertyDescriptor createWith(Map valuesById) { - throw new RuntimeException("Unimplemented createWith() method in subclass"); - } - - @Override public Map expectedFields() { return fieldTypesByKey; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index 294d383fd4..e7a47e1348 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -19,6 +19,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class BooleanProperty extends AbstractSingleValueProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Boolean.class) { @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index 170dbf4fc2..aded3f9df0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -110,7 +110,7 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty @Override public Map mappings() { - return choicesByLabel; + return choicesByLabel; // unmodifiable } @@ -171,4 +171,10 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty return labelsByChoice.get(item); } + + @Override + /* default */ PropertyDescriptorWrapper> getWrapper() { + return new EnumeratedPropertyDescriptorWrapper<>(this); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index bda22ed7fb..4d154a4eda 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -107,7 +107,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty @Override public Map mappings() { - return choicesByLabel; + return choicesByLabel; // unmodifiable } @@ -122,4 +122,9 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty return res; } + @Override + /* default */ PropertyDescriptorWrapper getWrapper() { + return new EnumeratedPropertyDescriptorWrapper<>(this); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java similarity index 69% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java index a2537fff01..df64f6c78c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/EnumeratedPropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.wrappers; +package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; @@ -11,10 +11,10 @@ import net.sourceforge.pmd.EnumeratedPropertyDescriptor; /** * @author Clément Fournier */ -public class EnumeratedPropertyDescriptorWrapper extends PropertyDescriptorWrapper +/* default */ class EnumeratedPropertyDescriptorWrapper extends PropertyDescriptorWrapper implements EnumeratedPropertyDescriptor { - public EnumeratedPropertyDescriptorWrapper(EnumeratedPropertyDescriptor propertyDescriptor) { + EnumeratedPropertyDescriptorWrapper(EnumeratedPropertyDescriptor propertyDescriptor) { super(propertyDescriptor); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java new file mode 100644 index 0000000000..388317efb2 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java @@ -0,0 +1,33 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.List; + +import net.sourceforge.pmd.MultiValuePropertyDescriptor; +import net.sourceforge.pmd.NumericPropertyDescriptor; + +/** + * @author Clément Fournier + */ +/* default */ class MultiValueNumericPropertyDescriptorWrapper + extends MultiValuePropertyDescriptorWrapper implements NumericPropertyDescriptor> { + + > & MultiValuePropertyDescriptor> MultiValueNumericPropertyDescriptorWrapper(D propertyDescriptor) { + super(propertyDescriptor); + } + + + @Override + public Number upperLimit() { + return ((NumericPropertyDescriptor) propertyDescriptor).upperLimit(); + } + + + @Override + public Number lowerLimit() { + return ((NumericPropertyDescriptor) propertyDescriptor).lowerLimit(); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java index f935a65331..c77b67aa49 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java @@ -7,24 +7,34 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.List; import java.util.Map; +import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; /** + * Concrete implementation of a property descriptor factory for multi valued properties. + * + * @param Type of the property + * * @author Clément Fournier + * @since 6.0.0 */ -public class MultiValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory> { +public abstract class MultiValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory> { public MultiValuePropertyDescriptorFactory(Class theValueType) { super(theValueType); } - public MultiValuePropertyDescriptorFactory(Class theValueType, Map - additionalFieldTypesByKey) { + public MultiValuePropertyDescriptorFactory(Class theValueType, + Map additionalFieldTypesByKey) { super(theValueType, additionalFieldTypesByKey); } + @Override + public abstract MultiValuePropertyDescriptor createWith(Map valuesById); + + @Override public boolean isMultiValue() { return true; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java similarity index 69% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java index 04c7aa7ac8..a7d9a211ca 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/MultiValuePropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.wrappers; +package net.sourceforge.pmd.lang.rule.properties; import java.util.List; @@ -11,10 +11,10 @@ import net.sourceforge.pmd.MultiValuePropertyDescriptor; /** * @author Clément Fournier */ -public class MultiValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper> +/* default */ class MultiValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper> implements MultiValuePropertyDescriptor { - public MultiValuePropertyDescriptorWrapper(MultiValuePropertyDescriptor propertyDescriptor) { + MultiValuePropertyDescriptorWrapper(MultiValuePropertyDescriptor propertyDescriptor) { super(propertyDescriptor); } @@ -30,5 +30,4 @@ public class MultiValuePropertyDescriptorWrapper extends PropertyDescriptorWr return ((MultiValuePropertyDescriptor) propertyDescriptor).multiValueDelimiter(); } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index 707b4d7ec2..f8df5817f1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -7,9 +7,11 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; import net.sourceforge.pmd.util.StringUtil; +// TODO: delete? It's not used anywhere, including the plugins (the only usage is a doc import in +// PropertyDescriptorWrapper +// I'm pretty sure the functionality of this class was superseded by PropertyDescriptorUtil at some point public class PropertyDescriptorFactory { private PropertyDescriptorFactory() { } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java similarity index 79% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index e69b8daa32..3aa8f2693b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -2,14 +2,13 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.wrappers; +package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorFactory; /** * This class serves as a wrapper class for a PropertyDescriptor instance. It @@ -25,7 +24,7 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { protected final PropertyDescriptor propertyDescriptor; - public PropertyDescriptorWrapper(PropertyDescriptor propertyDescriptor) { + /* default */ PropertyDescriptorWrapper(PropertyDescriptor propertyDescriptor) { if (propertyDescriptor == null) { throw new IllegalArgumentException("PropertyDescriptor cannot be null."); } @@ -93,7 +92,6 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } - @SuppressWarnings("unchecked") @Override public Class type() { return propertyDescriptor.type(); @@ -121,12 +119,17 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { @Override public boolean equals(Object obj) { if (obj instanceof PropertyDescriptorWrapper) { - return this.getPropertyDescriptor().equals(((PropertyDescriptorWrapper) obj).getPropertyDescriptor()); + return this.propertyDescriptor.equals(((PropertyDescriptorWrapper) obj).getPropertyDescriptor()); } - return this.getPropertyDescriptor().equals(obj); + return this.propertyDescriptor.equals(obj); } + /** + * Returns the underlying property descriptor. + * + * @return The underlying property descriptor + */ public PropertyDescriptor getPropertyDescriptor() { return propertyDescriptor; } @@ -142,4 +145,18 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { public String toString() { return "wrapped:" + propertyDescriptor.toString(); } + + + /** + * Gets the wrapper of this property descriptor. + * + * @param desc The descriptor + * @param The type of the descriptor + * + * @return The wrapper of this descriptor + */ + public static PropertyDescriptorWrapper getWrapper(PropertyDescriptor desc) { + return ((AbstractProperty) desc).getWrapper(); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java new file mode 100644 index 0000000000..ddb5824942 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java @@ -0,0 +1,31 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import net.sourceforge.pmd.NumericPropertyDescriptor; +import net.sourceforge.pmd.SingleValuePropertyDescriptor; + +/** + * @author Clément Fournier + */ +/* default */ class SingleValueNumericPropertyDescriptorWrapper + extends SingleValuePropertyDescriptorWrapper implements NumericPropertyDescriptor { + + & SingleValuePropertyDescriptor> SingleValueNumericPropertyDescriptorWrapper(D propertyDescriptor) { + super(propertyDescriptor); + } + + + @Override + public Number upperLimit() { + return ((NumericPropertyDescriptor) propertyDescriptor).upperLimit(); + } + + + @Override + public Number lowerLimit() { + return ((NumericPropertyDescriptor) propertyDescriptor).lowerLimit(); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java index 2fa5c8c955..16be34f0e6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java @@ -7,11 +7,17 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.SingleValuePropertyDescriptor; /** + * Concrete implementation of a property descriptor factory for single valued properties. + * + * @param Type of the property + * * @author Clément Fournier + * @since 6.0.0 */ -public class SingleValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory { +public abstract class SingleValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory { public SingleValuePropertyDescriptorFactory(Class theValueType) { super(theValueType); @@ -24,6 +30,10 @@ public class SingleValuePropertyDescriptorFactory extends BasicPropertyDescri } + @Override + public abstract SingleValuePropertyDescriptor createWith(Map valuesById); + + @Override public boolean isMultiValue() { return false; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java similarity index 61% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java rename to pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java index c089f3c3cc..e870292b91 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/wrappers/SingleValuePropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java @@ -2,17 +2,17 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties.wrappers; +package net.sourceforge.pmd.lang.rule.properties; import net.sourceforge.pmd.SingleValuePropertyDescriptor; /** * @author Clément Fournier */ -public class SingleValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper +/* default */ class SingleValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper implements SingleValuePropertyDescriptor { - public SingleValuePropertyDescriptorWrapper(SingleValuePropertyDescriptor propertyDescriptor) { + SingleValuePropertyDescriptorWrapper(SingleValuePropertyDescriptor propertyDescriptor) { super(propertyDescriptor); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 1dad391516..507ece2516 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -17,8 +17,8 @@ import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.StringProperty; -import net.sourceforge.pmd.lang.rule.properties.wrappers.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.xpath.Initializer; import net.sf.saxon.om.ValueRepresentation; @@ -98,7 +98,7 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { if (propertyDescriptor instanceof StringProperty) { valueRepresentation = new StringValue((String) value); } else if (propertyDescriptor instanceof BooleanProperty) { - valueRepresentation = BooleanValue.get(((Boolean) value).booleanValue()); + valueRepresentation = BooleanValue.get((Boolean) value); } else if (propertyDescriptor instanceof IntegerProperty) { valueRepresentation = Int64Value.makeIntegerValue((Integer) value); } else if (propertyDescriptor instanceof EnumeratedProperty) { From f65207639ba556207880a862d2e2581c9853efd4 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 30 Jun 2017 18:24:58 +0200 Subject: [PATCH 16/53] Removed a change to CollectionUtil --- .../sourceforge/pmd/util/CollectionUtil.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java index d7f63b9dc6..9b901ac614 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java @@ -289,28 +289,6 @@ public final class CollectionUtil { } - public static boolean areSemanticEquals(List a, List b) { - - if (a == null) { - return b == null || b.isEmpty(); - } - if (b == null) { - return a.isEmpty(); - } - - if (a.size() != b.size()) { - return false; - } - - for (int i = 0; i < a.size(); i++) { - if (!areEqual(a.get(i), b.get(i))) { - return false; - } - } - - return true; - } - /** * If the newValue is already held within the values array then the values * array is returned, otherwise a new array is created appending the From 50a2e9fdcfc64160a3dadb2cd3bdf3336e99cb9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Thu, 6 Jul 2017 17:48:41 -0300 Subject: [PATCH 17/53] Fix typeresolution for anonymous extending object - This is really an edge case, with little or no real-world scenarios, just fix it for completeness --- .../typedefinition/JavaTypeDefinition.java | 8 +++++++- .../typeresolution/ClassTypeResolverTest.java | 9 +++++++++ .../testdata/AnoymousExtendingObject.java | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java index e57306bcb9..cd8a2a15bc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java @@ -30,7 +30,13 @@ public class JavaTypeDefinition implements TypeDefinition { if (clazz.isAnonymousClass()) { // is this an anonymous class based on an interface or a class? if (clazz.getSuperclass() == Object.class) { - typeParameters = clazz.getInterfaces()[0].getTypeParameters(); + // is this based off an interface? + if (clazz.getInterfaces().length != 0) { + typeParameters = clazz.getInterfaces()[0].getTypeParameters(); + } else { + // This guy is just doing new Object() { ... } + typeParameters = clazz.getTypeParameters(); + } } else { typeParameters = clazz.getSuperclass().getTypeParameters(); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 4cb43afaa5..5a37f2b821 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -52,6 +52,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.ClassTypeResolver; import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition; import net.sourceforge.pmd.typeresolution.testdata.AnonymousClassFromInterface; import net.sourceforge.pmd.typeresolution.testdata.AnonymousInnerClass; +import net.sourceforge.pmd.typeresolution.testdata.AnoymousExtendingObject; import net.sourceforge.pmd.typeresolution.testdata.ArrayListFound; import net.sourceforge.pmd.typeresolution.testdata.DefaultJavaLangImport; import net.sourceforge.pmd.typeresolution.testdata.EnumWithAnonymousInnerClass; @@ -192,6 +193,14 @@ public class ClassTypeResolverTest { Assert.assertTrue(Converter.class.isAssignableFrom(child.getType())); Assert.assertSame(String.class, child.getTypeDefinition().getGenericType(0).getType()); } + + @Test + public void testAnoymousExtendingObject() throws Exception { + Node acu = parseAndTypeResolveForClass(AnoymousExtendingObject.class, "1.8"); + ASTAllocationExpression allocationExpression = acu.getFirstDescendantOfType(ASTAllocationExpression.class); + TypeNode child = (TypeNode) allocationExpression.jjtGetChild(0); + Assert.assertTrue(Object.class.isAssignableFrom(child.getType())); + } @Test public void testAnonymousInnerClass() throws ClassNotFoundException { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java new file mode 100644 index 0000000000..8138551400 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java @@ -0,0 +1,17 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.typeresolution.testdata; + +public class AnoymousExtendingObject { + + public void foo() { + System.out.println(new Object() { + @Override + public String toString() { + return "Suprise!"; + } + }); + } +} From e56bf2a407b4358f735e85a345c58f40607ea51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Sat, 8 Jul 2017 17:10:56 -0300 Subject: [PATCH 18/53] Simplify solution --- .../typedefinition/JavaTypeDefinition.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java index cd8a2a15bc..86e8ea1689 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java @@ -29,14 +29,8 @@ public class JavaTypeDefinition implements TypeDefinition { // the anonymous class can't have generics, but we may be binding generics from super classes if (clazz.isAnonymousClass()) { // is this an anonymous class based on an interface or a class? - if (clazz.getSuperclass() == Object.class) { - // is this based off an interface? - if (clazz.getInterfaces().length != 0) { - typeParameters = clazz.getInterfaces()[0].getTypeParameters(); - } else { - // This guy is just doing new Object() { ... } - typeParameters = clazz.getTypeParameters(); - } + if (clazz.getInterfaces().length != 0) { + typeParameters = clazz.getInterfaces()[0].getTypeParameters(); } else { typeParameters = clazz.getSuperclass().getTypeParameters(); } From 5b53b73bb89f06c2cf5c8427730df4db0d5b2a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 12:04:22 +0200 Subject: [PATCH 19/53] Java, typeres: add method first phase tests --- .../typeresolution/ClassTypeResolverTest.java | 33 +++++++++++++++++++ .../testdata/MethodFirstPhase.java | 25 ++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index cfae4bc696..cb92268c0c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -16,6 +16,7 @@ import java.util.Comparator; import java.util.List; import java.util.StringTokenizer; +import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; import org.apache.commons.io.IOUtils; import org.jaxen.JaxenException; import org.junit.Assert; @@ -1206,6 +1207,38 @@ public class ClassTypeResolverTest { assertEquals("All expressions not tested", index, expressions.size()); } + + @Test + public void testMethodFirstPhase() throws JaxenException { + // ASTCompilationUnit acu = parseAndTypeResolveForClass15(Dummy.class); + ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodFirstPhase.class); + + List expressions = convertList( + acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"), + AbstractJavaTypeNode.class); + + int index = 0; + + // int a = subtype(10, 'a', null, new Integer[0]); + assertEquals(int.class, expressions.get(index).getType()); + assertEquals(int.class, getChildType(expressions.get(index), 0)); + assertEquals(int.class, getChildType(expressions.get(index++), 1)); + + // Exception b = vararg((Object) null); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + + // String c = vararg((Object[]) null); + assertEquals(String.class, expressions.get(index).getType()); + assertEquals(String.class, getChildType(expressions.get(index), 0)); + assertEquals(String.class, getChildType(expressions.get(index++), 1)); + + // Make sure we got them all + assertEquals("All expressions not tested", index, expressions.size()); + } + + private Class getChildType(Node node, int childIndex) { return ((TypeNode) node.jjtGetChild(childIndex)).getType(); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java new file mode 100644 index 0000000000..8840180f5c --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java @@ -0,0 +1,25 @@ +package net.sourceforge.pmd.typeresolution.testdata; + +import net.sourceforge.pmd.lang.java.rule.strings.InefficientEmptyStringCheckRule; + +public class MethodFirstPhase { + void test() { + // primitive, char, null, arrays + int a = subtype(10, 'a', null, new Integer[0]); + + Exception b = vararg((Object) null); + String c = vararg((Object[]) null); + } + + String vararg(Object... a) {return null;} + Exception vararg(Object a) {return null;} + + + Exception subtype(short a, int b, String c, Number[] d) { return null; } + + int subtype(long a, int b, String c, Number[] d) {return 0;} + + Exception subtype(long a, byte b, String c, Number[] d) { return null; } + + Exception subtype(long a, int b, String c, Double[] d) {return null; } +} From 1b52d46c2659c33595a1f5b4842e88688cb41e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 14:38:08 +0200 Subject: [PATCH 20/53] Java, typeres: add first phase method overoad resolution --- .../typeresolution/ClassTypeResolver.java | 116 +++++++++++++++++- .../lang/java/typeresolution/MethodType.java | 2 +- .../typeresolution/ClassTypeResolverTest.java | 5 - .../testdata/MethodFirstPhase.java | 22 ++-- 4 files changed, 121 insertions(+), 24 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index cbc437a345..2eeedef80e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -97,6 +97,27 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { private static final Map> PRIMITIVE_TYPES; private static final Map JAVA_LANG; + private static ArrayList> primitiveSubTypeOrder = new ArrayList>(); + private static ArrayList> boxedPrimitivesSubTypeOrder = new ArrayList<>(); + + static { + primitiveSubTypeOrder.add(double.class); + primitiveSubTypeOrder.add(float.class); + primitiveSubTypeOrder.add(long.class); + primitiveSubTypeOrder.add(int.class); + primitiveSubTypeOrder.add(short.class); + primitiveSubTypeOrder.add(byte.class); + primitiveSubTypeOrder.add(char.class); // this is here for convenience, not really in order + + boxedPrimitivesSubTypeOrder.add(Double.class); + boxedPrimitivesSubTypeOrder.add(Float.class); + boxedPrimitivesSubTypeOrder.add(Long.class); + boxedPrimitivesSubTypeOrder.add(Integer.class); + boxedPrimitivesSubTypeOrder.add(Short.class); + boxedPrimitivesSubTypeOrder.add(Byte.class); + boxedPrimitivesSubTypeOrder.add(Character.class); + } + static { // Note: Assumption here that primitives come from same parent // ClassLoader regardless of what ClassLoader we are passed @@ -406,12 +427,93 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { public JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, List typeArgs) { - // TODO: add overload resolution - if (methods.size() == 1) { - return methods.get(0).getReturnType(); - } else { - return null; + // TODO: add second and third phase + + if(methods.size() == 1) { + return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests } + + List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + if(selectedMethods.size() == 1) { + return selectedMethods.get(0).getReturnType(); + // TODO: select most specific method + } + } + + return null; + } + + private List selectMethodsFirstPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) + && (typeArgs == null || typeArgs.size() == 0)) { + // TODO: type interference + } + + if (argList == null) { + selectedMethods.add(methodType); + + // vararg methods are considered fixed arity here + } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { + // check subtypeability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + // try each arguments if it's subtypeable + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + if (!isSubtypeable(methodType.getParameterTypes().get(argIndex), + (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + + } + + } + + return selectedMethods; + } + + private boolean isSubtypeable(JavaTypeDefinition parameter, ASTExpression argument) { + return isSubtypeable(parameter, argument.getTypeDefinition()); + } + + private boolean isSubtypeable(JavaTypeDefinition parameter, JavaTypeDefinition argument) { + // null types are always applicable + if (argument.getType() == null) { + return true; + } + + // this covers arrays, simple class/interface cases + if (parameter.getType().isAssignableFrom(argument.getType())) { + return true; + } + + int indexOfParameter = primitiveSubTypeOrder.indexOf(parameter.getType()); + + if(indexOfParameter != -1) { + if (argument.getType() == char.class) { + if (indexOfParameter <= 3) { // <= 3 because short and byte are not compatible with char + return true; + } + } else { + int indexOfArg = primitiveSubTypeOrder.indexOf(argument.getType()); + if(indexOfArg != -1 && indexOfParameter <= indexOfArg) { + return true; + } + } + } + + return false; } /** @@ -522,6 +624,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return method.getTypeParameters().length != 0; } + private boolean isGeneric(Class clazz) { + return clazz.getTypeParameters().length != 0; + } + private int getArity(Method method) { return method.getParameterTypes().length; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java index a44caef8a1..ad9b872b1b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java @@ -29,7 +29,7 @@ public class MethodType { return returnType; } - public List getArgTypes() { + public List getParameterTypes() { return argTypes; } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index cb92268c0c..7101ece1b3 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -1229,11 +1229,6 @@ public class ClassTypeResolverTest { assertEquals(Exception.class, getChildType(expressions.get(index), 0)); assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); - // String c = vararg((Object[]) null); - assertEquals(String.class, expressions.get(index).getType()); - assertEquals(String.class, getChildType(expressions.get(index), 0)); - assertEquals(String.class, getChildType(expressions.get(index++), 1)); - // Make sure we got them all assertEquals("All expressions not tested", index, expressions.size()); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java index 8840180f5c..0c1b2dd9ed 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java @@ -1,25 +1,21 @@ package net.sourceforge.pmd.typeresolution.testdata; -import net.sourceforge.pmd.lang.java.rule.strings.InefficientEmptyStringCheckRule; - public class MethodFirstPhase { void test() { - // primitive, char, null, arrays - int a = subtype(10, 'a', null, new Integer[0]); + // primitive, char, simple + int a = subtype(10, 'a', ""); + // TODO: add null, array types - Exception b = vararg((Object) null); - String c = vararg((Object[]) null); + Exception b = vararg((Number) null); } - String vararg(Object... a) {return null;} - Exception vararg(Object a) {return null;} + String vararg(Number... a) {return null;} + Exception vararg(Number a) {return null;} - Exception subtype(short a, int b, String c, Number[] d) { return null; } + Exception subtype(short a, int b, String c) { return null; } - int subtype(long a, int b, String c, Number[] d) {return 0;} + int subtype(long a, int b, String c) {return 0;} - Exception subtype(long a, byte b, String c, Number[] d) { return null; } - - Exception subtype(long a, int b, String c, Double[] d) {return null; } + Exception subtype(long a, byte b, String c) { return null; } } From 877f9d1b712995825b640278d123f3a79df6cca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 16:52:59 +0200 Subject: [PATCH 21/53] Java, typeres: add most specific method resolution --- .../typeresolution/ClassTypeResolver.java | 64 +++++++++++++++++-- .../typeresolution/ClassTypeResolverTest.java | 36 ++++++++++- .../testdata/MethodMostSpecific.java | 29 +++++++++ 3 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 2eeedef80e..c37032b3d4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -435,15 +435,71 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { - if(selectedMethods.size() == 1) { - return selectedMethods.get(0).getReturnType(); - // TODO: select most specific method - } + return selectMostSpecificMethod(selectedMethods).getReturnType(); } return null; } + private MethodType selectMostSpecificMethod(List selectedMethods) { + + MethodType mostSpecific = selectedMethods.get(0); + + for (int methodIndex = 1; methodIndex < selectedMethods.size(); ++methodIndex) { + MethodType nextMethod = selectedMethods.get(methodIndex); + + if (checkSubtypeability(mostSpecific, nextMethod)) { + if (checkSubtypeability(nextMethod, mostSpecific)) { // both are maximally specific + mostSpecific = selectAmongMaximallySpecific(mostSpecific, nextMethod); + } else { + mostSpecific = nextMethod; + } + } + } + + return mostSpecific; + } + + + private MethodType selectAmongMaximallySpecific(MethodType first, MethodType second) { + if(isAbstract(first)) { + if(isAbstract(second)) { + // https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + // the bottom of the section is relevant here, we can't resolve this type + // TODO: resolve this + + return null; + } else { // second one isn't abstract + return second; + } + } else if(isAbstract(second)){ + return first; // first isn't abstract, second one is + } else { + throw new IllegalStateException("None of the maximally specific methods are abstract.\n" + + first.toString() + "\n" + second.toString()); + } + } + + private boolean isAbstract(MethodType method) { + return Modifier.isAbstract(method.getMethod().getModifiers()); + } + + + private boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) { + List subtypeableArgs = subtypeableMethod.getParameterTypes(); + List methodTypeArgs = method.getParameterTypes(); + + // TODO: add support for not matching arity methods + + for (int index = 0; index < subtypeableArgs.size(); ++index) { + if (!isSubtypeable(methodTypeArgs.get(index), subtypeableArgs.get(index))) { + return false; + } + } + + return true; + } + private List selectMethodsFirstPhase(List methodsToSearch, ASTArgumentList argList, List typeArgs) { List selectedMethods = new ArrayList<>(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 7101ece1b3..49d47fc339 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -11,12 +11,15 @@ import static org.junit.Assert.assertSame; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; +import java.util.AbstractCollection; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.StringTokenizer; import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; +import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific; import org.apache.commons.io.IOUtils; import org.jaxen.JaxenException; import org.junit.Assert; @@ -82,6 +85,8 @@ import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassA2; import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB; import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB2; +import javax.management.relation.RoleList; + public class ClassTypeResolverTest { @@ -1184,7 +1189,6 @@ public class ClassTypeResolverTest { @Test public void testMethodAccessibility() throws JaxenException { - // ASTCompilationUnit acu = parseAndTypeResolveForClass15(Dummy.class); ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodAccessibility.class); List expressions = convertList( @@ -1210,7 +1214,6 @@ public class ClassTypeResolverTest { @Test public void testMethodFirstPhase() throws JaxenException { - // ASTCompilationUnit acu = parseAndTypeResolveForClass15(Dummy.class); ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodFirstPhase.class); List expressions = convertList( @@ -1233,6 +1236,35 @@ public class ClassTypeResolverTest { assertEquals("All expressions not tested", index, expressions.size()); } + @Test + public void testMethodMostSpecific() throws JaxenException { + ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodMostSpecific.class); + + List expressions = convertList( + acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"), + AbstractJavaTypeNode.class); + + int index = 0; + + // String a = moreSpecific((Number) null, (AbstractCollection) null); + assertEquals(String.class, expressions.get(index).getType()); + assertEquals(String.class, getChildType(expressions.get(index), 0)); + assertEquals(String.class, getChildType(expressions.get(index++), 1)); + + // Exception b = moreSpecific((Integer) null, (AbstractList) null); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + + // int c = moreSpecific((Double) null, (RoleList) null); + assertEquals(int.class, expressions.get(index).getType()); + assertEquals(int.class, getChildType(expressions.get(index), 0)); + assertEquals(int.class, getChildType(expressions.get(index++), 1)); + + // Make sure we got them all + assertEquals("All expressions not tested", index, expressions.size()); + } + private Class getChildType(Node node, int childIndex) { return ((TypeNode) node.jjtGetChild(childIndex)).getType(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java new file mode 100644 index 0000000000..6787ffe0a0 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java @@ -0,0 +1,29 @@ +package net.sourceforge.pmd.typeresolution.testdata; + +import javax.management.relation.RoleList; +import java.util.AbstractCollection; +import java.util.AbstractList; +import java.util.ArrayList; + + +public abstract class MethodMostSpecific { + void test() { + // Hiararchy: Object, AbstractCollection, AbstractList, ArrayList, RoleList + + String a = moreSpecific((Number) null, (AbstractCollection) null); + Exception b = moreSpecific((Integer) null, (AbstractList) null); + int c = moreSpecific((Double) null, (RoleList) null); + } + + String moreSpecific(Number a, AbstractCollection b) { + return null; + } + + Exception moreSpecific(Integer a, AbstractList b) { + return null; + } + + int moreSpecific(Number a, ArrayList b) { + return 0; + } +} From 430486a761b74218b7915474c0630b3bc4970923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 17:32:10 +0200 Subject: [PATCH 22/53] Java, typeres: add second phase method resolution tests --- .../typeresolution/ClassTypeResolverTest.java | 46 +++++++++++++++++-- .../testdata/MethodSecondPhase.java | 30 ++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 49d47fc339..520a587d3a 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -11,8 +11,6 @@ import static org.junit.Assert.assertSame; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; -import java.util.AbstractCollection; -import java.util.AbstractList; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -20,6 +18,7 @@ import java.util.StringTokenizer; import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific; +import net.sourceforge.pmd.typeresolution.testdata.MethodSecondPhase; import org.apache.commons.io.IOUtils; import org.jaxen.JaxenException; import org.junit.Assert; @@ -85,8 +84,6 @@ import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassA2; import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB; import net.sourceforge.pmd.typeresolution.testdata.dummytypes.SuperClassB2; -import javax.management.relation.RoleList; - public class ClassTypeResolverTest { @@ -1265,6 +1262,47 @@ public class ClassTypeResolverTest { assertEquals("All expressions not tested", index, expressions.size()); } + @Test + public void testMethodSecondPhase() throws JaxenException { + ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodSecondPhase.class); + + List expressions = convertList( + acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"), + AbstractJavaTypeNode.class); + + int index = 0; + + // String a = boxing(10, ""); + assertEquals(String.class, expressions.get(index).getType()); + assertEquals(String.class, getChildType(expressions.get(index), 0)); + assertEquals(String.class, getChildType(expressions.get(index++), 1)); + // Exception b = boxing('a', ""); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + // int c = boxing(10L, ""); + assertEquals(int.class, expressions.get(index).getType()); + assertEquals(int.class, getChildType(expressions.get(index), 0)); + assertEquals(int.class, getChildType(expressions.get(index++), 1)); + + // String d = unboxing("", (Integer) null); + assertEquals(String.class, expressions.get(index).getType()); + assertEquals(String.class, getChildType(expressions.get(index), 0)); + assertEquals(String.class, getChildType(expressions.get(index++), 1)); + // Exception e = unboxing("", (Character) null); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + // int f = unboxing("", (Byte) null); + assertEquals(int.class, expressions.get(index).getType()); + assertEquals(int.class, getChildType(expressions.get(index), 0)); + assertEquals(int.class, getChildType(expressions.get(index++), 1)); + + // Make sure we got them all + assertEquals("All expressions not tested", index, expressions.size()); + } + + private Class getChildType(Node node, int childIndex) { return ((TypeNode) node.jjtGetChild(childIndex)).getType(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java new file mode 100644 index 0000000000..4e7c9e537b --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java @@ -0,0 +1,30 @@ +package net.sourceforge.pmd.typeresolution.testdata; + +public class MethodSecondPhase { + void test() { + // boxing and widening conversion + String a = boxing(10, ""); + // boxing + Exception b = boxing('a', ""); + // boxing and most specific + int c = boxing(10L, ""); + + // unboxing and widening conversion + String d = unboxing("", (Integer) null); + + Exception e = unboxing("", (Character) null); + int f = unboxing("", (Byte) null); + } + + String boxing(Number a, String b) {return null;} + + Exception boxing(Character a, String b) {return null;} + + int boxing(Long a, String b) {return 0;} + + String unboxing(String b, long a) {return null;} + + Exception unboxing(String b, char a) {return null;} + + int unboxing(String b, short a) {return 0;} +} From 65be8c6afb2fe25d515ebf8a43fa5c319d526b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 18:16:10 +0200 Subject: [PATCH 23/53] Java, typeres: add ethod resolution second phase --- .../typeresolution/ClassTypeResolver.java | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index c37032b3d4..618f563c29 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -429,7 +429,7 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { List typeArgs) { // TODO: add second and third phase - if(methods.size() == 1) { + if (methods.size() == 1) { return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests } @@ -438,6 +438,11 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return selectMostSpecificMethod(selectedMethods).getReturnType(); } + selectedMethods = selectMethodsSecondPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + return selectMostSpecificMethod(selectedMethods).getReturnType(); + } + return null; } @@ -462,21 +467,21 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { private MethodType selectAmongMaximallySpecific(MethodType first, MethodType second) { - if(isAbstract(first)) { - if(isAbstract(second)) { + if (isAbstract(first)) { + if (isAbstract(second)) { // https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 // the bottom of the section is relevant here, we can't resolve this type // TODO: resolve this - + return null; } else { // second one isn't abstract return second; } - } else if(isAbstract(second)){ + } else if (isAbstract(second)) { return first; // first isn't abstract, second one is } else { throw new IllegalStateException("None of the maximally specific methods are abstract.\n" - + first.toString() + "\n" + second.toString()); + + first.toString() + "\n" + second.toString()); } } @@ -539,6 +544,78 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return selectedMethods; } + private List selectMethodsSecondPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { + // TODO: look at type interference, weep again + } + + if (argList == null) { + selectedMethods.add(methodType); + + // vararg methods are considered fixed arity here + } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { + // check method convertability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + // try each arguments if it's method convertible + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + if (!isMethodConvertble(methodType.getParameterTypes().get(argIndex), + (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + } + + } + + return selectedMethods; + } + + private boolean isMethodConvertble(JavaTypeDefinition parameter, ASTExpression argument) { + return isMethodConvertible(parameter, argument.getTypeDefinition()); + } + + private boolean isMethodConvertible(JavaTypeDefinition parameter, JavaTypeDefinition argument) { + // covers identity conversion, widening primitive conversion, widening reference conversion, null + // covers if both are primitive or bot are boxed primitive + if (isSubtypeable(parameter, argument)) { + return true; + } + + // covers boxing + int indexInPrimitive = primitiveSubTypeOrder.indexOf(argument.getType()); + + if (indexInPrimitive != -1 // arg is primitive + && isSubtypeable(parameter, + JavaTypeDefinition.forClass(boxedPrimitivesSubTypeOrder.get(indexInPrimitive)))) { + return true; + } + + // covers unboxing + int indexInBoxed = boxedPrimitivesSubTypeOrder.indexOf(argument.getType()); + + if (indexInBoxed != -1 // arg is boxed primitive + && isSubtypeable(parameter, + JavaTypeDefinition.forClass(primitiveSubTypeOrder.get(indexInBoxed)))) { + return true; + } + + // TODO: add raw unchecked conversion part + + return false; + } + + private boolean isSubtypeable(JavaTypeDefinition parameter, ASTExpression argument) { return isSubtypeable(parameter, argument.getTypeDefinition()); } @@ -556,14 +633,14 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { int indexOfParameter = primitiveSubTypeOrder.indexOf(parameter.getType()); - if(indexOfParameter != -1) { + if (indexOfParameter != -1) { if (argument.getType() == char.class) { if (indexOfParameter <= 3) { // <= 3 because short and byte are not compatible with char return true; } } else { int indexOfArg = primitiveSubTypeOrder.indexOf(argument.getType()); - if(indexOfArg != -1 && indexOfParameter <= indexOfArg) { + if (indexOfArg != -1 && indexOfParameter <= indexOfArg) { return true; } } From 176ccb45336773b5fdd8d63bf7bb8366e2613759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 19:31:05 +0200 Subject: [PATCH 24/53] Java, typeres: add vararg tests for method resolution --- .../typeresolution/ClassTypeResolverTest.java | 29 +++++++++++++++++++ .../testdata/MethodThirdPhase.java | 21 ++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 520a587d3a..bcf0718658 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -18,6 +18,7 @@ import java.util.StringTokenizer; import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific; +import net.sourceforge.pmd.typeresolution.testdata.MethodThirdPhase; import net.sourceforge.pmd.typeresolution.testdata.MethodSecondPhase; import org.apache.commons.io.IOUtils; import org.jaxen.JaxenException; @@ -1302,6 +1303,34 @@ public class ClassTypeResolverTest { assertEquals("All expressions not tested", index, expressions.size()); } + @Test + public void testMethodThirdPhase() throws JaxenException { + ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodThirdPhase.class); + + List expressions = convertList( + acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"), + AbstractJavaTypeNode.class); + + int index = 0; + + // Exception a = vararg(10, (Number) null, (Number) null); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + // Exception b = vararg(10); + assertEquals(Exception.class, expressions.get(index).getType()); + assertEquals(Exception.class, getChildType(expressions.get(index), 0)); + assertEquals(Exception.class, getChildType(expressions.get(index++), 1)); + // int c = vararg(10, "", "", ""); + assertEquals(int.class, expressions.get(index).getType()); + assertEquals(int.class, getChildType(expressions.get(index), 0)); + assertEquals(int.class, getChildType(expressions.get(index++), 1)); + + // Make sure we got them all + assertEquals("All expressions not tested", index, expressions.size()); + } + + private Class getChildType(Node node, int childIndex) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java new file mode 100644 index 0000000000..c4d16965de --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java @@ -0,0 +1,21 @@ +package net.sourceforge.pmd.typeresolution.testdata; + +public class MethodThirdPhase { + void test() { + // more args than parameters + Exception a = vararg(10, (Number) null, (Number) null); + + // less args than parameters + Exception b = vararg(10); + + // component type determined properly + int c = vararg(10, "", "", ""); + + // TODO: add most specific tests among vararg conversion + + } + + Exception vararg(int a, Number... b) { return null; } + + int vararg(int a, String c, String... b) {return 0; } +} From 97f7f6a6de7f1a3bfdc3c14d649feeaeee14394b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 20:03:32 +0200 Subject: [PATCH 25/53] Java, typeres: add vararg method resolution --- .../typeresolution/ClassTypeResolver.java | 56 ++++++++++++++++++- .../lang/java/typeresolution/MethodType.java | 4 ++ .../typedefinition/JavaTypeDefinition.java | 10 ++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 618f563c29..e752f8c060 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -427,8 +427,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { public JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, List typeArgs) { - // TODO: add second and third phase - if (methods.size() == 1) { return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests } @@ -443,6 +441,14 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return selectMostSpecificMethod(selectedMethods).getReturnType(); } + selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + if(selectedMethods.size() == 1) { + return selectedMethods.get(0).getReturnType(); + // TODO: add selecting most specific vararg method + } + } + return null; } @@ -581,6 +587,52 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return selectedMethods; } + + private List selectMethodsThirdPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { + // TODO: look at type interference, weep again + } + + if (argList == null) { + selectedMethods.add(methodType); + + // now we consider varargs as not fixed arity + } else { // check subtypeability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + List methodParameters = methodType.getParameterTypes(); + JavaTypeDefinition varargComponentType = methodType.getVarargComponentType(); + + // try each arguments if it's method convertible + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + JavaTypeDefinition parameterType = argIndex < methodParameters.size() - 1 + ? methodParameters.get(argIndex) : varargComponentType; + + if (!isMethodConvertble(parameterType, (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + + // TODO: If k != n, or if k = n and An cannot be converted by method invocation conversion to + // Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation. + + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + } + } + + return selectedMethods; + } + + private boolean isMethodConvertble(JavaTypeDefinition parameter, ASTExpression argument) { return isMethodConvertible(parameter, argument.getTypeDefinition()); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java index ad9b872b1b..c3da11906f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java @@ -36,4 +36,8 @@ public class MethodType { public Method getMethod() { return method; } + + public JavaTypeDefinition getVarargComponentType() { + return argTypes.get(argTypes.size() - 1).getComponentType(); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java index e57306bcb9..6a526be6e8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java @@ -166,4 +166,14 @@ public class JavaTypeDefinition implements TypeDefinition { // TODO : Shall we throw here? return forClass(Object.class); } + + public JavaTypeDefinition getComponentType() { + Class componentType = getType().getComponentType(); + + if(componentType == null) { + throw new IllegalStateException(getType().getSimpleName() + " is not an array type!"); + } + + return forClass(componentType); + } } From 979ef7c77c3c7c1cac8d94470878aee8003bdab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 22:29:52 +0200 Subject: [PATCH 26/53] Java, typeres: fix checkstyle issues --- .../typeresolution/ClassTypeResolver.java | 6 +-- .../typedefinition/JavaTypeDefinition.java | 38 +++++++++---------- .../typeresolution/ClassTypeResolverTest.java | 8 ++-- .../testdata/MethodFirstPhase.java | 25 +++++++++--- .../testdata/MethodMostSpecific.java | 6 ++- .../testdata/MethodSecondPhase.java | 28 +++++++++++--- .../testdata/MethodThirdPhase.java | 12 +++++- 7 files changed, 83 insertions(+), 40 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index e752f8c060..9565b80c89 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -443,7 +443,7 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { - if(selectedMethods.size() == 1) { + if (selectedMethods.size() == 1) { return selectedMethods.get(0).getReturnType(); // TODO: add selecting most specific vararg method } @@ -648,8 +648,8 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { int indexInPrimitive = primitiveSubTypeOrder.indexOf(argument.getType()); if (indexInPrimitive != -1 // arg is primitive - && isSubtypeable(parameter, - JavaTypeDefinition.forClass(boxedPrimitivesSubTypeOrder.get(indexInPrimitive)))) { + && isSubtypeable(parameter, + JavaTypeDefinition.forClass(boxedPrimitivesSubTypeOrder.get(indexInPrimitive)))) { return true; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java index 6a526be6e8..613350ee98 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typedefinition/JavaTypeDefinition.java @@ -21,7 +21,7 @@ public class JavaTypeDefinition implements TypeDefinition { private final Class clazz; private final List genericArgs; private final boolean isGeneric; - + private JavaTypeDefinition(final Class clazz) { this.clazz = clazz; @@ -37,7 +37,7 @@ public class JavaTypeDefinition implements TypeDefinition { } else { typeParameters = clazz.getTypeParameters(); } - + isGeneric = typeParameters.length != 0; if (isGeneric) { // Generics will be lazily loaded @@ -46,48 +46,48 @@ public class JavaTypeDefinition implements TypeDefinition { this.genericArgs = Collections.emptyList(); } } - + public static JavaTypeDefinition forClass(final Class clazz) { if (clazz == null) { return null; } - + final JavaTypeDefinition typeDef = CLASS_TYPE_DEF_CACHE.get(clazz); - + if (typeDef != null) { return typeDef; } - + final JavaTypeDefinition newDef = new JavaTypeDefinition(clazz); // We can only cache types without generics, since their values are context-based if (!newDef.isGeneric) { CLASS_TYPE_DEF_CACHE.put(clazz, newDef); } - + return newDef; } - + public static JavaTypeDefinition forClass(final Class clazz, final JavaTypeDefinition... boundGenerics) { if (clazz == null) { return null; } - + // With generics there is no cache final JavaTypeDefinition typeDef = new JavaTypeDefinition(clazz); for (final JavaTypeDefinition generic : boundGenerics) { typeDef.genericArgs.add(generic); } - + return typeDef; } - + @Override public Class getType() { return clazz; } - + public boolean isGeneric() { return !genericArgs.isEmpty(); } @@ -99,9 +99,9 @@ public class JavaTypeDefinition implements TypeDefinition { return getGenericType(i); } } - + throw new IllegalArgumentException("No generic parameter by name " + parameterName - + " on class " + clazz.getSimpleName()); + + " on class " + clazz.getSimpleName()); } public JavaTypeDefinition getGenericType(final int index) { @@ -112,7 +112,7 @@ public class JavaTypeDefinition implements TypeDefinition { return cachedDefinition; } } - + // Force the list to have enough elements for (int i = genericArgs.size(); i <= index; i++) { genericArgs.add(null); @@ -123,10 +123,10 @@ public class JavaTypeDefinition implements TypeDefinition { * Object.class is a right answer in those scenarios */ genericArgs.set(index, forClass(Object.class)); - + final TypeVariable typeVariable = clazz.getTypeParameters()[index]; final JavaTypeDefinition typeDefinition = resolveTypeDefinition(typeVariable.getBounds()[0]); - + // cache result genericArgs.set(index, typeDefinition); return typeDefinition; @@ -149,7 +149,7 @@ public class JavaTypeDefinition implements TypeDefinition { for (int i = 0; i < typeArguments.length; i++) { genericBounds[i] = resolveTypeDefinition(typeArguments[i]); } - + // TODO : is this cast safe? return forClass((Class) parameterizedType.getRawType(), genericBounds); } else if (type instanceof TypeVariable) { @@ -170,7 +170,7 @@ public class JavaTypeDefinition implements TypeDefinition { public JavaTypeDefinition getComponentType() { Class componentType = getType().getComponentType(); - if(componentType == null) { + if (componentType == null) { throw new IllegalStateException(getType().getSimpleName() + " is not an array type!"); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index bcf0718658..675791ba24 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -16,10 +16,6 @@ import java.util.Comparator; import java.util.List; import java.util.StringTokenizer; -import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; -import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific; -import net.sourceforge.pmd.typeresolution.testdata.MethodThirdPhase; -import net.sourceforge.pmd.typeresolution.testdata.MethodSecondPhase; import org.apache.commons.io.IOUtils; import org.jaxen.JaxenException; import org.junit.Assert; @@ -72,7 +68,11 @@ import net.sourceforge.pmd.typeresolution.testdata.FieldAccessSuper; import net.sourceforge.pmd.typeresolution.testdata.InnerClass; import net.sourceforge.pmd.typeresolution.testdata.Literals; import net.sourceforge.pmd.typeresolution.testdata.MethodAccessibility; +import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase; +import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific; import net.sourceforge.pmd.typeresolution.testdata.MethodPotentialApplicability; +import net.sourceforge.pmd.typeresolution.testdata.MethodSecondPhase; +import net.sourceforge.pmd.typeresolution.testdata.MethodThirdPhase; import net.sourceforge.pmd.typeresolution.testdata.NestedAnonymousClass; import net.sourceforge.pmd.typeresolution.testdata.Operators; import net.sourceforge.pmd.typeresolution.testdata.Promotion; diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java index 0c1b2dd9ed..9cca02ca08 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java @@ -1,3 +1,7 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.typeresolution.testdata; public class MethodFirstPhase { @@ -9,13 +13,24 @@ public class MethodFirstPhase { Exception b = vararg((Number) null); } - String vararg(Number... a) {return null;} - Exception vararg(Number a) {return null;} + String vararg(Number... a) { + return null; + } + + Exception vararg(Number a) { + return null; + } - Exception subtype(short a, int b, String c) { return null; } + Exception subtype(short a, int b, String c) { + return null; + } - int subtype(long a, int b, String c) {return 0;} + int subtype(long a, int b, String c) { + return 0; + } - Exception subtype(long a, byte b, String c) { return null; } + Exception subtype(long a, byte b, String c) { + return null; + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java index 6787ffe0a0..1c755ef7f0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java @@ -1,9 +1,13 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.typeresolution.testdata; -import javax.management.relation.RoleList; import java.util.AbstractCollection; import java.util.AbstractList; import java.util.ArrayList; +import javax.management.relation.RoleList; public abstract class MethodMostSpecific { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java index 4e7c9e537b..fa258b8dc0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java @@ -1,3 +1,7 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.typeresolution.testdata; public class MethodSecondPhase { @@ -16,15 +20,27 @@ public class MethodSecondPhase { int f = unboxing("", (Byte) null); } - String boxing(Number a, String b) {return null;} + String boxing(Number a, String b) { + return null; + } - Exception boxing(Character a, String b) {return null;} + Exception boxing(Character a, String b) { + return null; + } - int boxing(Long a, String b) {return 0;} + int boxing(Long a, String b) { + return 0; + } - String unboxing(String b, long a) {return null;} + String unboxing(String b, long a) { + return null; + } - Exception unboxing(String b, char a) {return null;} + Exception unboxing(String b, char a) { + return null; + } - int unboxing(String b, short a) {return 0;} + int unboxing(String b, short a) { + return 0; + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java index c4d16965de..290ed7cb03 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java @@ -1,3 +1,7 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.typeresolution.testdata; public class MethodThirdPhase { @@ -15,7 +19,11 @@ public class MethodThirdPhase { } - Exception vararg(int a, Number... b) { return null; } + Exception vararg(int a, Number... b) { + return null; + } - int vararg(int a, String c, String... b) {return 0; } + int vararg(int a, String c, String... b) { + return 0; + } } From 2a7fbc1d43f6571ac67364234045050cf04ff8d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sun, 9 Jul 2017 22:48:26 +0200 Subject: [PATCH 27/53] Java, typeres: put links to JLS sections for method resolution --- .../typeresolution/ClassTypeResolver.java | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 9565b80c89..c590fb9535 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -425,6 +425,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return super.visit(node, data); } + /** + * Searches a list of methods by trying the three phases of method overload resolution. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 + */ public JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, List typeArgs) { if (methods.size() == 1) { @@ -452,6 +456,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return null; } + /** + * Most specific method selection. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + */ private MethodType selectMostSpecificMethod(List selectedMethods) { MethodType mostSpecific = selectedMethods.get(0); @@ -472,6 +480,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { } + /** + * Select maximally specific method. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + */ private MethodType selectAmongMaximallySpecific(MethodType first, MethodType second) { if (isAbstract(first)) { if (isAbstract(second)) { @@ -511,6 +523,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return true; } + /** + * Look for methods be subtypeability. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.2 + */ private List selectMethodsFirstPhase(List methodsToSearch, ASTArgumentList argList, List typeArgs) { List selectedMethods = new ArrayList<>(); @@ -550,6 +566,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return selectedMethods; } + /** + * Look for methods be method conversion. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.3 + */ private List selectMethodsSecondPhase(List methodsToSearch, ASTArgumentList argList, List typeArgs) { List selectedMethods = new ArrayList<>(); @@ -588,6 +608,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { } + /** + * Look for methods considering varargs as well. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.4 + */ private List selectMethodsThirdPhase(List methodsToSearch, ASTArgumentList argList, List typeArgs) { List selectedMethods = new ArrayList<>(); @@ -637,6 +661,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return isMethodConvertible(parameter, argument.getTypeDefinition()); } + /** + * Method invocation conversion rules. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3 + */ private boolean isMethodConvertible(JavaTypeDefinition parameter, JavaTypeDefinition argument) { // covers identity conversion, widening primitive conversion, widening reference conversion, null // covers if both are primitive or bot are boxed primitive @@ -672,6 +700,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return isSubtypeable(parameter, argument.getTypeDefinition()); } + /** + * Subtypeability rules. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10 + */ private boolean isSubtypeable(JavaTypeDefinition parameter, JavaTypeDefinition argument) { // null types are always applicable if (argument.getType() == null) { @@ -702,8 +734,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { } /** - * Search outwards from a node the enclosing type declarations. Searching them and their supertypes - * for method + * This method looks for method invocations be simple name. + * It searches outwards class declarations and their supertypes and in the end, static method imports. + * Compiles a list of potentially applicable methods. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.1 */ private List getLocalApplicableMethods(TypeNode node, String methodName, List typeArguments, @@ -728,6 +762,9 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return foundMethods; } + /** + * Looks for potentially applicable methods in a given type definition. + */ public List getApplicableMethods(JavaTypeDefinition context, String methodName, List typeArguments, @@ -773,6 +810,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return result; } + /** + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1 + * Potential applicability. + */ public boolean isMethodApplicable(Method method, String methodName, int argArity, Class accessingClass, List typeArguments) { @@ -817,6 +858,9 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return method.getParameterTypes().length; } + /** + * This method can be called on a prefix + */ private ASTArguments getSuffixMethodArgs(Node node) { Node prefix = node.jjtGetParent(); @@ -1252,6 +1296,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return data; } + /** + * The reason arguments are not visited here, is because they will be visited once the method + * to which they are arguments to is resolved. + */ @Override public Object visit(ASTArguments node, Object data) { return data; From 4728eff5d6d4bd41d0eb157f55acabc595da6e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Tue, 11 Jul 2017 10:35:15 +0200 Subject: [PATCH 28/53] Java, typeres: move method typeresolution methods into a helper class --- .../typeresolution/ClassTypeResolver.java | 477 +---------------- .../lang/java/typeresolution/MethodType.java | 13 + .../typeresolution/MethodTypeResolution.java | 497 ++++++++++++++++++ 3 files changed, 515 insertions(+), 472 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index c590fb9535..059fe6e50c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -4,10 +4,11 @@ package net.sourceforge.pmd.lang.java.typeresolution; +import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.getApplicableMethods; +import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.getBestMethodReturnType; +import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.isMemberVisibleFromClass; + import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -84,6 +85,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin import net.sourceforge.pmd.lang.symboltable.NameOccurrence; import net.sourceforge.pmd.lang.symboltable.Scope; + // // Helpful reading: // http://www.janeg.ca/scjp/oper/promotions.html @@ -97,27 +99,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { private static final Map> PRIMITIVE_TYPES; private static final Map JAVA_LANG; - private static ArrayList> primitiveSubTypeOrder = new ArrayList>(); - private static ArrayList> boxedPrimitivesSubTypeOrder = new ArrayList<>(); - - static { - primitiveSubTypeOrder.add(double.class); - primitiveSubTypeOrder.add(float.class); - primitiveSubTypeOrder.add(long.class); - primitiveSubTypeOrder.add(int.class); - primitiveSubTypeOrder.add(short.class); - primitiveSubTypeOrder.add(byte.class); - primitiveSubTypeOrder.add(char.class); // this is here for convenience, not really in order - - boxedPrimitivesSubTypeOrder.add(Double.class); - boxedPrimitivesSubTypeOrder.add(Float.class); - boxedPrimitivesSubTypeOrder.add(Long.class); - boxedPrimitivesSubTypeOrder.add(Integer.class); - boxedPrimitivesSubTypeOrder.add(Short.class); - boxedPrimitivesSubTypeOrder.add(Byte.class); - boxedPrimitivesSubTypeOrder.add(Character.class); - } - static { // Note: Assumption here that primitives come from same parent // ClassLoader regardless of what ClassLoader we are passed @@ -425,314 +406,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return super.visit(node, data); } - /** - * Searches a list of methods by trying the three phases of method overload resolution. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 - */ - public JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, - List typeArgs) { - if (methods.size() == 1) { - return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests - } - - List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); - if (!selectedMethods.isEmpty()) { - return selectMostSpecificMethod(selectedMethods).getReturnType(); - } - - selectedMethods = selectMethodsSecondPhase(methods, arguments, typeArgs); - if (!selectedMethods.isEmpty()) { - return selectMostSpecificMethod(selectedMethods).getReturnType(); - } - - selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); - if (!selectedMethods.isEmpty()) { - if (selectedMethods.size() == 1) { - return selectedMethods.get(0).getReturnType(); - // TODO: add selecting most specific vararg method - } - } - - return null; - } - - /** - * Most specific method selection. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 - */ - private MethodType selectMostSpecificMethod(List selectedMethods) { - - MethodType mostSpecific = selectedMethods.get(0); - - for (int methodIndex = 1; methodIndex < selectedMethods.size(); ++methodIndex) { - MethodType nextMethod = selectedMethods.get(methodIndex); - - if (checkSubtypeability(mostSpecific, nextMethod)) { - if (checkSubtypeability(nextMethod, mostSpecific)) { // both are maximally specific - mostSpecific = selectAmongMaximallySpecific(mostSpecific, nextMethod); - } else { - mostSpecific = nextMethod; - } - } - } - - return mostSpecific; - } - - - /** - * Select maximally specific method. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 - */ - private MethodType selectAmongMaximallySpecific(MethodType first, MethodType second) { - if (isAbstract(first)) { - if (isAbstract(second)) { - // https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 - // the bottom of the section is relevant here, we can't resolve this type - // TODO: resolve this - - return null; - } else { // second one isn't abstract - return second; - } - } else if (isAbstract(second)) { - return first; // first isn't abstract, second one is - } else { - throw new IllegalStateException("None of the maximally specific methods are abstract.\n" - + first.toString() + "\n" + second.toString()); - } - } - - private boolean isAbstract(MethodType method) { - return Modifier.isAbstract(method.getMethod().getModifiers()); - } - - - private boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) { - List subtypeableArgs = subtypeableMethod.getParameterTypes(); - List methodTypeArgs = method.getParameterTypes(); - - // TODO: add support for not matching arity methods - - for (int index = 0; index < subtypeableArgs.size(); ++index) { - if (!isSubtypeable(methodTypeArgs.get(index), subtypeableArgs.get(index))) { - return false; - } - } - - return true; - } - - /** - * Look for methods be subtypeability. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.2 - */ - private List selectMethodsFirstPhase(List methodsToSearch, ASTArgumentList argList, - List typeArgs) { - List selectedMethods = new ArrayList<>(); - - for (MethodType methodType : methodsToSearch) { - if (isGeneric(methodType.getMethod().getDeclaringClass()) - && (typeArgs == null || typeArgs.size() == 0)) { - // TODO: type interference - } - - if (argList == null) { - selectedMethods.add(methodType); - - // vararg methods are considered fixed arity here - } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { - // check subtypeability of each argument to the corresponding parameter - boolean methodIsApplicable = true; - - // try each arguments if it's subtypeable - for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { - if (!isSubtypeable(methodType.getParameterTypes().get(argIndex), - (ASTExpression) argList.jjtGetChild(argIndex))) { - methodIsApplicable = false; - break; - } - // TODO: add unchecked conversion in an else if branch - } - - if (methodIsApplicable) { - selectedMethods.add(methodType); - } - - } - - } - - return selectedMethods; - } - - /** - * Look for methods be method conversion. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.3 - */ - private List selectMethodsSecondPhase(List methodsToSearch, ASTArgumentList argList, - List typeArgs) { - List selectedMethods = new ArrayList<>(); - - for (MethodType methodType : methodsToSearch) { - if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { - // TODO: look at type interference, weep again - } - - if (argList == null) { - selectedMethods.add(methodType); - - // vararg methods are considered fixed arity here - } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { - // check method convertability of each argument to the corresponding parameter - boolean methodIsApplicable = true; - - // try each arguments if it's method convertible - for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { - if (!isMethodConvertble(methodType.getParameterTypes().get(argIndex), - (ASTExpression) argList.jjtGetChild(argIndex))) { - methodIsApplicable = false; - break; - } - // TODO: add unchecked conversion in an else if branch - } - - if (methodIsApplicable) { - selectedMethods.add(methodType); - } - } - - } - - return selectedMethods; - } - - - /** - * Look for methods considering varargs as well. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.4 - */ - private List selectMethodsThirdPhase(List methodsToSearch, ASTArgumentList argList, - List typeArgs) { - List selectedMethods = new ArrayList<>(); - - for (MethodType methodType : methodsToSearch) { - if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { - // TODO: look at type interference, weep again - } - - if (argList == null) { - selectedMethods.add(methodType); - - // now we consider varargs as not fixed arity - } else { // check subtypeability of each argument to the corresponding parameter - boolean methodIsApplicable = true; - - List methodParameters = methodType.getParameterTypes(); - JavaTypeDefinition varargComponentType = methodType.getVarargComponentType(); - - // try each arguments if it's method convertible - for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { - JavaTypeDefinition parameterType = argIndex < methodParameters.size() - 1 - ? methodParameters.get(argIndex) : varargComponentType; - - if (!isMethodConvertble(parameterType, (ASTExpression) argList.jjtGetChild(argIndex))) { - methodIsApplicable = false; - break; - } - - // TODO: If k != n, or if k = n and An cannot be converted by method invocation conversion to - // Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation. - - // TODO: add unchecked conversion in an else if branch - } - - if (methodIsApplicable) { - selectedMethods.add(methodType); - } - } - } - - return selectedMethods; - } - - - private boolean isMethodConvertble(JavaTypeDefinition parameter, ASTExpression argument) { - return isMethodConvertible(parameter, argument.getTypeDefinition()); - } - - /** - * Method invocation conversion rules. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3 - */ - private boolean isMethodConvertible(JavaTypeDefinition parameter, JavaTypeDefinition argument) { - // covers identity conversion, widening primitive conversion, widening reference conversion, null - // covers if both are primitive or bot are boxed primitive - if (isSubtypeable(parameter, argument)) { - return true; - } - - // covers boxing - int indexInPrimitive = primitiveSubTypeOrder.indexOf(argument.getType()); - - if (indexInPrimitive != -1 // arg is primitive - && isSubtypeable(parameter, - JavaTypeDefinition.forClass(boxedPrimitivesSubTypeOrder.get(indexInPrimitive)))) { - return true; - } - - // covers unboxing - int indexInBoxed = boxedPrimitivesSubTypeOrder.indexOf(argument.getType()); - - if (indexInBoxed != -1 // arg is boxed primitive - && isSubtypeable(parameter, - JavaTypeDefinition.forClass(primitiveSubTypeOrder.get(indexInBoxed)))) { - return true; - } - - // TODO: add raw unchecked conversion part - - return false; - } - - - private boolean isSubtypeable(JavaTypeDefinition parameter, ASTExpression argument) { - return isSubtypeable(parameter, argument.getTypeDefinition()); - } - - /** - * Subtypeability rules. - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10 - */ - private boolean isSubtypeable(JavaTypeDefinition parameter, JavaTypeDefinition argument) { - // null types are always applicable - if (argument.getType() == null) { - return true; - } - - // this covers arrays, simple class/interface cases - if (parameter.getType().isAssignableFrom(argument.getType())) { - return true; - } - - int indexOfParameter = primitiveSubTypeOrder.indexOf(parameter.getType()); - - if (indexOfParameter != -1) { - if (argument.getType() == char.class) { - if (indexOfParameter <= 3) { // <= 3 because short and byte are not compatible with char - return true; - } - } else { - int indexOfArg = primitiveSubTypeOrder.indexOf(argument.getType()); - if (indexOfArg != -1 && indexOfParameter <= indexOfArg) { - return true; - } - } - } - - return false; - } - /** * This method looks for method invocations be simple name. * It searches outwards class declarations and their supertypes and in the end, static method imports. @@ -762,101 +435,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return foundMethods; } - /** - * Looks for potentially applicable methods in a given type definition. - */ - public List getApplicableMethods(JavaTypeDefinition context, - String methodName, - List typeArguments, - int argArity, - Class accessingClass) { - List result = new ArrayList<>(); - - if (context == null) { - return result; - } - - // TODO: shadowing, overriding - // TODO: add multiple upper bounds - - Class contextClass = context.getType(); - - // search the class - for (Method method : contextClass.getDeclaredMethods()) { - if (isMethodApplicable(method, methodName, argArity, accessingClass, typeArguments)) { - if (isGeneric(method)) { - // TODO: do generic methods - // this disables invocations which could match generic methods - result.clear(); - return result; - } - - result.add(getTypeDefOfMethod(context, method)); - } - } - - // search it's supertype - if (!contextClass.equals(Object.class)) { - result.addAll(getApplicableMethods(context.resolveTypeDefinition(contextClass.getGenericSuperclass()), - methodName, typeArguments, argArity, accessingClass)); - } - - // search it's interfaces - for (Type interfaceType : contextClass.getGenericInterfaces()) { - result.addAll(getApplicableMethods(context.resolveTypeDefinition(interfaceType), - methodName, typeArguments, argArity, accessingClass)); - } - - return result; - } - - /** - * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1 - * Potential applicability. - */ - public boolean isMethodApplicable(Method method, String methodName, int argArity, - Class accessingClass, List typeArguments) { - - if (method.getName().equals(methodName) // name matches - // is visible - && isMemberVisibleFromClass(method.getDeclaringClass(), method.getModifiers(), accessingClass) - // if method is vararg with arity n, then the invocation's arity >= n - 1 - && (!method.isVarArgs() || (argArity >= getArity(method) - 1)) - // if the method isn't vararg, then arity matches - && (method.isVarArgs() || (argArity == getArity(method))) - // isn't generic or arity of type arguments matches that of parameters - && (!isGeneric(method) || typeArguments == null - || method.getTypeParameters().length == typeArguments.size())) { - - return true; - } - - return false; - } - - private MethodType getTypeDefOfMethod(JavaTypeDefinition context, Method method) { - JavaTypeDefinition returnType = context.resolveTypeDefinition(method.getGenericReturnType()); - List argTypes = new ArrayList<>(); - - // search typeArgs vs - for (Type argType : method.getGenericParameterTypes()) { - argTypes.add(context.resolveTypeDefinition(argType)); - } - - return new MethodType(returnType, argTypes, method); - } - - private boolean isGeneric(Method method) { - return method.getTypeParameters().length != 0; - } - - private boolean isGeneric(Class clazz) { - return clazz.getTypeParameters().length != 0; - } - - private int getArity(Method method) { - return method.getParameterTypes().length; - } /** * This method can be called on a prefix @@ -971,51 +549,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return null; } - /** - * Given a class, the modifiers of on of it's member and the class that is trying to access that member, - * returns true is the member is accessible from the accessingClass Class. - * - * @param classWithMember The Class with the member. - * @param modifiers The modifiers of that member. - * @param accessingClass The Class trying to access the member. - * @return True if the member is visible from the accessingClass Class. - */ - private boolean isMemberVisibleFromClass(Class classWithMember, int modifiers, Class accessingClass) { - if (accessingClass == null) { - return false; - } - - // public members - if (Modifier.isPublic(modifiers)) { - return true; - } - - boolean areInTheSamePackage; - if (accessingClass.getPackage() != null) { - areInTheSamePackage = accessingClass.getPackage().getName().startsWith( - classWithMember.getPackage().getName()); - } else { - return false; // if the package information is null, we can't do nothin' - } - - // protected members - if (Modifier.isProtected(modifiers)) { - if (areInTheSamePackage || classWithMember.isAssignableFrom(accessingClass)) { - return true; - } - // private members - } else if (Modifier.isPrivate(modifiers)) { - if (classWithMember.equals(accessingClass)) { - return true; - } - // package private members - } else if (areInTheSamePackage) { - return true; - } - - return false; - } - @Override public Object visit(ASTFieldDeclaration node, Object data) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java index c3da11906f..ff5bd703fd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.java.typeresolution; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Collections; import java.util.List; @@ -37,7 +38,19 @@ public class MethodType { return method; } + public boolean isVararg() { + return method.isVarArgs(); + } + public JavaTypeDefinition getVarargComponentType() { + if (!isVararg()) { + throw new IllegalStateException("Method is not vararg: " + method.toString() + "!"); + } + return argTypes.get(argTypes.size() - 1).getComponentType(); } + + public boolean isAbstract() { + return Modifier.isAbstract(method.getModifiers()); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java new file mode 100644 index 0000000000..1168422692 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java @@ -0,0 +1,497 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.typeresolution; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition; + +public final class MethodTypeResolution { + private MethodTypeResolution() {} + + private static final List> PRIMITIVE_SUBTYPE_ORDER; + private static final List> BOXED_PRIMITIVE_SUBTYPE_ORDER; + + static { + List> primitiveList = new ArrayList<>(); + + primitiveList.add(double.class); + primitiveList.add(float.class); + primitiveList.add(long.class); + primitiveList.add(int.class); + primitiveList.add(short.class); + primitiveList.add(byte.class); + primitiveList.add(char.class); // this is here for convenience, not really in order + + PRIMITIVE_SUBTYPE_ORDER = Collections.unmodifiableList(primitiveList); + + List> boxedList = new ArrayList<>(); + + boxedList.add(Double.class); + boxedList.add(Float.class); + boxedList.add(Long.class); + boxedList.add(Integer.class); + boxedList.add(Short.class); + boxedList.add(Byte.class); + boxedList.add(Character.class); + + BOXED_PRIMITIVE_SUBTYPE_ORDER = Collections.unmodifiableList(boxedList); + } + + public static boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) { + List subtypeableArgs = subtypeableMethod.getParameterTypes(); + List methodTypeArgs = method.getParameterTypes(); + + // TODO: add support for not matching arity methods + + for (int index = 0; index < subtypeableArgs.size(); ++index) { + if (!isSubtypeable(methodTypeArgs.get(index), subtypeableArgs.get(index))) { + return false; + } + } + + return true; + } + + /** + * Look for methods be subtypeability. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.2 + */ + public static List selectMethodsFirstPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) + && (typeArgs == null || typeArgs.size() == 0)) { + // TODO: type interference + } + + if (argList == null) { + selectedMethods.add(methodType); + + // vararg methods are considered fixed arity here + } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { + // check subtypeability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + // try each arguments if it's subtypeable + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + if (!isSubtypeable(methodType.getParameterTypes().get(argIndex), + (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + + } + + } + + return selectedMethods; + } + + /** + * Look for methods be method conversion. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.3 + */ + public static List selectMethodsSecondPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { + // TODO: look at type interference, weep again + } + + if (argList == null) { + selectedMethods.add(methodType); + + // vararg methods are considered fixed arity here + } else if (getArity(methodType.getMethod()) == argList.jjtGetNumChildren()) { + // check method convertability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + // try each arguments if it's method convertible + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + if (!isMethodConvertble(methodType.getParameterTypes().get(argIndex), + (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + } + + } + + return selectedMethods; + } + + + /** + * Look for methods considering varargs as well. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.4 + */ + public static List selectMethodsThirdPhase(List methodsToSearch, ASTArgumentList argList, + List typeArgs) { + List selectedMethods = new ArrayList<>(); + + for (MethodType methodType : methodsToSearch) { + if (isGeneric(methodType.getMethod().getDeclaringClass()) && typeArgs.size() == 0) { + // TODO: look at type interference, weep again + } + + if (argList == null) { + selectedMethods.add(methodType); + + // now we consider varargs as not fixed arity + } else { // check subtypeability of each argument to the corresponding parameter + boolean methodIsApplicable = true; + + List methodParameters = methodType.getParameterTypes(); + JavaTypeDefinition varargComponentType = methodType.getVarargComponentType(); + + // try each arguments if it's method convertible + for (int argIndex = 0; argIndex < argList.jjtGetNumChildren(); ++argIndex) { + JavaTypeDefinition parameterType = argIndex < methodParameters.size() - 1 + ? methodParameters.get(argIndex) : varargComponentType; + + if (!isMethodConvertble(parameterType, (ASTExpression) argList.jjtGetChild(argIndex))) { + methodIsApplicable = false; + break; + } + + // TODO: If k != n, or if k = n and An cannot be converted by method invocation conversion to + // Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation. + + // TODO: add unchecked conversion in an else if branch + } + + if (methodIsApplicable) { + selectedMethods.add(methodType); + } + } + } + + return selectedMethods; + } + + + /** + * Searches a list of methods by trying the three phases of method overload resolution. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 + */ + public static JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, + List typeArgs) { + if (methods.size() == 1) { + return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests + } + + List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + return selectMostSpecificMethod(selectedMethods).getReturnType(); + } + + selectedMethods = selectMethodsSecondPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + return selectMostSpecificMethod(selectedMethods).getReturnType(); + } + + selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); + if (!selectedMethods.isEmpty()) { + if (selectedMethods.size() == 1) { + return selectedMethods.get(0).getReturnType(); + // TODO: add selecting most specific vararg method + } + } + + return null; + } + + /** + * Most specific method selection. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + */ + public static MethodType selectMostSpecificMethod(List selectedMethods) { + + MethodType mostSpecific = selectedMethods.get(0); + + for (int methodIndex = 1; methodIndex < selectedMethods.size(); ++methodIndex) { + MethodType nextMethod = selectedMethods.get(methodIndex); + + if (checkSubtypeability(mostSpecific, nextMethod)) { + if (checkSubtypeability(nextMethod, mostSpecific)) { // both are maximally specific + mostSpecific = selectAmongMaximallySpecific(mostSpecific, nextMethod); + } else { + mostSpecific = nextMethod; + } + } + } + + return mostSpecific; + } + + + /** + * Select maximally specific method. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + */ + public static MethodType selectAmongMaximallySpecific(MethodType first, MethodType second) { + if (first.isAbstract()) { + if (second.isAbstract()) { + // https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 + // the bottom of the section is relevant here, we can't resolve this type + // TODO: resolve this + + return null; + } else { // second one isn't abstract + return second; + } + } else if (second.isAbstract()) { + return first; // first isn't abstract, second one is + } else { + throw new IllegalStateException("None of the maximally specific methods are abstract.\n" + + first.toString() + "\n" + second.toString()); + } + } + + + /** + * Looks for potentially applicable methods in a given type definition. + */ + public static List getApplicableMethods(JavaTypeDefinition context, + String methodName, + List typeArguments, + int argArity, + Class accessingClass) { + List result = new ArrayList<>(); + + if (context == null) { + return result; + } + + // TODO: shadowing, overriding + // TODO: add multiple upper bounds + + Class contextClass = context.getType(); + + // search the class + for (Method method : contextClass.getDeclaredMethods()) { + if (isMethodApplicable(method, methodName, argArity, accessingClass, typeArguments)) { + if (isGeneric(method)) { + // TODO: do generic methods + // this disables invocations which could match generic methods + result.clear(); + return result; + } + + result.add(getTypeDefOfMethod(context, method)); + } + } + + // search it's supertype + if (!contextClass.equals(Object.class)) { + result.addAll(getApplicableMethods(context.resolveTypeDefinition(contextClass.getGenericSuperclass()), + methodName, typeArguments, argArity, accessingClass)); + } + + // search it's interfaces + for (Type interfaceType : contextClass.getGenericInterfaces()) { + result.addAll(getApplicableMethods(context.resolveTypeDefinition(interfaceType), + methodName, typeArguments, argArity, accessingClass)); + } + + return result; + } + + + public static MethodType getTypeDefOfMethod(JavaTypeDefinition context, Method method) { + JavaTypeDefinition returnType = context.resolveTypeDefinition(method.getGenericReturnType()); + List argTypes = new ArrayList<>(); + + // search typeArgs vs + for (Type argType : method.getGenericParameterTypes()) { + argTypes.add(context.resolveTypeDefinition(argType)); + } + + return new MethodType(returnType, argTypes, method); + } + + + /** + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1 + * Potential applicability. + */ + public static boolean isMethodApplicable(Method method, String methodName, int argArity, + Class accessingClass, List typeArguments) { + + if (method.getName().equals(methodName) // name matches + // is visible + && isMemberVisibleFromClass(method.getDeclaringClass(), method.getModifiers(), accessingClass) + // if method is vararg with arity n, then the invocation's arity >= n - 1 + && (!method.isVarArgs() || (argArity >= getArity(method) - 1)) + // if the method isn't vararg, then arity matches + && (method.isVarArgs() || (argArity == getArity(method))) + // isn't generic or arity of type arguments matches that of parameters + && (!isGeneric(method) || typeArguments == null + || method.getTypeParameters().length == typeArguments.size())) { + + return true; + } + + return false; + } + + + /** + * Given a class, the modifiers of on of it's member and the class that is trying to access that member, + * returns true is the member is accessible from the accessingClass Class. + * + * @param classWithMember The Class with the member. + * @param modifiers The modifiers of that member. + * @param accessingClass The Class trying to access the member. + * @return True if the member is visible from the accessingClass Class. + */ + public static boolean isMemberVisibleFromClass(Class classWithMember, int modifiers, Class accessingClass) { + if (accessingClass == null) { + return false; + } + + // public members + if (Modifier.isPublic(modifiers)) { + return true; + } + + boolean areInTheSamePackage; + if (accessingClass.getPackage() != null) { + areInTheSamePackage = accessingClass.getPackage().getName().startsWith( + classWithMember.getPackage().getName()); + } else { + return false; // if the package information is null, we can't do nothin' + } + + // protected members + if (Modifier.isProtected(modifiers)) { + if (areInTheSamePackage || classWithMember.isAssignableFrom(accessingClass)) { + return true; + } + // private members + } else if (Modifier.isPrivate(modifiers)) { + if (classWithMember.equals(accessingClass)) { + return true; + } + // package private members + } else if (areInTheSamePackage) { + return true; + } + + return false; + } + + public static boolean isGeneric(Method method) { + return method.getTypeParameters().length != 0; + } + + public static boolean isGeneric(Class clazz) { + return clazz.getTypeParameters().length != 0; + } + + public static int getArity(Method method) { + return method.getParameterTypes().length; + } + + public static boolean isMethodConvertble(JavaTypeDefinition parameter, ASTExpression argument) { + return isMethodConvertible(parameter, argument.getTypeDefinition()); + } + + /** + * Method invocation conversion rules. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3 + */ + public static boolean isMethodConvertible(JavaTypeDefinition parameter, JavaTypeDefinition argument) { + // covers identity conversion, widening primitive conversion, widening reference conversion, null + // covers if both are primitive or bot are boxed primitive + if (isSubtypeable(parameter, argument)) { + return true; + } + + // covers boxing + int indexInPrimitive = PRIMITIVE_SUBTYPE_ORDER.indexOf(argument.getType()); + + if (indexInPrimitive != -1 // arg is primitive + && isSubtypeable(parameter, + JavaTypeDefinition.forClass(BOXED_PRIMITIVE_SUBTYPE_ORDER.get(indexInPrimitive)))) { + return true; + } + + // covers unboxing + int indexInBoxed = BOXED_PRIMITIVE_SUBTYPE_ORDER.indexOf(argument.getType()); + + if (indexInBoxed != -1 // arg is boxed primitive + && isSubtypeable(parameter, + JavaTypeDefinition.forClass(PRIMITIVE_SUBTYPE_ORDER.get(indexInBoxed)))) { + return true; + } + + // TODO: add raw unchecked conversion part + + return false; + } + + + public static boolean isSubtypeable(JavaTypeDefinition parameter, ASTExpression argument) { + return isSubtypeable(parameter, argument.getTypeDefinition()); + } + + /** + * Subtypeability rules. + * https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.10 + */ + public static boolean isSubtypeable(JavaTypeDefinition parameter, JavaTypeDefinition argument) { + // null types are always applicable + if (argument.getType() == null) { + return true; + } + + // this covers arrays, simple class/interface cases + if (parameter.getType().isAssignableFrom(argument.getType())) { + return true; + } + + int indexOfParameter = PRIMITIVE_SUBTYPE_ORDER.indexOf(parameter.getType()); + + if (indexOfParameter != -1) { + if (argument.getType() == char.class) { + if (indexOfParameter <= 3) { // <= 3 because short and byte are not compatible with char + return true; + } + } else { + int indexOfArg = PRIMITIVE_SUBTYPE_ORDER.indexOf(argument.getType()); + if (indexOfArg != -1 && indexOfParameter <= indexOfArg) { + return true; + } + } + } + + return false; + } +} From 707fd9bdd05d004c85aa30d0d8d58a404fe122e2 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 11 Jul 2017 12:02:20 +0200 Subject: [PATCH 29/53] Removed choices from EnumeratedPropertyDescriptor --- .../pmd/EnumeratedPropertyDescriptor.java | 8 -------- .../rule/properties/EnumeratedMultiProperty.java | 13 ------------- .../lang/rule/properties/EnumeratedProperty.java | 12 ------------ .../EnumeratedPropertyDescriptorWrapper.java | 5 ----- 4 files changed, 38 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java index 53ffaabafc..1b4dc39913 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/EnumeratedPropertyDescriptor.java @@ -24,12 +24,4 @@ public interface EnumeratedPropertyDescriptor extends PropertyDescriptor mappings(); - - /** - * Returns a set of choice tuples if available. This is kept for compatibility with the eclipse plugin, even - * though it returns the same information as {@link #mappings()} (only it returns them ordered). - * - * @return An array of the label value mappings. The first column is the labels, the second is the value. - */ - Object[][] choices(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index aded3f9df0..d56e14832e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -114,18 +113,6 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty } - @Override - public Object[][] choices() { - Object[][] res = new Object[choicesByLabel.size()][2]; - int i = 0; - for (Entry e : choicesByLabel.entrySet()) { - res[i++][0] = e.getKey(); - res[i][1] = e.getValue(); - } - return res; - } - - @Override public Class type() { return valueType; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 4d154a4eda..fd386b6e67 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Collections; import java.util.Enumeration; import java.util.Map; -import java.util.Map.Entry; import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -111,17 +110,6 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty } - @Override - public Object[][] choices() { - Object[][] res = new Object[choicesByLabel.size()][2]; - int i = 0; - for (Entry e : choicesByLabel.entrySet()) { - res[i++][0] = e.getKey(); - res[i][1] = e.getValue(); - } - return res; - } - @Override /* default */ PropertyDescriptorWrapper getWrapper() { return new EnumeratedPropertyDescriptorWrapper<>(this); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java index df64f6c78c..46b71c98bc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java @@ -25,9 +25,4 @@ import net.sourceforge.pmd.EnumeratedPropertyDescriptor; } - @Override - public Object[][] choices() { - return ((EnumeratedPropertyDescriptor) propertyDescriptor).choices(); - } - } From 65ef499433b1aaf92347bf0732e939c7f91ed1ec Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 11 Jul 2017 12:09:02 +0200 Subject: [PATCH 30/53] Removed isRequired --- .../java/net/sourceforge/pmd/PropertyDescriptor.java | 9 --------- .../rule/properties/AbstractMultiValueProperty.java | 5 +---- .../pmd/lang/rule/properties/AbstractProperty.java | 11 ++--------- .../rule/properties/AbstractSingleValueProperty.java | 5 +---- .../rule/properties/PropertyDescriptorWrapper.java | 6 ------ 5 files changed, 4 insertions(+), 32 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index f3dfb8a662..342a12aacb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -76,15 +76,6 @@ public interface PropertyDescriptor extends Comparable> T defaultValue(); - /** - * Denotes whether the value is required before the rule can be executed. - * Has no meaning for primitive types such as booleans, ints, etc. - * - * @return boolean - */ - boolean isRequired(); - - /** * Validation function that returns a diagnostic error message for a sample * property value. Returns null if the value is acceptable. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 95b69b97de..0f46d52cb8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -81,10 +81,7 @@ import net.sourceforge.pmd.Rule; @Override public String propertyErrorFor(Rule rule) { List realValues = rule.getProperty(this); - if (realValues == null && !isRequired()) { - return null; - } - return errorFor(realValues); + return realValues == null ? null : errorFor(realValues); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index c7d8a307dc..1395c4f00a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -27,7 +27,6 @@ import net.sourceforge.pmd.util.StringUtil; private final String name; private final String description; - private final boolean isRequired; private final float uiOrder; @@ -48,7 +47,6 @@ import net.sourceforge.pmd.util.StringUtil; name = checkNotEmpty(theName, NAME); description = checkNotEmpty(theDescription, DESCRIPTION); - isRequired = false; // TODO - do we need this? uiOrder = theUIOrder; } @@ -67,12 +65,6 @@ import net.sourceforge.pmd.util.StringUtil; } - @Override - public boolean isRequired() { - return isRequired; - } - - @Override public float uiOrder() { return uiOrder; @@ -162,6 +154,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @return A wrapper for this property. */ - /* default */ abstract PropertyDescriptorWrapper getWrapper(); + /* default */ + abstract PropertyDescriptorWrapper getWrapper(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 1d01801f16..d1f37748be 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -71,10 +71,7 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; @Override public String propertyErrorFor(Rule rule) { T realValue = rule.getProperty(this); - if (realValue == null && !isRequired()) { - return null; - } - return errorFor(realValue); + return realValue == null ? null : errorFor(realValue); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index 3aa8f2693b..00947d4869 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -68,12 +68,6 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } - @Override - public boolean isRequired() { - return propertyDescriptor.isRequired(); - } - - @Override public String name() { return propertyDescriptor.name(); From ac50d9a47f5f4e8375986d51e70ae7a43412a554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 11 Jul 2017 15:55:56 -0300 Subject: [PATCH 31/53] Update changelog, refs #492 --- src/site/markdown/overview/changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 748888cd37..ee74962950 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -33,7 +33,8 @@ CPD will therefore have less false positives and false negatives. As part of Google Summer of Code 2017, [Bendegúz Nagy](https://github.com/WinterGrascph)'s work on type resolution for Java continues. For this release he has extended support for method calls. -Method shadowing and overloading are still work in progress, but expect it to be fully supported soon enough. +Method shadowing and overloading are supported, as is varargs management. However, the selection of the target method upon the presence +of generics and type inference is still work in progress. Expect it in forecoming releases. #### Modified Rules @@ -69,4 +70,5 @@ Method shadowing and overloading are still work in progress, but expect it to be * [#420](https://github.com/pmd/pmd/pull/420): \[java] Fix UR anomaly in assert statements - [Clément Fournier](https://github.com/oowekyala) * [#484](https://github.com/pmd/pmd/pull/484): \[core] Changed linux usage to a more unix like path - [patriksevallius](https://github.com/patriksevallius) * [#486](https://github.com/pmd/pmd/pull/486): \[java] Add basic method typeresolution - [Bendegúz Nagy](https://github.com/WinterGrascph) +* [#492](https://github.com/pmd/pmd/pull/492): \[java] Typeresolution for overloaded methods - [Bendegúz Nagy](https://github.com/WinterGrascph) From 1f0908388b14b7707db14d01d85d8fb1788d2367 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 17:40:47 +0200 Subject: [PATCH 32/53] Added some tests --- .../properties/AbstractNumericProperty.java | 89 ++-- .../properties/EnumeratedMultiProperty.java | 5 +- .../properties/PropertyDescriptorFactory.java | 4 +- .../rule/properties/StringMultiProperty.java | 9 +- .../lang/rule/properties/TypeProperty.java | 6 +- .../AbstractPropertyDescriptorTester.java | 478 +++++++++--------- .../pmd/properties/LongPropertyTest.java | 74 +++ .../NonRuleWithAllPropertyTypes.java | 2 +- .../SimpleEnumeratedPropertyTest.java | 119 ++++- 9 files changed, 485 insertions(+), 301 deletions(-) create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 4f27829d8a..9b02b00167 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -28,11 +28,11 @@ import net.sourceforge.pmd.PropertyDescriptorField; = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, new Boolean[] {true, true}); - private Number lowerLimit; - private Number upperLimit; + private T lowerLimit; + private T upperLimit; - protected AbstractNumericProperty(String theName, String theDescription, Number lower, Number upper, T theDefault, + protected AbstractNumericProperty(String theName, String theDescription, T lower, T upper, T theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); @@ -42,6 +42,55 @@ import net.sourceforge.pmd.PropertyDescriptorField; lowerLimit = lower; upperLimit = upper; + + checkNumber(lowerLimit); + checkNumber(upperLimit); + checkNumber(theDefault); + } + + + 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; + } + + + /** + * Returns a string representing the range defined by the two bounds. + * + * @param low Lower bound + * @param up Upper bound + * + * @return String + */ + static String rangeString(Number low, Number up) { + return "(" + low + " -> " + up + ")"; } @@ -67,40 +116,6 @@ import net.sourceforge.pmd.PropertyDescriptorField; } - /** - * 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) { - - double number = value.doubleValue(); - - if (number > upperLimit.doubleValue() || number < lowerLimit.doubleValue()) { - return value + " is out of range " + rangeString(lowerLimit, upperLimit); - } - - return null; - } - - - /** - * Returns a string representing the range defined by the two bounds. - * - * @param low Lower bound - * @param up Upper bound - * - * @return String - */ - static String rangeString(Number low, Number up) { - return "(" + low + " -> " + up + ")"; - } - - @Override protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index d56e14832e..b1725fce85 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -142,11 +142,8 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty private E choiceFrom(String label) { - if (StringUtil.isEmpty(label)) { - return null; - } E result = choicesByLabel.get(label); - if (result == null) { + if (label == null || result == null) { throw new IllegalArgumentException(label); } return result; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index f8df5817f1..c7aa47e0cb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -90,8 +90,8 @@ public class PropertyDescriptorFactory { checkMinMax(name, type, min, max); IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, 0.0f); - return new IntegerMultiProperty(name, description, IntegerProperty.intFrom(min), - IntegerProperty.intFrom(max), property.valueFrom(value), 0.0f); + return new IntegerMultiProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), + ValueParser.INTEGER_PARSER.valueOf(max), property.valueFrom(value), 0.0f); } else if ("Long".equals(type)) { checkMinMax(name, type, min, max); return new LongProperty(name, description, min, max, value, 0.0f); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 4030eae324..56b4b3687b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -112,11 +112,11 @@ public final class StringMultiProperty extends AbstractMultiValueProperty { } - // TODO:cf deprecate this + /** + * Deprecated. + * + * @deprecated + */ public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, float theUIOrder) { this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index aa978f1b89..e1754c07b4 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -40,41 +40,235 @@ public abstract class AbstractPropertyDescriptorTester { private static final int MULTI_VALUE_COUNT = 10; protected final String typeName; + public AbstractPropertyDescriptorTester(String typeName) { this.typeName = typeName; } + + protected abstract PropertyDescriptor> createBadMultiProperty(); + + + @Test + public void testFactorySingleValue() { + PropertyDescriptor prop = getSingleFactory().createWith(getPropertyDescriptorValues()); + T originalValue = createValue(); + T value = prop.valueFrom( + originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); + String asDelimitedString = prop.asDelimitedString(value); + Object value2 = prop.valueFrom(asDelimitedString); + assertEquals(value, value2); + } + + + @SuppressWarnings("unchecked") + protected final PropertyDescriptorFactory getSingleFactory() { + return (PropertyDescriptorFactory) PropertyDescriptorUtil.factoryFor(typeName); + } + + + private Map getPropertyDescriptorValues() { + Map valuesById = new HashMap<>(); + valuesById.put(PropertyDescriptorField.NAME, "test"); + valuesById.put(PropertyDescriptorField.DESCRIPTION, "desc"); + valuesById.put(PropertyDescriptorField.MIN, "0"); + valuesById.put(PropertyDescriptorField.MAX, "10"); + return valuesById; + } + + + /** + * Return a legal value(s) per the general scope of the descriptor. + * + * @return Object + */ + protected abstract T createValue(); + + + @Test + public void testFactoryMultiValueDefaultDelimiter() { + PropertyDescriptorFactory> multiFactory = getMultiFactory(); + PropertyDescriptor> prop = multiFactory.createWith(getPropertyDescriptorValues()); + List originalValue = createMultipleValues(MULTI_VALUE_COUNT); + String asDelimitedString = prop.asDelimitedString(originalValue); + List value2 = prop.valueFrom(asDelimitedString); + assertEquals(originalValue, value2); + } + + + @SuppressWarnings("unchecked") + protected final PropertyDescriptorFactory> getMultiFactory() { + return (PropertyDescriptorFactory>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); + } + + + private List createMultipleValues(int count) { + List res = new ArrayList<>(); + while (count > 0) { + res.add(createValue()); + count--; + } + return res; + } + + + @Test + public void testFactoryMultiValueCustomDelimiter() { + PropertyDescriptorFactory> multiFactory = getMultiFactory(); + Map valuesById = getPropertyDescriptorValues(); + String customDelimiter = "ä"; + assertFalse(ALL_CHARS.contains(customDelimiter)); + valuesById.put(PropertyDescriptorField.DELIMITER, customDelimiter); + PropertyDescriptor> prop = multiFactory.createWith(valuesById); + List originalValue = createMultipleValues(MULTI_VALUE_COUNT); + String asDelimitedString = prop.asDelimitedString(originalValue); + List value2 = prop.valueFrom(asDelimitedString); + assertEquals(originalValue.toString(), value2.toString()); + assertEquals(originalValue, value2); + } + + + @Test + public void testConstructors() { + + PropertyDescriptor desc = createProperty(); + assertNotNull(desc); + + try { + createBadProperty(); + } catch (Exception ex) { + return; // caught ok + } + + fail("uncaught constructor exception"); + } + + + /** + * Creates and returns a properly configured property descriptor. + * + * @return PropertyDescriptor + */ + protected abstract PropertyDescriptor createProperty(); + + + /** + * Attempt to create a property with faulty configuration values. This + * method should throw an IllegalArgumentException if done correctly. + * + * @return PropertyDescriptor + */ + protected abstract PropertyDescriptor createBadProperty(); + + + @Test + public void testAsDelimitedString() { + + List testValue = createMultipleValues(MULTI_VALUE_COUNT); + PropertyDescriptor> pmdProp = createMultiProperty(); + + String storeValue = pmdProp.asDelimitedString(testValue); + List returnedValue = pmdProp.valueFrom(storeValue); + + assertEquals(returnedValue, testValue); + } + + + protected abstract PropertyDescriptor> createMultiProperty(); + + + @Test + public void testValueFrom() { + + T testValue = createValue(); + PropertyDescriptor pmdProp = createProperty(); + + String storeValue = pmdProp.asDelimitedString(testValue); + + T returnedValue = pmdProp.valueFrom(storeValue); + + assertEquals(returnedValue, testValue); + } + + + @Test + public void testErrorForCorrectSingle() { + T testValue = createValue(); + PropertyDescriptor pmdProp = createProperty(); // plain vanilla + // property & valid test value + String errorMsg = pmdProp.errorFor(testValue); + assertNull(errorMsg, errorMsg); + } + + + @Test + public void testErrorForCorrectMulti() { + List testMultiValues = createMultipleValues(MULTI_VALUE_COUNT); // multi-value property, all + // valid test values + PropertyDescriptor> multiProperty = createMultiProperty(); + String errorMsg = multiProperty.errorFor(testMultiValues); + assertNull(errorMsg, errorMsg); + + } + + + @Test + public void testErrorForBadSingle() { + T testValue = createBadValue(); + PropertyDescriptor pmdProp = createProperty(); // plain vanilla + // property & valid test value + String errorMsg = pmdProp.errorFor(testValue); + assertNotNull("uncaught bad value: " + testValue, errorMsg); + } + + + /** + * Return a value(s) that is known to be faulty per the general scope of the + * descriptor. + * + * @return Object + */ + protected abstract T createBadValue(); + + + @Test + public void testErrorForBadMulti() { + List testMultiValues = createMultipleBadValues(MULTI_VALUE_COUNT); // multi-value property, all + // valid test values + PropertyDescriptor> multiProperty = createMultiProperty(); + String errorMsg = multiProperty.errorFor(testMultiValues); + assertNotNull("uncaught bad value in: " + testMultiValues, errorMsg); + } + + + private List createMultipleBadValues(int count) { + List res = new ArrayList<>(); + while (count > 0) { + res.add(createBadValue()); + count--; + } + return res; + } + + + @Test + public void testType() { + assertNotNull(createMultiProperty().type()); + assertNotNull(createProperty().type()); + } + + public static boolean randomBool() { return ((Math.random() * 100) % 2) == 0; } - /** - * Method randomInt. - * - * @return int - */ + public static int randomInt() { int randomVal = (int) (Math.random() * 100 + 1D); return randomVal + (int) (Math.random() * 100000D); } - /** - * Method randomInt. - * - * @param min int - * @param max int - * - * @return int - */ - public static int randomInt(int min, int max) { - if (max < min) { - max = min; - } - int range = Math.abs(max - min); - int x = (int) (range * Math.random()); - return x + min; - } public static String randomString(int length) { @@ -87,27 +281,28 @@ public abstract class AbstractPropertyDescriptorTester { return sb.toString(); } - /** - * Method randomFloat. - * - * @param min float - * @param max float - * - * @return float - */ + + public static char randomChar(char[] characters) { + return characters[randomInt(0, characters.length - 1)]; + } + + + public static int randomInt(int min, int max) { + if (max < min) { + max = min; + } + int range = Math.abs(max - min); + int x = (int) (range * Math.random()); + return x + min; + } + + public static float randomFloat(float min, float max) { return (float) randomDouble(min, max); } - /** - * Method randomDouble. - * - * @param min double - * @param max double - * - * @return double - */ + public static double randomDouble(double min, double max) { if (max < min) { max = min; @@ -117,17 +312,17 @@ public abstract class AbstractPropertyDescriptorTester { return x + min; } - /** - * Method randomChar. - * - * @param characters char[] - * - * @return char - */ - public static char randomChar(char[] characters) { - return characters[randomInt(0, characters.length - 1)]; + + public static long randomLong(long min, long max) { + if (max < min) { + max = min; + } + long range = Math.abs(max - min); + long x = (long) (range * Math.random()); + return x + min; } + /** * Method randomChoice. * @@ -139,6 +334,7 @@ public abstract class AbstractPropertyDescriptorTester { return items[randomInt(0, items.length - 1)]; } + /** * Method filter. * @@ -164,194 +360,4 @@ public abstract class AbstractPropertyDescriptorTester { } return results; } - - /** - * Return a legal value(s) per the general scope of the descriptor. - * - * @return Object - */ - protected abstract T createValue(); - - private List createMultipleValues(int count) { - List res = new ArrayList<>(); - while (count > 0) { - res.add(createValue()); - count--; - } - return res; - } - - /** - * Return a value(s) that is known to be faulty per the general scope of the - * descriptor. - * - * @return Object - */ - protected abstract T createBadValue(); - - private List createMultipleBadValues(int count) { - List res = new ArrayList<>(); - while (count > 0) { - res.add(createBadValue()); - count--; - } - return res; - } - - /** - * Creates and returns a properly configured property descriptor. - * - * @return PropertyDescriptor - */ - protected abstract PropertyDescriptor createProperty(); - - protected abstract PropertyDescriptor> createMultiProperty(); - - /** - * Attempt to create a property with faulty configuration values. This - * method should throw an IllegalArgumentException if done correctly. - * - * @return PropertyDescriptor - */ - protected abstract PropertyDescriptor createBadProperty(); - - protected abstract PropertyDescriptor> createBadMultiProperty(); - - @SuppressWarnings("unchecked") - protected final PropertyDescriptorFactory getSingleFactory() { - return (PropertyDescriptorFactory) PropertyDescriptorUtil.factoryFor(typeName); - } - - @SuppressWarnings("unchecked") - protected final PropertyDescriptorFactory> getMultiFactory() { - return (PropertyDescriptorFactory>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); - } - - private Map getPropertyDescriptorValues() { - Map valuesById = new HashMap<>(); - valuesById.put(PropertyDescriptorField.NAME, "test"); - valuesById.put(PropertyDescriptorField.DESCRIPTION, "desc"); - valuesById.put(PropertyDescriptorField.MIN, "0"); - valuesById.put(PropertyDescriptorField.MAX, "10"); - return valuesById; - } - - @Test - public void testFactorySingleValue() { - PropertyDescriptor prop = getSingleFactory().createWith(getPropertyDescriptorValues()); - T originalValue = createValue(); - T value = prop.valueFrom( - originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); - String asDelimitedString = prop.asDelimitedString(value); - Object value2 = prop.valueFrom(asDelimitedString); - assertEquals(value, value2); - } - - @Test - public void testFactoryMultiValueDefaultDelimiter() { - PropertyDescriptorFactory> multiFactory = getMultiFactory(); - PropertyDescriptor> prop = multiFactory.createWith(getPropertyDescriptorValues()); - List originalValue = createMultipleValues(MULTI_VALUE_COUNT); - String asDelimitedString = prop.asDelimitedString(originalValue); - List value2 = prop.valueFrom(asDelimitedString); - assertEquals(originalValue, value2); - } - - @Test - public void testFactoryMultiValueCustomDelimiter() { - PropertyDescriptorFactory> multiFactory = getMultiFactory(); - Map valuesById = getPropertyDescriptorValues(); - String customDelimiter = "ä"; - assertFalse(ALL_CHARS.contains(customDelimiter)); - valuesById.put(PropertyDescriptorField.DELIMITER, customDelimiter); - PropertyDescriptor> prop = multiFactory.createWith(valuesById); - List originalValue = createMultipleValues(MULTI_VALUE_COUNT); - String asDelimitedString = prop.asDelimitedString(originalValue); - List value2 = prop.valueFrom(asDelimitedString); - assertEquals(originalValue.toString(), value2.toString()); - assertEquals(originalValue, value2); - } - - @Test - public void testConstructors() { - - PropertyDescriptor desc = createProperty(); - assertNotNull(desc); - - try { - createBadProperty(); - } catch (Exception ex) { - return; // caught ok - } - - fail("uncaught constructor exception"); - } - - @Test - public void testAsDelimitedString() { - - List testValue = createMultipleValues(MULTI_VALUE_COUNT); - PropertyDescriptor> pmdProp = createMultiProperty(); - - String storeValue = pmdProp.asDelimitedString(testValue); - List returnedValue = pmdProp.valueFrom(storeValue); - - assertEquals(returnedValue, testValue); - } - - @Test - public void testValueFrom() { - - T testValue = createValue(); - PropertyDescriptor pmdProp = createProperty(); - - String storeValue = pmdProp.asDelimitedString(testValue); - - T returnedValue = pmdProp.valueFrom(storeValue); - - assertEquals(returnedValue, testValue); - } - - @Test - public void testErrorForCorrectSingle() { - T testValue = createValue(); - PropertyDescriptor pmdProp = createProperty(); // plain vanilla - // property & valid test value - String errorMsg = pmdProp.errorFor(testValue); - assertNull(errorMsg, errorMsg); - } - - @Test - public void testErrorForCorrectMulti() { - List testMultiValues = createMultipleValues(MULTI_VALUE_COUNT); // multi-value property, all - // valid test values - PropertyDescriptor> multiProperty = createMultiProperty(); - String errorMsg = multiProperty.errorFor(testMultiValues); - assertNull(errorMsg, errorMsg); - - } - - @Test - public void testErrorForBadSingle() { - T testValue = createBadValue(); - PropertyDescriptor pmdProp = createProperty(); // plain vanilla - // property & valid test value - String errorMsg = pmdProp.errorFor(testValue); - assertNotNull("uncaught bad value: " + testValue, errorMsg); - } - - @Test - public void testErrorForBadMulti() { - List testMultiValues = createMultipleBadValues(MULTI_VALUE_COUNT); // multi-value property, all - // valid test values - PropertyDescriptor> multiProperty = createMultiProperty(); - String errorMsg = multiProperty.errorFor(testMultiValues); - assertNotNull("uncaught bad value in: " + testMultiValues, errorMsg); - } - - @Test - public void testType() { - PropertyDescriptor pmdProp = createProperty(); - assertNotNull(pmdProp.type()); - } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java new file mode 100644 index 0000000000..e3c1736214 --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java @@ -0,0 +1,74 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties; + +import java.util.List; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.lang.rule.properties.LongMultiProperty; +import net.sourceforge.pmd.lang.rule.properties.LongProperty; + +/** + * @author Clément Fournier + */ +public class LongPropertyTest extends AbstractPropertyDescriptorTester { + + private static final long MIN = 10L; + private static final long MAX = 11000L; + private static final long SHIFT = 300L; + + + public LongPropertyTest() { + super("Long"); + } + + + @Override + protected Long createValue() { + return randomLong(MIN, MAX); + } + + + @Override + protected Long createBadValue() { + return randomBool() ? randomLong(MIN - SHIFT, MIN) : randomLong(MAX, MAX + SHIFT); + } + + + @Override + protected PropertyDescriptor createProperty() { + return new LongProperty("testFloat", "Test float property", MIN, MAX, 90L, 1.0f); + } + + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new LongMultiProperty("testFloat", "Test float property", MIN, MAX, + new Long[] {-1000L, 0L, 100L, 20L}, 1.0f); + } + + + @Override + protected PropertyDescriptor createBadProperty() { + return new LongProperty("testFloat", "Test float property", 200L, -400L, 900L, 1.0f); + } + + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new LongMultiProperty("testFloat", "Test float property", 0L, 5L, + new Long[] {-1000L, 0L, 100L, 20L}, 1.0f); + } + + + public static LongProperty randomProperty(int nameLength, int descLength, boolean multiValue) { + + long defalt = randomLong(0, 1000); + + return new LongProperty(randomString(nameLength), randomString(descLength), defalt - 10000, defalt + 10000, + defalt, 0f); + } + +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java index 127eb80731..a8858d4b59 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java @@ -64,7 +64,7 @@ public class NonRuleWithAllPropertyTypes extends AbstractRule { 5.0f); public static final CharacterMultiProperty MULTI_CHAR = new CharacterMultiProperty("multiChar", "Multiple characters", new Character[] {'a', 'e', 'i', 'o', 'u'}, 6.0f, '|'); - public static final FloatProperty SINGLE_FLOAT = new FloatProperty("singleFloat", "Single float value", 9f, 10f, .9f, + public static final FloatProperty SINGLE_FLOAT = new FloatProperty("singleFloat", "Single float value", .9f, 10f, .9f, 5.0f); public static final FloatMultiProperty MULTI_FLOAT = new FloatMultiProperty("multiFloat", "Multiple float values", 0f, 5f, new Float[] {1f, 2f, 3f}, 6.0f); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index eee817b468..43fe10940c 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -4,14 +4,24 @@ package net.sourceforge.pmd.properties; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.Assume; import org.junit.Test; +import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; /** @@ -24,7 +34,18 @@ import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTester { private static final String[] KEYS = {"bar", "na", "bee", "coo"}; - private static final Foo[] VALUES = Foo.values(); + private static final Foo[] VALUES = {Foo.BAR, Foo.NA, Foo.BEE, Foo.COO}; + private static final Map MAPPINGS; + + + static { + Map map = new HashMap<>(); + map.put("bar", Foo.BAR); + map.put("na", Foo.NA); + map.put("bee", Foo.BEE); + map.put("coo", Foo.COO); + MAPPINGS = Collections.unmodifiableMap(map); + } public SimpleEnumeratedPropertyTest() { @@ -32,15 +53,35 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest } - @Override - protected Foo createValue() { - return randomChoice(Foo.values()); + @Test + @SuppressWarnings("unchecked") + public void testWrapper() { + EnumeratedPropertyDescriptor prop = (EnumeratedPropertyDescriptor) createProperty(); + EnumeratedPropertyDescriptor> multi = (EnumeratedPropertyDescriptor>) createMultiProperty(); + + EnumeratedPropertyDescriptor propW = null; + EnumeratedPropertyDescriptor> multiW = null; + try { + propW = (EnumeratedPropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); + multiW = (EnumeratedPropertyDescriptor>) PropertyDescriptorWrapper.getWrapper(multi); + } catch (ClassCastException ioe) { + fail(); + } + + assertEquals(prop.mappings(), propW.mappings()); + assertEquals(multi.mappings(), multiW.mappings()); + + } @Override - protected Foo createBadValue() { - return null; // not in the set of values + protected PropertyDescriptor createProperty() { + return new EnumeratedProperty<>("testEnumerations", + "Test enumerations with complex types", + KEYS, + VALUES, 0, Foo.class, + 1.0f); } @@ -54,13 +95,65 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest } + @Test + public void testMappings() { + EnumeratedPropertyDescriptor prop + = (EnumeratedPropertyDescriptor) createProperty(); + EnumeratedPropertyDescriptor> multi + = (EnumeratedPropertyDescriptor>) createMultiProperty(); + + assertEquals(MAPPINGS, prop.mappings()); + assertEquals(MAPPINGS, multi.mappings()); + } + + + @Test + public void testDefaultIndexOutOfBounds() { + try { + EnumeratedMultiProperty multi + = new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with simple type", + KEYS, VALUES, new int[] {99}, Foo.class, 1.0f); + } catch (IllegalArgumentException iae) { + return; + } + fail(); + } + + + @Test + public void testNoMappingForDefault() { + try { + EnumeratedMultiProperty multi + = new EnumeratedMultiProperty<>("testEnumerations", "Test enumerations with simple type", + MAPPINGS, Arrays.asList(Foo.IGNORED), Foo.class, 1.0f); + } catch (IllegalArgumentException iae) { + return; + } + fail(); + } + + + @Test + public void creationTest() { + PropertyDescriptor prop = createProperty(); + PropertyDescriptor> multi = createMultiProperty(); + + for (Map.Entry e : MAPPINGS.entrySet()) { + assertEquals(e.getValue(), prop.valueFrom(e.getKey())); + assertTrue(multi.valueFrom(e.getKey()).contains(e.getValue())); + } + } + + @Override - protected PropertyDescriptor createProperty() { - return new EnumeratedProperty<>("testEnumerations", - "Test enumerations with complex types", - KEYS, - VALUES, 0, Foo.class, - 1.0f); + protected Foo createValue() { + return randomChoice(Foo.values()); + } + + + @Override + protected Foo createBadValue() { + return null; // not in the set of values } @@ -100,6 +193,6 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest enum Foo { - BAR, NA, BEE, COO + BAR, NA, BEE, COO, IGNORED } } From 72d435f2f62896dd7fb68b076eaa494274b88e8d Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 18:07:23 +0200 Subject: [PATCH 33/53] Removed PropertyDescriptorFactory --- .../net/sourceforge/pmd/RuleSetFactory.java | 46 +----- .../net/sourceforge/pmd/RuleSetWriter.java | 27 ---- .../properties/PropertyDescriptorFactory.java | 145 ------------------ 3 files changed, 1 insertion(+), 217 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 50982078fa..0aff742b08 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -788,51 +788,7 @@ public class RuleSetFactory { return null; } - /** - * Parse a property node. - * - * @param rule - * The Rule to which the property should be added. //@param - * propertyNode Must be a property element node. - */ - // private static void parsePropertyNode(Rule rule, Node propertyNode) { - // Element propertyElement = (Element) propertyNode; - // String name = propertyElement.getAttribute("name"); - // String description = propertyElement.getAttribute("description"); - // String type = propertyElement.getAttribute("type"); - // String delimiter = propertyElement.getAttribute("delimiter"); - // String min = propertyElement.getAttribute("min"); - // String max = propertyElement.getAttribute("max"); - // String value = propertyElement.getAttribute("value"); - // - // // If value not provided, get from child element. - // if (StringUtil.isEmpty(value)) { - // for (int i = 0; i < propertyNode.getChildNodes().getLength(); i++) { - // Node node = propertyNode.getChildNodes().item(i); - // if ((node.getNodeType() == Node.ELEMENT_NODE) && - // node.getNodeName().equals("value")) { - // value = parseTextNode(node); - // } - // } - // } - // - // // Setting of existing property, or defining a new property? - // if (StringUtil.isEmpty(type)) { - // PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); - // if (propertyDescriptor == null) { - // throw new IllegalArgumentException("Cannot set non-existant property '" + - // name + "' on Rule " + rule.getName()); - // } else { - // Object realValue = propertyDescriptor.valueFrom(value); - // rule.setProperty(propertyDescriptor, realValue); - // } - // } else { - // PropertyDescriptor propertyDescriptor = - // PropertyDescriptorFactory.createPropertyDescriptor(name, description, - // type, delimiter, min, max, value); - // rule.definePropertyDescriptor(propertyDescriptor); - // } - // } + private static void setValue(Rule rule, PropertyDescriptor desc, String strValue) { T realValue = desc.valueFrom(strValue); rule.setProperty(desc, realValue); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 2b4f421db0..9d4d3e121d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -333,33 +333,6 @@ public class RuleSetWriter { return propertyElement; } - // private Element createPropertyDefinitionElement(PropertyDescriptor - // propertyDescriptor) { - // Element propertyElement = createPropertyValueElement(propertyDescriptor, - // propertyDescriptor.defaultValue()); - // - // propertyElement.setAttribute("description", - // propertyDescriptor.description()); - // String type = - // PropertyDescriptorFactory.getPropertyDescriptorType(propertyDescriptor); - // propertyElement.setAttribute("type", type); - // - // if (propertyDescriptor.isMultiValue()) { - // propertyElement.setAttribute("delimiter", - // String.valueOf(propertyDescriptor.multiValueDelimiter())); - // } - // - // if (propertyDescriptor instanceof AbstractNumericProperty) { - // propertyElement.setAttribute("min", - // String.valueOf(((AbstractNumericProperty) - // propertyDescriptor).lowerLimit())); - // propertyElement.setAttribute("max", - // String.valueOf(((AbstractNumericProperty) - // propertyDescriptor).upperLimit())); - // } - // - // return propertyElement; - // } private Element createPropertyDefinitionElementBR(PropertyDescriptor propertyDescriptor) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java deleted file mode 100644 index c7aa47e0cb..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.List; - -import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.util.StringUtil; - -// TODO: delete? It's not used anywhere, including the plugins (the only usage is a doc import in -// PropertyDescriptorWrapper -// I'm pretty sure the functionality of this class was superseded by PropertyDescriptorUtil at some point -public class PropertyDescriptorFactory { - - private PropertyDescriptorFactory() { } - - - /** - * Returns the String type of the PropertyDescriptor for use in XML - * serialization. If the value is null the type cannot be - * serialized. - */ - public static String getPropertyDescriptorType(PropertyDescriptor propertyDescriptor) { - Class type = propertyDescriptor.type(); - - String typeName = null; - // TODO - yes we can, investigate - if (propertyDescriptor instanceof EnumeratedProperty || propertyDescriptor instanceof MethodProperty - || propertyDescriptor instanceof TypeProperty) { - // Cannot serialize these kinds of PropertyDescriptors - } else if ("java.lang".equals(type.getPackage().getName())) { - typeName = type.getSimpleName(); - } - if (typeName == null) { - throw new IllegalArgumentException("Cannot encode type for PropertyDescriptor class: " + type.getName()); - } - if (propertyDescriptor.isMultiValue()) { - typeName = "List<" + typeName + ">"; // TODO:cf - } - - return typeName; - } - - - // TODO:cf Deprecate? PropertyDescriptors can already be made from a map - public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { - return new PropertyDescriptorWrapper<>( - createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); - } - - - private static PropertyDescriptor createRawPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { - if ("Boolean".equals(type)) { - return new BooleanProperty(name, description, value, 0.0f); - } else if ("List".equals(type)) { - BooleanMultiProperty property = new BooleanMultiProperty(name, description, (List) null, 0.0f); - return new BooleanMultiProperty(name, description, property.valueFrom(value), 0.0f); - } else if ("Character".equals(type)) { - return new CharacterProperty(name, description, CharacterProperty.charFrom(value), 0.0f); - } else if ("List".equals(type)) { - checkDelimiter(name, type, delimiter); - char delim = delimiter.charAt(0); - CharacterMultiProperty property = new CharacterMultiProperty(name, description, (List) null, 0.0f, delim); - return new CharacterMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); - } else if ("Double".equals(type)) { - checkMinMax(name, type, min, max); - return new DoubleProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, (List) null, 0.0f); - return new DoubleMultiProperty(name, description, DoubleProperty.doubleFrom(min), - DoubleProperty.doubleFrom(max), property.valueFrom(value), 0.0f); - } else if ("Float".equals(type)) { - checkMinMax(name, type, min, max); - return new FloatProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); - return new FloatMultiProperty(name, description, FloatProperty.floatFrom(min), FloatProperty.floatFrom(max), - property.valueFrom(value), 0.0f); - } else if ("Integer".equals(type)) { - checkMinMax(name, type, min, max); - return new IntegerProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), ValueParser.INTEGER_PARSER.valueOf(max), - ValueParser.INTEGER_PARSER.valueOf(value), 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, - 0.0f); - return new IntegerMultiProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), - ValueParser.INTEGER_PARSER.valueOf(max), property.valueFrom(value), 0.0f); - } else if ("Long".equals(type)) { - checkMinMax(name, type, min, max); - return new LongProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); - return new LongMultiProperty(name, description, LongProperty.longFrom(min), LongProperty.longFrom(max), - property.valueFrom(value), 0.0f); - - // TODO - include legal package names for next four types - } else if ("Type".equals(type)) { - return new TypeProperty(name, description, value, (String[]) null, 0.0f); - } else if ("List".equals(type)) { - return new TypeMultiProperty(name, description, value, (String[]) null, 0.0f); - } else if ("Method".equals(type)) { - return new MethodProperty(name, description, value, (String[]) null, 0.0f); - } else if ("List".equals(type)) { - return new MethodMultiProperty(name, description, value, (String[]) null, 0.0f); - - } else if ("String".equals(type)) { - return new StringProperty(name, description, value, 0.0f); - } else if ("List".equals(type)) { - checkDelimiter(name, type, delimiter); - char delim = delimiter.charAt(0); - StringMultiProperty property = new StringMultiProperty(name, description, (String[]) null, 0.0f, delim); - return new StringMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); - } else { - throw new IllegalArgumentException("Cannot define property type '" + type + "'."); - } - } - - - private static void checkDelimiter(String name, String type, String delimiter) { - if (delimiter == null || delimiter.length() == 0) { - throw new IllegalArgumentException( - "Delimiter must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - } - - - private static void checkMinMax(String name, String type, String min, String max) { - if (StringUtil.isEmpty(min)) { - throw new IllegalArgumentException( - "Min must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - if (StringUtil.isEmpty(max)) { - throw new IllegalArgumentException( - "Max must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - } -} From 772875d13f9023c52b39f586cdca0de2034a246c Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 18:38:40 +0200 Subject: [PATCH 34/53] More tests --- .../lang/rule/properties/FloatProperty.java | 16 +---- .../lang/rule/properties/IntegerProperty.java | 10 --- .../lang/rule/properties/LongProperty.java | 14 +--- .../SingleValuePropertyDescriptorFactory.java | 2 +- .../lang/rule/properties/TypeProperty.java | 2 +- ...stractNumericPropertyDescriptorTester.java | 58 ++++++++++++++++ .../AbstractPropertyDescriptorTester.java | 66 +++++++++++++++++++ .../pmd/properties/DoublePropertyTest.java | 2 +- .../pmd/properties/MethodPropertyTest.java | 3 +- .../SimpleEnumeratedPropertyTest.java | 1 - 10 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 5db204c0d9..d7b8503d90 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -50,7 +50,7 @@ public final class FloatProperty extends AbstractNumericProperty { */ public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { - this(theName, theDescription, floatFrom(minStr), floatFrom(maxStr), floatFrom(defaultStr), theUIOrder); + this(theName, theDescription, FLOAT_PARSER.valueOf(minStr), FLOAT_PARSER.valueOf(maxStr), FLOAT_PARSER.valueOf(defaultStr), theUIOrder); } @@ -68,19 +68,7 @@ public final class FloatProperty extends AbstractNumericProperty { */ public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, float theUIOrder) { - super(theName, theDescription, Float.valueOf(min), Float.valueOf(max), Float.valueOf(theDefault), theUIOrder); - } - - - /** - * Parses a String into a Float. - * - * @param numberString String to parse - * - * @return Parsed Float - */ - public static Float floatFrom(String numberString) { - return FLOAT_PARSER.valueOf(numberString); + super(theName, theDescription, min, max, theDefault, theUIOrder); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 5658f289aa..bbe2e29bb7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -64,14 +64,4 @@ public final class IntegerProperty extends AbstractNumericProperty { } - /** - * Parses a String into an Integer. - * - * @param numberString String to parse - * - * @return Parsed Integer - */ - public static Integer intFrom(String numberString) { - return INTEGER_PARSER.valueOf(numberString); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index 7fbbe87581..a4adba5aa9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -51,7 +51,7 @@ public final class LongProperty extends AbstractNumericProperty { */ public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { - this(theName, theDescription, longFrom(minStr), longFrom(maxStr), longFrom(defaultStr), theUIOrder); + this(theName, theDescription, Long.valueOf(minStr), Long.valueOf(maxStr), Long.valueOf(defaultStr), theUIOrder); } @@ -72,18 +72,6 @@ public final class LongProperty extends AbstractNumericProperty { } - /** - * Parses a String into a Long. - * - * @param numberString String to parse - * - * @return Parsed Long - */ - public static Long longFrom(String numberString) { - return Long.valueOf(numberString); - } - - @Override public Class type() { return Long.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java index 16be34f0e6..beb4c70a30 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java @@ -35,7 +35,7 @@ public abstract class SingleValuePropertyDescriptorFactory extends BasicPrope @Override - public boolean isMultiValue() { + public final boolean isMultiValue() { return false; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index ac9b7a6e1f..884882a1a1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -89,7 +89,7 @@ public final class TypeProperty extends AbstractPackagedProperty { /** - * Deprecated. + * Deprecated constructor. * * @deprecated */ diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java new file mode 100644 index 0000000000..2b624b3cda --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java @@ -0,0 +1,58 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.Test; + +import net.sourceforge.pmd.NumericPropertyDescriptor; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; + +/** + * @author Clément Fournier + */ +public abstract class AbstractNumericPropertyDescriptorTester extends AbstractPropertyDescriptorTester { + + public AbstractNumericPropertyDescriptorTester(String typeName) { + super(typeName); + } + + + @Test + public void testLowerUpperLimit() { + assertNotNull(((NumericPropertyDescriptor) createProperty()).lowerLimit()); + assertNotNull(((NumericPropertyDescriptor) createProperty()).upperLimit()); + assertNotNull(((NumericPropertyDescriptor) createMultiProperty()).lowerLimit()); + assertNotNull(((NumericPropertyDescriptor) createMultiProperty()).upperLimit()); + } + + + @Test + @SuppressWarnings("unchecked") + public void testWrapper() { + NumericPropertyDescriptor prop = (NumericPropertyDescriptor) createProperty(); + NumericPropertyDescriptor> multi = (NumericPropertyDescriptor>) createMultiProperty(); + + NumericPropertyDescriptor propW = null; + NumericPropertyDescriptor> multiW = null; + try { + propW = (NumericPropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); + multiW = (NumericPropertyDescriptor>) PropertyDescriptorWrapper.getWrapper(multi); + } catch (ClassCastException ioe) { + fail(); + } + + assertEquals(prop.lowerLimit(), propW.lowerLimit()); + assertEquals(prop.upperLimit(), propW.upperLimit()); + assertEquals(multi.lowerLimit(), multiW.lowerLimit()); + assertEquals(multi.upperLimit(), multiW.upperLimit()); + } + +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index e1754c07b4..3831acb6f2 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -8,6 +8,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; @@ -17,10 +18,15 @@ import java.util.Map; import org.junit.Test; +import net.sourceforge.pmd.EnumeratedPropertyDescriptor; +import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.SingleValuePropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; +import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; /** * Base functionality for all concrete subclasses that evaluate type-specific @@ -250,6 +256,66 @@ public abstract class AbstractPropertyDescriptorTester { return res; } + @Test + public void testIsMultiValue() { + assertFalse(createProperty().isMultiValue()); + assertTrue(createMultiProperty().isMultiValue()); + } + + @Test + public void testAddAttributes() { + Map atts = createProperty().attributeValuesById(); + Map multiAtts = createMultiProperty().attributeValuesById(); + + assertTrue(atts.containsKey(PropertyDescriptorField.NAME)); + assertTrue(atts.containsKey(PropertyDescriptorField.DESCRIPTION)); + assertTrue(atts.containsKey(PropertyDescriptorField.DEFAULT_VALUE)); + + assertTrue(multiAtts.containsKey(PropertyDescriptorField.DELIMITER)); + assertTrue(multiAtts.containsKey(PropertyDescriptorField.NAME)); + assertTrue(multiAtts.containsKey(PropertyDescriptorField.DESCRIPTION)); + assertTrue(multiAtts.containsKey(PropertyDescriptorField.DEFAULT_VALUE)); + } + + @Test + @SuppressWarnings("unchecked") + public void testWrapper() { + PropertyDescriptor prop = createProperty(); + PropertyDescriptor> multi = createMultiProperty(); + + PropertyDescriptor propW = null; + PropertyDescriptor> multiW = null; + try { + propW = (SingleValuePropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); + multiW = (MultiValuePropertyDescriptor) PropertyDescriptorWrapper.getWrapper(multi); + } catch (ClassCastException ioe) { + fail(); + } + + assertEquals(prop.type(), propW.type()); + assertEquals(prop.defaultValue(), propW.defaultValue()); + assertEquals(prop.description(), propW.description()); + assertEquals(prop.isMultiValue(), propW.isMultiValue()); + assertEquals(prop.name(), propW.name()); + assertEquals(prop.preferredRowCount(), propW.preferredRowCount()); + assertEquals(prop.uiOrder(), propW.uiOrder(), 0); + assertEquals(prop.attributeValuesById(), propW.attributeValuesById()); + assertEquals(prop.hashCode(), propW.hashCode()); + + + + assertEquals(multi.type(), multiW.type()); + assertEquals(multi.defaultValue(), multiW.defaultValue()); + assertEquals(multi.description(), multiW.description()); + assertEquals(multi.isMultiValue(), multiW.isMultiValue()); + assertEquals(multi.name(), multiW.name()); + assertEquals(multi.preferredRowCount(), multiW.preferredRowCount()); + assertEquals(multi.uiOrder(), multiW.uiOrder(), 0); + assertEquals(multi.attributeValuesById(), multiW.attributeValuesById()); + assertEquals(multi.hashCode(), multiW.hashCode()); + + } + @Test public void testType() { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java index 0a7b84f424..91de40b395 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java @@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.DoubleProperty; * * @author Brian Remedios */ -public class DoublePropertyTest extends AbstractPropertyDescriptorTester { +public class DoublePropertyTest extends AbstractNumericPropertyDescriptorTester { private static final double MIN = -10.0; private static final double MAX = 100.0; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java index 4ddaf0e5bb..9b5e3652ba 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java @@ -84,7 +84,8 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester @Override protected PropertyDescriptor createProperty() { - return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.lang"}, 1.0f); + return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.lang", "org.apache"}, + 1.0f); } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index 43fe10940c..26169e9209 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -71,7 +71,6 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest assertEquals(prop.mappings(), propW.mappings()); assertEquals(multi.mappings(), multiW.mappings()); - } From 648e15122e0bfdb157dc831db880e480048ea038 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 18:39:13 +0200 Subject: [PATCH 35/53] Revert "Removed PropertyDescriptorFactory" This reverts commit 72d435f2f62896dd7fb68b076eaa494274b88e8d. --- .../net/sourceforge/pmd/RuleSetFactory.java | 46 +++++- .../net/sourceforge/pmd/RuleSetWriter.java | 27 ++++ .../properties/PropertyDescriptorFactory.java | 145 ++++++++++++++++++ 3 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 0aff742b08..50982078fa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -788,7 +788,51 @@ public class RuleSetFactory { return null; } - + /** + * Parse a property node. + * + * @param rule + * The Rule to which the property should be added. //@param + * propertyNode Must be a property element node. + */ + // private static void parsePropertyNode(Rule rule, Node propertyNode) { + // Element propertyElement = (Element) propertyNode; + // String name = propertyElement.getAttribute("name"); + // String description = propertyElement.getAttribute("description"); + // String type = propertyElement.getAttribute("type"); + // String delimiter = propertyElement.getAttribute("delimiter"); + // String min = propertyElement.getAttribute("min"); + // String max = propertyElement.getAttribute("max"); + // String value = propertyElement.getAttribute("value"); + // + // // If value not provided, get from child element. + // if (StringUtil.isEmpty(value)) { + // for (int i = 0; i < propertyNode.getChildNodes().getLength(); i++) { + // Node node = propertyNode.getChildNodes().item(i); + // if ((node.getNodeType() == Node.ELEMENT_NODE) && + // node.getNodeName().equals("value")) { + // value = parseTextNode(node); + // } + // } + // } + // + // // Setting of existing property, or defining a new property? + // if (StringUtil.isEmpty(type)) { + // PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); + // if (propertyDescriptor == null) { + // throw new IllegalArgumentException("Cannot set non-existant property '" + + // name + "' on Rule " + rule.getName()); + // } else { + // Object realValue = propertyDescriptor.valueFrom(value); + // rule.setProperty(propertyDescriptor, realValue); + // } + // } else { + // PropertyDescriptor propertyDescriptor = + // PropertyDescriptorFactory.createPropertyDescriptor(name, description, + // type, delimiter, min, max, value); + // rule.definePropertyDescriptor(propertyDescriptor); + // } + // } private static void setValue(Rule rule, PropertyDescriptor desc, String strValue) { T realValue = desc.valueFrom(strValue); rule.setProperty(desc, realValue); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 9d4d3e121d..2b4f421db0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -333,6 +333,33 @@ public class RuleSetWriter { return propertyElement; } + // private Element createPropertyDefinitionElement(PropertyDescriptor + // propertyDescriptor) { + // Element propertyElement = createPropertyValueElement(propertyDescriptor, + // propertyDescriptor.defaultValue()); + // + // propertyElement.setAttribute("description", + // propertyDescriptor.description()); + // String type = + // PropertyDescriptorFactory.getPropertyDescriptorType(propertyDescriptor); + // propertyElement.setAttribute("type", type); + // + // if (propertyDescriptor.isMultiValue()) { + // propertyElement.setAttribute("delimiter", + // String.valueOf(propertyDescriptor.multiValueDelimiter())); + // } + // + // if (propertyDescriptor instanceof AbstractNumericProperty) { + // propertyElement.setAttribute("min", + // String.valueOf(((AbstractNumericProperty) + // propertyDescriptor).lowerLimit())); + // propertyElement.setAttribute("max", + // String.valueOf(((AbstractNumericProperty) + // propertyDescriptor).upperLimit())); + // } + // + // return propertyElement; + // } private Element createPropertyDefinitionElementBR(PropertyDescriptor propertyDescriptor) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java new file mode 100644 index 0000000000..c7aa47e0cb --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -0,0 +1,145 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.List; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.util.StringUtil; + +// TODO: delete? It's not used anywhere, including the plugins (the only usage is a doc import in +// PropertyDescriptorWrapper +// I'm pretty sure the functionality of this class was superseded by PropertyDescriptorUtil at some point +public class PropertyDescriptorFactory { + + private PropertyDescriptorFactory() { } + + + /** + * Returns the String type of the PropertyDescriptor for use in XML + * serialization. If the value is null the type cannot be + * serialized. + */ + public static String getPropertyDescriptorType(PropertyDescriptor propertyDescriptor) { + Class type = propertyDescriptor.type(); + + String typeName = null; + // TODO - yes we can, investigate + if (propertyDescriptor instanceof EnumeratedProperty || propertyDescriptor instanceof MethodProperty + || propertyDescriptor instanceof TypeProperty) { + // Cannot serialize these kinds of PropertyDescriptors + } else if ("java.lang".equals(type.getPackage().getName())) { + typeName = type.getSimpleName(); + } + if (typeName == null) { + throw new IllegalArgumentException("Cannot encode type for PropertyDescriptor class: " + type.getName()); + } + if (propertyDescriptor.isMultiValue()) { + typeName = "List<" + typeName + ">"; // TODO:cf + } + + return typeName; + } + + + // TODO:cf Deprecate? PropertyDescriptors can already be made from a map + public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, + String delimiter, String min, String max, String value) { + return new PropertyDescriptorWrapper<>( + createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); + } + + + private static PropertyDescriptor createRawPropertyDescriptor(String name, String description, String type, + String delimiter, String min, String max, String value) { + if ("Boolean".equals(type)) { + return new BooleanProperty(name, description, value, 0.0f); + } else if ("List".equals(type)) { + BooleanMultiProperty property = new BooleanMultiProperty(name, description, (List) null, 0.0f); + return new BooleanMultiProperty(name, description, property.valueFrom(value), 0.0f); + } else if ("Character".equals(type)) { + return new CharacterProperty(name, description, CharacterProperty.charFrom(value), 0.0f); + } else if ("List".equals(type)) { + checkDelimiter(name, type, delimiter); + char delim = delimiter.charAt(0); + CharacterMultiProperty property = new CharacterMultiProperty(name, description, (List) null, 0.0f, delim); + return new CharacterMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); + } else if ("Double".equals(type)) { + checkMinMax(name, type, min, max); + return new DoubleProperty(name, description, min, max, value, 0.0f); + } else if ("List".equals(type)) { + checkMinMax(name, type, min, max); + DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, (List) null, 0.0f); + return new DoubleMultiProperty(name, description, DoubleProperty.doubleFrom(min), + DoubleProperty.doubleFrom(max), property.valueFrom(value), 0.0f); + } else if ("Float".equals(type)) { + checkMinMax(name, type, min, max); + return new FloatProperty(name, description, min, max, value, 0.0f); + } else if ("List".equals(type)) { + checkMinMax(name, type, min, max); + FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); + return new FloatMultiProperty(name, description, FloatProperty.floatFrom(min), FloatProperty.floatFrom(max), + property.valueFrom(value), 0.0f); + } else if ("Integer".equals(type)) { + checkMinMax(name, type, min, max); + return new IntegerProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), ValueParser.INTEGER_PARSER.valueOf(max), + ValueParser.INTEGER_PARSER.valueOf(value), 0.0f); + } else if ("List".equals(type)) { + checkMinMax(name, type, min, max); + IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, + 0.0f); + return new IntegerMultiProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), + ValueParser.INTEGER_PARSER.valueOf(max), property.valueFrom(value), 0.0f); + } else if ("Long".equals(type)) { + checkMinMax(name, type, min, max); + return new LongProperty(name, description, min, max, value, 0.0f); + } else if ("List".equals(type)) { + checkMinMax(name, type, min, max); + LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); + return new LongMultiProperty(name, description, LongProperty.longFrom(min), LongProperty.longFrom(max), + property.valueFrom(value), 0.0f); + + // TODO - include legal package names for next four types + } else if ("Type".equals(type)) { + return new TypeProperty(name, description, value, (String[]) null, 0.0f); + } else if ("List".equals(type)) { + return new TypeMultiProperty(name, description, value, (String[]) null, 0.0f); + } else if ("Method".equals(type)) { + return new MethodProperty(name, description, value, (String[]) null, 0.0f); + } else if ("List".equals(type)) { + return new MethodMultiProperty(name, description, value, (String[]) null, 0.0f); + + } else if ("String".equals(type)) { + return new StringProperty(name, description, value, 0.0f); + } else if ("List".equals(type)) { + checkDelimiter(name, type, delimiter); + char delim = delimiter.charAt(0); + StringMultiProperty property = new StringMultiProperty(name, description, (String[]) null, 0.0f, delim); + return new StringMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); + } else { + throw new IllegalArgumentException("Cannot define property type '" + type + "'."); + } + } + + + private static void checkDelimiter(String name, String type, String delimiter) { + if (delimiter == null || delimiter.length() == 0) { + throw new IllegalArgumentException( + "Delimiter must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + } + } + + + private static void checkMinMax(String name, String type, String min, String max) { + if (StringUtil.isEmpty(min)) { + throw new IllegalArgumentException( + "Min must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + } + if (StringUtil.isEmpty(max)) { + throw new IllegalArgumentException( + "Max must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); + } + } +} From 9a2a91115b827ceccb17e21da9da0504ac8bb9f6 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 19:04:09 +0200 Subject: [PATCH 36/53] Deprecated PropertyDescriptorFactory --- .../AbstractMultiNumericProperty.java | 49 ++++++++++++------- .../properties/AbstractNumericProperty.java | 26 +++++++--- .../rule/properties/AbstractProperty.java | 3 +- .../properties/EnumeratedMultiProperty.java | 1 - .../properties/PropertyDescriptorFactory.java | 27 +++++++--- .../AbstractPropertyDescriptorTester.java | 2 - 6 files changed, 73 insertions(+), 35 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 44b2a39524..1a5a6189e3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -24,8 +24,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; /* default */ abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty implements NumericPropertyDescriptor> { - private final Number lowerLimit; - private final Number upperLimit; + private final T lowerLimit; + private final T upperLimit; /** @@ -33,35 +33,36 @@ import net.sourceforge.pmd.PropertyDescriptorField; * * @param theName Name * @param theDescription Description - * @param min Minimum value of the property - * @param max Maximum value of the property + * @param lower Minimum value of the property + * @param upper Maximum value of the property * @param theDefault List of defaults * @param theUIOrder UI order * - * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds + * @throws IllegalArgumentException if lower > upper, or one of them is null, or one of the defaults is not between + * the bounds */ - AbstractMultiNumericProperty(String theName, String theDescription, Number min, Number max, List theDefault, + AbstractMultiNumericProperty(String theName, String theDescription, T lower, T upper, List theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); - if (min.doubleValue() > max.doubleValue()) { + 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"); } - lowerLimit = min; - upperLimit = max; + } - @Override - public Number lowerLimit() { - return lowerLimit; - } - - - @Override - public Number upperLimit() { - return upperLimit; + private void checkNumber(T number) { + if (valueErrorFor(number) != null) { + throw new IllegalArgumentException(valueErrorFor(number)); + } } @@ -78,6 +79,18 @@ import net.sourceforge.pmd.PropertyDescriptorField; } + @Override + public Number lowerLimit() { + return lowerLimit; + } + + + @Override + public Number upperLimit() { + return upperLimit; + } + + @Override protected void addAttributesTo(Map attributes) { super.addAttributesTo(attributes); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 9b02b00167..f338437454 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -32,20 +32,34 @@ import net.sourceforge.pmd.PropertyDescriptorField; private T upperLimit; + /** + * Constructor for a single-valued numeric property. + * + * @param theName Name + * @param theDescription Description + * @param lower Minimum value of the property + * @param upper Maximum value of the property + * @param theDefault List of defaults + * @param theUIOrder UI order + * + * @throws IllegalArgumentException if lower > upper, or one of them is null, or the default is not between the + * bounds + */ protected AbstractNumericProperty(String theName, String theDescription, T lower, T upper, T theDefault, float theUIOrder) { super(theName, theDescription, theDefault, theUIOrder); + 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"); } - lowerLimit = lower; - upperLimit = upper; - checkNumber(lowerLimit); - checkNumber(upperLimit); - checkNumber(theDefault); } @@ -89,7 +103,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; * * @return String */ - static String rangeString(Number low, Number up) { + /* default */ static String rangeString(Number low, Number up) { return "(" + low + " -> " + up + ")"; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 1395c4f00a..d66f84010b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -154,7 +154,6 @@ import net.sourceforge.pmd.util.StringUtil; * * @return A wrapper for this property. */ - /* default */ - abstract PropertyDescriptorWrapper getWrapper(); + /* default */ abstract PropertyDescriptorWrapper getWrapper(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index b1725fce85..3f1c52e09a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -13,7 +13,6 @@ import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.CollectionUtil; -import net.sourceforge.pmd.util.StringUtil; /** * Multi-valued property which can take only a fixed set of values of any type, then selected via String labels. The diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java index c7aa47e0cb..b0461bf568 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java @@ -9,9 +9,10 @@ import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.util.StringUtil; -// TODO: delete? It's not used anywhere, including the plugins (the only usage is a doc import in -// PropertyDescriptorWrapper -// I'm pretty sure the functionality of this class was superseded by PropertyDescriptorUtil at some point + +/** + * @deprecated + */ public class PropertyDescriptorFactory { private PropertyDescriptorFactory() { } @@ -21,6 +22,8 @@ public class PropertyDescriptorFactory { * Returns the String type of the PropertyDescriptor for use in XML * serialization. If the value is null the type cannot be * serialized. + * + * @deprecated */ public static String getPropertyDescriptorType(PropertyDescriptor propertyDescriptor) { Class type = propertyDescriptor.type(); @@ -44,7 +47,19 @@ public class PropertyDescriptorFactory { } - // TODO:cf Deprecate? PropertyDescriptors can already be made from a map + /** + * @param name + * @param description + * @param type + * @param delimiter + * @param min + * @param max + * @param value + * + * @return + * + * @deprecated + */ public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, String delimiter, String min, String max, String value) { return new PropertyDescriptorWrapper<>( @@ -80,7 +95,7 @@ public class PropertyDescriptorFactory { } else if ("List".equals(type)) { checkMinMax(name, type, min, max); FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); - return new FloatMultiProperty(name, description, FloatProperty.floatFrom(min), FloatProperty.floatFrom(max), + return new FloatMultiProperty(name, description, Float.valueOf(min), Float.valueOf(max), property.valueFrom(value), 0.0f); } else if ("Integer".equals(type)) { checkMinMax(name, type, min, max); @@ -98,7 +113,7 @@ public class PropertyDescriptorFactory { } else if ("List".equals(type)) { checkMinMax(name, type, min, max); LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); - return new LongMultiProperty(name, description, LongProperty.longFrom(min), LongProperty.longFrom(max), + return new LongMultiProperty(name, description, Long.valueOf(min), Long.valueOf(max), property.valueFrom(value), 0.0f); // TODO - include legal package names for next four types diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 3831acb6f2..e58b890a3b 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -18,7 +18,6 @@ import java.util.Map; import org.junit.Test; -import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -26,7 +25,6 @@ import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.SingleValuePropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; -import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; /** * Base functionality for all concrete subclasses that evaluate type-specific From 9075cb005c37782d5248485d8628d90dff4a238f Mon Sep 17 00:00:00 2001 From: oowekyala Date: Wed, 12 Jul 2017 20:00:32 +0200 Subject: [PATCH 37/53] Fix bug with empty value strings --- .../lang/rule/properties/AbstractMultiValueProperty.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 0f46d52cb8..e37b9e0112 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -13,6 +13,7 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.util.StringUtil; /** * Multi-valued property. @@ -176,11 +177,15 @@ import net.sourceforge.pmd.Rule; @Override public List valueFrom(String valueString) throws IllegalArgumentException { + if (StringUtil.isEmpty(valueString)) { + return Collections.emptyList(); + } + String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter())); List values = new ArrayList<>(strValues.length); - for (int i = 0; i < strValues.length; i++) { - values.add(createFrom(strValues[i])); + for (String strValue : strValues) { + values.add(createFrom(strValue)); } return values; From 12a16caf69731a2d2f2d5f8d167d858e7b64c09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sat, 8 Jul 2017 20:22:35 +0200 Subject: [PATCH 38/53] Java, typeres: add vararg most specific tests --- .../pmd/typeresolution/ClassTypeResolverTest.java | 4 ++++ .../pmd/typeresolution/testdata/MethodThirdPhase.java | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 675791ba24..5a493f9e1f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -1325,6 +1325,10 @@ public class ClassTypeResolverTest { assertEquals(int.class, expressions.get(index).getType()); assertEquals(int.class, getChildType(expressions.get(index), 0)); assertEquals(int.class, getChildType(expressions.get(index++), 1)); + // String d = mostSpecific(10, 10, 10); + assertEquals(String.class, expressions.get(index).getType()); + assertEquals(String.class, getChildType(expressions.get(index), 0)); + assertEquals(String.class, getChildType(expressions.get(index++), 1)); // Make sure we got them all assertEquals("All expressions not tested", index, expressions.size()); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java index 290ed7cb03..e7740157d1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java @@ -15,8 +15,16 @@ public class MethodThirdPhase { // component type determined properly int c = vararg(10, "", "", ""); - // TODO: add most specific tests among vararg conversion + // most specific vararg method + String d = mostSpecific(10, 10, 10); + } + Exception mostSpecific(Number... b) { + return null; + } + + String mostSpecific(Integer... b) { + return null; } Exception vararg(int a, Number... b) { From 976240ca48d8843d62015226ff6c6498496d1ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bendeg=C3=BAz=20Nagy?= Date: Sun, 9 Jul 2017 14:36:41 +0200 Subject: [PATCH 39/53] Java, typeres: add choosing most specific vararg method --- .../lang/java/typeresolution/MethodType.java | 8 ++++ .../typeresolution/MethodTypeResolution.java | 44 +++++++++++++------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java index ff5bd703fd..8423b2cf5e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodType.java @@ -53,4 +53,12 @@ public class MethodType { public boolean isAbstract() { return Modifier.isAbstract(method.getModifiers()); } + + public JavaTypeDefinition getArgTypeIncludingVararg(int index) { + if (index < argTypes.size() - 1) { + return argTypes.get(index); + } else { + return getVarargComponentType(); + } + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java index 1168422692..b8fd7fd2c9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/MethodTypeResolution.java @@ -48,15 +48,37 @@ public final class MethodTypeResolution { } public static boolean checkSubtypeability(MethodType method, MethodType subtypeableMethod) { - List subtypeableArgs = subtypeableMethod.getParameterTypes(); - List methodTypeArgs = method.getParameterTypes(); + List subtypeableParams = subtypeableMethod.getParameterTypes(); + List methodParams = method.getParameterTypes(); - // TODO: add support for not matching arity methods - for (int index = 0; index < subtypeableArgs.size(); ++index) { - if (!isSubtypeable(methodTypeArgs.get(index), subtypeableArgs.get(index))) { - return false; + if (!method.getMethod().isVarArgs() && !subtypeableMethod.getMethod().isVarArgs()) { + for (int index = 0; index < subtypeableParams.size(); ++index) { + if (!isSubtypeable(methodParams.get(index), subtypeableParams.get(index))) { + return false; + } } + } else if (method.getMethod().isVarArgs() && subtypeableMethod.getMethod().isVarArgs()) { + + if (methodParams.size() < subtypeableParams.size()) { + for (int index = 0; index < subtypeableParams.size(); ++index) { + if (!isSubtypeable(method.getArgTypeIncludingVararg(index), + subtypeableMethod.getArgTypeIncludingVararg(index))) { + return false; + } + } + } else { + for (int index = 0; index < methodParams.size(); ++index) { + if (!isSubtypeable(method.getArgTypeIncludingVararg(index), + subtypeableMethod.getArgTypeIncludingVararg(index))) { + return false; + } + } + } + + } else { + throw new IllegalStateException("These methods can only be vararg at the same time:\n" + + method.toString() + "\n" + subtypeableMethod.toString()); } return true; @@ -202,10 +224,7 @@ public final class MethodTypeResolution { */ public static JavaTypeDefinition getBestMethodReturnType(List methods, ASTArgumentList arguments, List typeArgs) { - if (methods.size() == 1) { - return methods.get(0).getReturnType(); // TODO: remove this in the end, needed to pass some previous tests - } - + List selectedMethods = selectMethodsFirstPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { return selectMostSpecificMethod(selectedMethods).getReturnType(); @@ -218,10 +237,7 @@ public final class MethodTypeResolution { selectedMethods = selectMethodsThirdPhase(methods, arguments, typeArgs); if (!selectedMethods.isEmpty()) { - if (selectedMethods.size() == 1) { - return selectedMethods.get(0).getReturnType(); - // TODO: add selecting most specific vararg method - } + return selectMostSpecificMethod(selectedMethods).getReturnType(); } return null; From 0164edf585dfd1580d88de0f239edb284269dcb3 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 14:17:30 +0200 Subject: [PATCH 40/53] Corrections for #479 --- .../sourceforge/pmd/PropertyDescriptor.java | 2 +- .../pmd/PropertyDescriptorField.java | 16 +++- .../net/sourceforge/pmd/RuleSetFactory.java | 84 ++++++------------- .../net/sourceforge/pmd/RuleSetWriter.java | 31 +------ .../AbstractMultiNumericProperty.java | 5 +- .../properties/PropertyDescriptorUtil.java | 9 -- 6 files changed, 46 insertions(+), 101 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 342a12aacb..57bd7d7b2e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -106,7 +106,7 @@ public interface PropertyDescriptor extends Comparable> /** - * Retunrs the value represented by this string. + * Returns the value represented by this string. * * @param propertyString The string to parse * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java index 356b5e9a0e..55f97a21a8 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java @@ -41,7 +41,7 @@ public enum PropertyDescriptorField { /** Default index for enumerated properties. */ DEFAULT_INDEX("defaultIndex"); - final String attributeName; + private final String attributeName; PropertyDescriptorField(String attributeName) { @@ -49,9 +49,19 @@ public enum PropertyDescriptorField { } - @Override - public String toString() { + /** + * Returns the String name of this attribute. + * + * @return The attribute's name + */ + public String attributeName() { return attributeName; } + + @Override + public String toString() { + return attributeName(); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 50982078fa..d3ccdc6233 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -723,14 +723,14 @@ public class RuleSetFactory { } } + /** * Check whether the given ruleName is contained in the given ruleset. * - * @param ruleSetReferenceId - * the ruleset to check - * @param ruleName - * the rule name to search for - * @return true if the ruleName exists + * @param ruleSetReferenceId the ruleset to check + * @param ruleName the rule name to search for + * + * @return {@code true} if the ruleName exists */ private boolean containsRule(RuleSetReferenceId ruleSetReferenceId, String ruleName) { boolean found = false; @@ -788,68 +788,39 @@ public class RuleSetFactory { return null; } + /** - * Parse a property node. + * Sets the value of a property. * - * @param rule - * The Rule to which the property should be added. //@param - * propertyNode Must be a property element node. + * @param rule The rule which has the property + * @param desc The property descriptor + * @param strValue The string value of the property, converted to a T + * @param The type of values of the property descriptor */ - // private static void parsePropertyNode(Rule rule, Node propertyNode) { - // Element propertyElement = (Element) propertyNode; - // String name = propertyElement.getAttribute("name"); - // String description = propertyElement.getAttribute("description"); - // String type = propertyElement.getAttribute("type"); - // String delimiter = propertyElement.getAttribute("delimiter"); - // String min = propertyElement.getAttribute("min"); - // String max = propertyElement.getAttribute("max"); - // String value = propertyElement.getAttribute("value"); - // - // // If value not provided, get from child element. - // if (StringUtil.isEmpty(value)) { - // for (int i = 0; i < propertyNode.getChildNodes().getLength(); i++) { - // Node node = propertyNode.getChildNodes().item(i); - // if ((node.getNodeType() == Node.ELEMENT_NODE) && - // node.getNodeName().equals("value")) { - // value = parseTextNode(node); - // } - // } - // } - // - // // Setting of existing property, or defining a new property? - // if (StringUtil.isEmpty(type)) { - // PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); - // if (propertyDescriptor == null) { - // throw new IllegalArgumentException("Cannot set non-existant property '" + - // name + "' on Rule " + rule.getName()); - // } else { - // Object realValue = propertyDescriptor.valueFrom(value); - // rule.setProperty(propertyDescriptor, realValue); - // } - // } else { - // PropertyDescriptor propertyDescriptor = - // PropertyDescriptorFactory.createPropertyDescriptor(name, description, - // type, delimiter, min, max, value); - // rule.definePropertyDescriptor(propertyDescriptor); - // } - // } private static void setValue(Rule rule, PropertyDescriptor desc, String strValue) { T realValue = desc.valueFrom(strValue); rule.setProperty(desc, realValue); } + + /** + * Parse a property node. + * + * @param rule The Rule to which the property should be added. + * @param propertyNode Must be a property element node. + */ private static void parsePropertyNodeBR(Rule rule, Node propertyNode) { Element propertyElement = (Element) propertyNode; - String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName); - String strValue = propertyElement.getAttribute(PropertyDescriptorField.DEFAULT_VALUE.attributeName); + String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName()); + String strValue = propertyElement.getAttribute(PropertyDescriptorField.DEFAULT_VALUE.attributeName()); if (StringUtil.isEmpty(strValue)) { strValue = valueFrom(propertyElement); } // Setting of existing property, or defining a new property? if (StringUtil.isEmpty(typeId)) { - String name = propertyElement.getAttribute(PropertyDescriptorField.NAME.attributeName); + String name = propertyElement.getAttribute(PropertyDescriptorField.NAME.attributeName()); PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); if (propertyDescriptor == null) { @@ -871,7 +842,7 @@ public class RuleSetFactory { // populate a map of values for an individual descriptor for (Map.Entry entry : valueKeys.entrySet()) { - String valueStr = propertyElement.getAttribute(entry.getKey().attributeName); + String valueStr = propertyElement.getAttribute(entry.getKey().attributeName()); if (entry.getValue() && StringUtil.isEmpty(valueStr)) { // TODO debug pt System.out.println("Missing required value for: " + entry.getKey()); @@ -911,16 +882,15 @@ public class RuleSetFactory { return buffer.toString(); } + /** * Determine if the specified rule element will represent a Rule with the * given name. * - * @param ruleElement - * The rule element. - * @param ruleName - * The Rule name. - * @return true if the Rule would have the given name, - * false otherwise. + * @param ruleElement The rule element. + * @param ruleName The Rule name. + * + * @return {@code true} if the Rule would have the given name, {@code false} otherwise. */ private boolean isRuleName(Element ruleElement, String ruleName) { if (ruleElement.hasAttribute("name")) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 2b4f421db0..428138e5fd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -333,45 +333,18 @@ public class RuleSetWriter { return propertyElement; } - // private Element createPropertyDefinitionElement(PropertyDescriptor - // propertyDescriptor) { - // Element propertyElement = createPropertyValueElement(propertyDescriptor, - // propertyDescriptor.defaultValue()); - // - // propertyElement.setAttribute("description", - // propertyDescriptor.description()); - // String type = - // PropertyDescriptorFactory.getPropertyDescriptorType(propertyDescriptor); - // propertyElement.setAttribute("type", type); - // - // if (propertyDescriptor.isMultiValue()) { - // propertyElement.setAttribute("delimiter", - // String.valueOf(propertyDescriptor.multiValueDelimiter())); - // } - // - // if (propertyDescriptor instanceof AbstractNumericProperty) { - // propertyElement.setAttribute("min", - // String.valueOf(((AbstractNumericProperty) - // propertyDescriptor).lowerLimit())); - // propertyElement.setAttribute("max", - // String.valueOf(((AbstractNumericProperty) - // propertyDescriptor).upperLimit())); - // } - // - // return propertyElement; - // } private Element createPropertyDefinitionElementBR(PropertyDescriptor propertyDescriptor) { final Element propertyElement = createPropertyValueElement(propertyDescriptor, propertyDescriptor.defaultValue()); - propertyElement.setAttribute(PropertyDescriptorField.TYPE.attributeName, + propertyElement.setAttribute(PropertyDescriptorField.TYPE.attributeName(), PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type(), propertyDescriptor.isMultiValue())); Map propertyValuesById = propertyDescriptor.attributeValuesById(); for (Map.Entry entry : propertyValuesById.entrySet()) { - propertyElement.setAttribute(entry.getKey().attributeName, entry.getValue()); + propertyElement.setAttribute(entry.getKey().attributeName(), entry.getValue()); } return propertyElement; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 1a5a6189e3..104b9dc65f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -60,8 +60,9 @@ import net.sourceforge.pmd.PropertyDescriptorField; private void checkNumber(T number) { - if (valueErrorFor(number) != null) { - throw new IllegalArgumentException(valueErrorFor(number)); + String error = valueErrorFor(number); + if (error != null) { + throw new IllegalArgumentException(error); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index 7cad68b59f..5ac30e810e 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -5,11 +5,9 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.Map; -import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; /** @@ -17,13 +15,6 @@ import net.sourceforge.pmd.PropertyDescriptorFactory; */ public class PropertyDescriptorUtil { - public static final Comparator> COMPARATOR_BY_ORDER = new Comparator>() { - @Override - public int compare(PropertyDescriptor pd1, PropertyDescriptor pd2) { - return pd2.uiOrder() > pd1.uiOrder() ? -1 : 1; - } - }; - private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; From e39cbba24aa663eda230b81325cfe5216df19cfe Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 14:54:05 +0200 Subject: [PATCH 41/53] Added overloads of setProperty for multivalued properties --- .../apexunit/AbstractApexUnitTestRule.java | 4 +-- .../complexity/AbstractNcssCountRule.java | 4 +-- .../AvoidDeeplyNestedIfStmtsRule.java | 4 +-- .../complexity/ExcessiveClassLengthRule.java | 4 +-- .../ExcessiveParameterListRule.java | 4 +-- .../complexity/ExcessivePublicCountRule.java | 4 +-- .../complexity/NcssConstructorCountRule.java | 4 +-- .../rule/complexity/NcssMethodCountRule.java | 4 +-- .../rule/complexity/NcssTypeCountRule.java | 4 +-- .../StdCyclomaticComplexityRule.java | 3 +- .../rule/complexity/TooManyFieldsRule.java | 3 +- .../AvoidDmlStatementsInLoopsRule.java | 4 +-- .../performance/AvoidSoqlInLoopsRule.java | 4 +-- .../apex/rule/security/ApexBadCryptoRule.java | 3 +- .../rule/security/ApexCRUDViolationRule.java | 2 +- .../lang/apex/rule/security/ApexCSRFRule.java | 4 +-- .../security/ApexDangerousMethodsRule.java | 3 +- .../security/ApexInsecureEndpointRule.java | 3 +- .../rule/security/ApexOpenRedirectRule.java | 3 +- .../rule/security/ApexSOQLInjectionRule.java | 3 +- .../security/ApexSharingViolationsRule.java | 3 +- .../ApexSuggestUsingNamedCredRule.java | 3 +- .../security/ApexXSSFromEscapeFalseRule.java | 3 +- .../security/ApexXSSFromURLParamRule.java | 3 +- .../rule/style/AvoidGlobalModifierRule.java | 4 +-- .../rule/style/AvoidLogicInTriggerRule.java | 3 +- .../style/ClassNamingConventionsRule.java | 4 +-- .../style/MethodNamingConventionsRule.java | 4 +-- ...ethodWithSameNameAsEnclosingClassRule.java | 3 +- .../style/VariableNamingConventionsRule.java | 3 +- .../pmd/AbstractPropertySource.java | 36 +++++++++++++++++-- .../net/sourceforge/pmd/PropertySource.java | 35 +++++++++++++++++- .../pmd/lang/rule/AbstractDelegateRule.java | 20 +++++++++++ .../pmd/lang/rule/RuleReference.java | 5 +++ .../pmd/properties/PropertyAccessorTest.java | 2 +- 35 files changed, 124 insertions(+), 78 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java index d4bb22d466..d74b34ef04 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/AbstractApexUnitTestRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.apexunit; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; @@ -21,7 +19,7 @@ import apex.jorje.services.Version; public abstract class AbstractApexUnitTestRule extends AbstractApexRule { public AbstractApexUnitTestRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Bug Risk")); + setProperty(CODECLIMATE_CATEGORIES, "Bug Risk"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java index 9f6b69386c..e1bcf2b59a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AbstractNcssCountRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.apex.ast.ASTContinueStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement; @@ -45,7 +43,7 @@ public abstract class AbstractNcssCountRule extends AbstractStatisticalApexRule this.nodeClass = nodeClass; setProperty(MINIMUM_DESCRIPTOR, 1000d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java index 758080f9d3..46635ff6f4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; @@ -22,7 +20,7 @@ public class AvoidDeeplyNestedIfStmtsRule extends AbstractApexRule { public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); // Note: Remedy needs better OO design and therefore high effort setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java index c4addbf62d..66961ef534 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java @@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.AnnotationTypeInfos.IS_TEST; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; /** @@ -19,7 +17,7 @@ public class ExcessiveClassLengthRule extends ExcessiveLengthRule { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 1000d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java index 192cea0aeb..08f6abd87b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.util.NumericConstants; @@ -19,7 +17,7 @@ public class ExcessiveParameterListRule extends ExcessiveNodeCountRule { public ExcessiveParameterListRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 4d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java index 5f0406bf78..1da2781e3e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java @@ -7,8 +7,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.PUBLIC; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclarationStatements; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -33,7 +31,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule { public ExcessivePublicCountRule() { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 20d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java index 9536f5729b..912e7688b9 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.stat.DataPoint; import net.sourceforge.pmd.util.NumericConstants; @@ -23,7 +21,7 @@ public class NcssConstructorCountRule extends AbstractNcssCountRule { public NcssConstructorCountRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 20d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java index b0606c53ef..19a3261ee3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.stat.DataPoint; import net.sourceforge.pmd.util.NumericConstants; @@ -23,7 +21,7 @@ public class NcssMethodCountRule extends AbstractNcssCountRule { public NcssMethodCountRule() { super(ASTMethod.class); setProperty(MINIMUM_DESCRIPTOR, 40d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java index 671d6df53e..1d1fb9489e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -28,7 +26,7 @@ public class NcssTypeCountRule extends AbstractNcssCountRule { public NcssTypeCountRule() { super(ASTUserClass.class); setProperty(MINIMUM_DESCRIPTOR, 500d); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 250); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java index 9428990be3..bc50c96bf1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; -import java.util.Arrays; import java.util.Stack; import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; @@ -79,7 +78,7 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule { definePropertyDescriptor(SHOW_CLASSES_COMPLEXITY_DESCRIPTOR); definePropertyDescriptor(SHOW_METHODS_COMPLEXITY_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 250); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java index fa5fca8883..dc0db3c886 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.apex.rule.complexity; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -32,7 +31,7 @@ public class TooManyFieldsRule extends AbstractApexRule { public TooManyFieldsRule() { definePropertyDescriptor(MAX_FIELDS_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Complexity")); + setProperty(CODECLIMATE_CATEGORIES, "Complexity"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java index cdeaf0ef25..ff7649ab97 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.performance; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlInsertStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlMergeStatement; @@ -23,7 +21,7 @@ import net.sourceforge.pmd.lang.ast.Node; public class AvoidDmlStatementsInLoopsRule extends AbstractApexRule { public AvoidDmlStatementsInLoopsRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Performance")); + setProperty(CODECLIMATE_CATEGORIES, "Performance"); // Note: Often more complicated as just moving the SOQL a few lines. // Involves Maps... setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java index 345bcae677..e6dbb26cd7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.performance; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement; import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement; import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement; @@ -18,7 +16,7 @@ import net.sourceforge.pmd.lang.ast.Node; public class AvoidSoqlInLoopsRule extends AbstractApexRule { public AvoidSoqlInLoopsRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Performance")); + setProperty(CODECLIMATE_CATEGORIES, "Performance"); // Note: Often more complicated as just moving the SOQL a few lines. // Involves Maps... setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 150); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java index deffa03d2d..942cf25e25 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -35,7 +34,7 @@ public class ApexBadCryptoRule extends AbstractApexRule { private final Set potentiallyStaticBlob = new HashSet<>(); public ApexBadCryptoRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index c715e5db57..959e11fb0a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -90,7 +90,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private static final String[] RESERVED_KEYS_FLS = new String[] { "Schema", S_OBJECT_TYPE, }; public ApexCRUDViolationRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java index 7c55adf594..d4aff9c94d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; @@ -22,7 +20,7 @@ public class ApexCSRFRule extends AbstractApexRule { public static final String INIT = "init"; public ApexCSRFRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java index d80b21de92..c3726a8b89 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.regex.Pattern; @@ -40,7 +39,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { public ApexDangerousMethodsRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java index b8819f35e2..847c6ce4cd 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -33,7 +32,7 @@ public class ApexInsecureEndpointRule extends AbstractApexRule { private final Set httpEndpointStrings = new HashSet<>(); public ApexInsecureEndpointRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java index 0c23b3a7f4..7a3e25e35b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; import java.lang.reflect.Field; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -38,7 +37,7 @@ public class ApexOpenRedirectRule extends AbstractApexRule { public ApexOpenRedirectRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java index 01365fa4e2..94a46f3211 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -50,7 +49,7 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { private final HashMap selectContainingVariables = new HashMap<>(); public ApexSOQLInjectionRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java index c2ff1787db..824c80e651 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.List; import java.util.WeakHashMap; @@ -27,7 +26,7 @@ public class ApexSharingViolationsRule extends AbstractApexRule { private WeakHashMap, Object> localCacheOfReportedNodes = new WeakHashMap<>(); public ApexSharingViolationsRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java index c8124e8f37..234a023d16 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -35,7 +34,7 @@ public class ApexSuggestUsingNamedCredRule extends AbstractApexRule { public ApexSuggestUsingNamedCredRule() { super.addRuleChainVisit(ASTUserClass.class); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java index 748d97e552..e17db570b0 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTLiteralExpression; @@ -23,7 +22,7 @@ public class ApexXSSFromEscapeFalseRule extends AbstractApexRule { private static final String ADD_ERROR = "addError"; public ApexXSSFromEscapeFalseRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java index e96dc6b1a7..73db6e6111 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,7 +50,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { private final Set urlParameterStrings = new HashSet<>(); public ApexXSSFromURLParamRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Security")); + setProperty(CODECLIMATE_CATEGORIES, "Security"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java index 742a8c140a..46045bd497 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java @@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.GLOBAL; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; @@ -17,7 +15,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class AvoidGlobalModifierRule extends AbstractApexRule { public AvoidGlobalModifierRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java index f6d871acbf..c282ca9e68 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; -import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement; @@ -14,7 +13,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class AvoidLogicInTriggerRule extends AbstractApexRule { public AvoidLogicInTriggerRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java index 6d9554559b..8a9a1dfaa3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; @@ -13,7 +11,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class ClassNamingConventionsRule extends AbstractApexRule { public ClassNamingConventionsRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 5); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java index 301d5be2c9..1d251a6fdf 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java @@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.OVERRIDE; -import java.util.Arrays; - import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTProperty; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -16,7 +14,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class MethodNamingConventionsRule extends AbstractApexRule { public MethodNamingConventionsRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 1); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java index 177299ac01..1cbc197aac 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; -import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; @@ -14,7 +13,7 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; public class MethodWithSameNameAsEnclosingClassRule extends AbstractApexRule { public MethodWithSameNameAsEnclosingClassRule() { - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java index 911f288bb9..daef74e51e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.apex.rule.style; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; -import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.PropertyDescriptor; @@ -81,7 +80,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { definePropertyDescriptor(PARAMETER_PREFIXES_DESCRIPTOR); definePropertyDescriptor(PARAMETER_SUFFIXES_DESCRIPTOR); - setProperty(CODECLIMATE_CATEGORIES, Arrays.asList("Style")); + setProperty(CODECLIMATE_CATEGORIES, "Style"); // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 5); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java index c371492e1a..b6b297e3b8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -122,14 +123,45 @@ public abstract class AbstractPropertySource implements PropertySource { @Override public void setProperty(PropertyDescriptor propertyDescriptor, T value) { checkValidPropertyDescriptor(propertyDescriptor); - propertyValuesByDescriptor.put(propertyDescriptor, value); + if (value instanceof List) { + propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList((List) value)); + + } else { + propertyValuesByDescriptor.put(propertyDescriptor, value); + } } + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value) { + checkValidPropertyDescriptor(propertyDescriptor); + propertyValuesByDescriptor.put(propertyDescriptor, Collections.singletonList(value)); + } + + + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2) { + checkValidPropertyDescriptor(propertyDescriptor); + propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList(Arrays.asList(value1, value2))); + } + + + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values) { + checkValidPropertyDescriptor(propertyDescriptor); + propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList(Arrays.asList(value1, value2, values))); + } + + + /** + * Checks whether this property descriptor is defined for this property source. + * + * @param propertyDescriptor The property descriptor to check + */ private void checkValidPropertyDescriptor(PropertyDescriptor propertyDescriptor) { if (!propertyDescriptors.contains(propertyDescriptor)) { throw new IllegalArgumentException( - "Property descriptor not defined for Rule " + getName() + ": " + propertyDescriptor); + "Property descriptor not defined for Rule " + getName() + ": " + propertyDescriptor); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java index e208f8a8e7..836d26b328 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java @@ -46,7 +46,7 @@ public interface PropertySource { /** - * Get the typed value for the given property. + * Get the typed value for the given property. Multi valued properties return immutable lists. * * @param The underlying type of the property descriptor. * @param propertyDescriptor The property descriptor. @@ -66,6 +66,39 @@ public interface PropertySource { void setProperty(PropertyDescriptor propertyDescriptor, T value); + /** + * Sets the value of a multi value property descriptor with only one argument. + * + * @param propertyDescriptor The property descriptor for which to add a value + * @param value Value + * @param The type of the values + */ + void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value); + + + /** + * Sets the value of a multi value property descriptor with two arguments. + * + * @param propertyDescriptor The property descriptor for which to add a value + * @param value1 First value + * @param value2 Second value + * @param The type of the values + */ + void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2); + + + /** + * Sets the value of a multi value property descriptor with a variable number of arguments. + * + * @param propertyDescriptor The property descriptor for which to add a value + * @param value1 First value + * @param value2 Second value + * @param values Rest of the values + * @param The type of the values + */ + void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values); + + /** * Returns all the current property values for the receiver or an immutable * empty map if none are specified. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java index 0e346113b4..78727fc8d4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertySource; import net.sourceforge.pmd.Rule; @@ -206,6 +207,25 @@ public abstract class AbstractDelegateRule implements Rule { rule.setProperty(propertyDescriptor, value); } + + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value) { + rule.setProperty(propertyDescriptor, value); + } + + + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2) { + rule.setProperty(propertyDescriptor, value1, value2); + } + + + @Override + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values) { + rule.setProperty(propertyDescriptor, value1, value2, values); + } + + @Override public Map, Object> getPropertiesByPropertyDescriptor() { return rule.getPropertiesByPropertyDescriptor(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java index c378022373..6a79e157f3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleReference.java @@ -252,6 +252,11 @@ public class RuleReference extends AbstractDelegateRule { } } + + + + + public RuleSetReference getRuleSetReference() { return ruleSetReference; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java index 685705d0af..338e37eaf4 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java @@ -78,7 +78,7 @@ public class PropertyAccessorTest { rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_STR, "brian"); assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.SINGLE_STR), "brian"); - rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_STR, Arrays.asList("hello", "world")); + rule.setProperty(NonRuleWithAllPropertyTypes.MULTI_STR, "hello", "world"); assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_STR), Arrays.asList("hello", "world")); } From 5e57af605c6a974370efa64fc9bf6b74c90f9bf5 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 16:46:05 +0200 Subject: [PATCH 42/53] Removed need for wrappers --- ...=> AbstractPropertyDescriptorFactory.java} | 64 +++++++++++++------ .../pmd/MultiValuePropertyDescriptor.java | 7 ++ .../sourceforge/pmd/PropertyDescriptor.java | 12 ++++ .../pmd/PropertyDescriptorFactory.java | 2 +- .../net/sourceforge/pmd/RuleSetFactory.java | 6 +- .../net/sourceforge/pmd/RuleSetWriter.java | 8 +-- .../AbstractMultiNumericProperty.java | 4 +- .../AbstractMultiPackagedProperty.java | 10 +-- .../AbstractMultiValueProperty.java | 13 ++-- .../properties/AbstractNumericProperty.java | 9 +-- .../properties/AbstractPackagedProperty.java | 9 +-- .../rule/properties/AbstractProperty.java | 10 ++- .../AbstractSingleValueProperty.java | 5 +- .../rule/properties/BooleanMultiProperty.java | 15 +++-- .../lang/rule/properties/BooleanProperty.java | 15 +++-- .../properties/CharacterMultiProperty.java | 37 ++++++----- .../rule/properties/CharacterProperty.java | 15 +++-- .../rule/properties/DoubleMultiProperty.java | 14 ++-- .../lang/rule/properties/DoubleProperty.java | 18 ++++-- .../properties/EnumeratedMultiProperty.java | 25 +++++--- .../rule/properties/EnumeratedProperty.java | 54 ++++++++++++---- .../lang/rule/properties/FileProperty.java | 22 ++++++- .../rule/properties/FloatMultiProperty.java | 17 +++-- .../lang/rule/properties/FloatProperty.java | 19 ++++-- .../rule/properties/IntegerMultiProperty.java | 17 +++-- .../lang/rule/properties/IntegerProperty.java | 13 +++- .../rule/properties/LongMultiProperty.java | 16 +++-- .../lang/rule/properties/LongProperty.java | 18 ++++-- .../rule/properties/MethodMultiProperty.java | 30 +++++---- .../lang/rule/properties/MethodProperty.java | 33 ++++++++-- .../MultiValuePropertyDescriptorFactory.java | 6 +- .../properties/PropertyDescriptorWrapper.java | 6 ++ .../SingleValuePropertyDescriptorFactory.java | 6 +- .../rule/properties/StringMultiProperty.java | 18 ++++-- .../lang/rule/properties/StringProperty.java | 16 ++++- .../rule/properties/TypeMultiProperty.java | 29 +++------ .../lang/rule/properties/TypeProperty.java | 19 ++++-- .../pmd/lang/rule/properties/ValueParser.java | 9 +++ .../NonRuleWithAllPropertyTypes.java | 3 +- .../pmd/properties/TypePropertyTest.java | 28 +++++--- 40 files changed, 467 insertions(+), 210 deletions(-) rename pmd-core/src/main/java/net/sourceforge/pmd/{lang/rule/properties/BasicPropertyDescriptorFactory.java => AbstractPropertyDescriptorFactory.java} (75%) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java similarity index 75% rename from pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java rename to pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index cbfd86114c..9aae00a602 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BasicPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -2,7 +2,7 @@ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ -package net.sourceforge.pmd.lang.rule.properties; +package net.sourceforge.pmd; import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; @@ -18,19 +18,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import net.sourceforge.pmd.PropertyDescriptorFactory; -import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.lang.rule.properties.ValueParser; import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** * Basic implementation of a property descriptor factory. * - * @param + * @param The type of values property descriptor returned by this factory. This can be a list. * * @author Brian Remedios */ -public abstract class BasicPropertyDescriptorFactory implements PropertyDescriptorFactory { +public abstract class AbstractPropertyDescriptorFactory implements PropertyDescriptorFactory { protected static final Map CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESCRIPTION, DEFAULT_VALUE, DELIMITER}, @@ -41,13 +40,13 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr private final Map fieldTypesByKey; - public BasicPropertyDescriptorFactory(Class theValueType) { + public AbstractPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY); } - public BasicPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { + public AbstractPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; Map temp @@ -114,7 +113,7 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr protected static String[] labelsIn(Map valuesById) { return StringUtil.substringsOf(valuesById.get(PropertyDescriptorField.LABELS), - AbstractMultiValueProperty.DEFAULT_DELIMITER); + MultiValuePropertyDescriptor.DEFAULT_DELIMITER); } @@ -140,7 +139,7 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr protected static char delimiterIn(Map valuesById) { - return delimiterIn(valuesById, AbstractMultiValueProperty.DEFAULT_DELIMITER); + return delimiterIn(valuesById, MultiValuePropertyDescriptor.DEFAULT_DELIMITER); } @@ -185,8 +184,8 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr } - public static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, Boolean[] - otherValues) { + public static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, + Boolean[] otherValues) { Map largerMap = new HashMap<>( otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size()); largerMap.putAll(CORE_FIELD_TYPES_BY_KEY); @@ -196,13 +195,38 @@ public abstract class BasicPropertyDescriptorFactory implements PropertyDescr return largerMap; } - // protected static Map - // factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) { - // Map factoryMap = new HashMap(factories.length); - // for (PropertyDescriptorFactory factory : factories) - // factoryMap.put(factory.typeId(), factory); - // return factoryMap; - // } - // + + @Override + public final PropertyDescriptor createWith(Map 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 createExternalWith(Map 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 createWith(Map valuesById, boolean isExternallyDefined); + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java index c010060f9d..092bd6edf5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java @@ -17,6 +17,13 @@ import java.util.List; */ public interface MultiValuePropertyDescriptor extends PropertyDescriptor> { + /** Default delimiter for multi-valued properties other than numeric ones. */ + char DEFAULT_DELIMITER = '|'; + + /** Default delimiter for numeric multi-valued properties. */ + char DEFAULT_NUMERIC_DELIMITER = ','; + + /** * Return the character being used to delimit multiple property values within a single string. You must ensure that * this character does not appear within any rule property values to avoid deserialization errors. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 57bd7d7b2e..1fbf7a8694 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -156,4 +156,16 @@ public interface PropertyDescriptor extends Comparable> * @return map */ Map attributeValuesById(); + + + /** + * True if this descriptor was defined in the ruleset xml. This precision is + * necessary for the {@link RuleSetWriter} to write out the property correctly: + * if it was defined externally, then its definition must be written out, otherwise + * only its value. + * + * @return True if the descriptor was defined in xml + */ + boolean isDefinedExternally(); + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index 746f26df48..0990938b6e 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -9,7 +9,7 @@ import java.util.Map; /** * A factory to create {@link PropertyDescriptor}s based on a map of values. * - * @param the type of values property descriptor returned by this factory. This can be a list. + * @param The type of values property descriptor returned by this factory. This can be a list. * * @author Brian Remedios */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index d3ccdc6233..cc1c3751d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -38,7 +38,6 @@ import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.util.ResourceLoader; import net.sourceforge.pmd.util.StringUtil; @@ -850,10 +849,9 @@ public class RuleSetFactory { values.put(entry.getKey(), valueStr); } - PropertyDescriptor desc = pdFactory.createWith(values); - PropertyDescriptorWrapper wrapper = PropertyDescriptorWrapper.getWrapper(desc); + PropertyDescriptor desc = ((AbstractPropertyDescriptorFactory) pdFactory).createExternalWith(values); - rule.definePropertyDescriptor(wrapper); + rule.definePropertyDescriptor(desc); setValue(rule, desc, strValue); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 428138e5fd..09104f3da0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -33,7 +33,6 @@ import net.sourceforge.pmd.lang.rule.ImmutableLanguage; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; /** * This class represents a way to serialize a RuleSet to an XML configuration @@ -268,14 +267,13 @@ public class RuleSetWriter { for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { // For each provided PropertyDescriptor - if (propertyDescriptor instanceof PropertyDescriptorWrapper) { - // Any wrapper property needs to go out as a definition. + if (propertyDescriptor.isDefinedExternally()) { + // Any externally defined property needs to go out as a definition. if (propertiesElement == null) { propertiesElement = createPropertiesElement(); } - Element propertyElement = createPropertyDefinitionElementBR( - ((PropertyDescriptorWrapper) propertyDescriptor).getPropertyDescriptor()); + Element propertyElement = createPropertyDefinitionElementBR(propertyDescriptor); propertiesElement.appendChild(propertyElement); } else { if (propertiesByPropertyDescriptor != null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 104b9dc65f..6559bd517d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -42,8 +42,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; * the bounds */ AbstractMultiNumericProperty(String theName, String theDescription, T lower, T upper, List theDefault, - float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); lowerLimit = lower; upperLimit = upper; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index cf433e480d..5b73987465 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import net.sourceforge.pmd.AbstractPropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; /** @@ -28,8 +29,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; protected static final char DELIMITER = '|'; /** Required keys in the map. */ protected static final Map PACKAGED_FIELD_TYPES_BY_KEY - = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, - new Boolean[] {false}); + = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, + new Boolean[] {false}); private static final char PACKAGE_NAME_DELIMITER = ' '; private String[] legalPackageNames; @@ -46,8 +47,9 @@ import net.sourceforge.pmd.PropertyDescriptorField; * @throws IllegalArgumentException */ protected AbstractMultiPackagedProperty(String theName, String theDescription, List theDefault, - String[] theLegalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); + String[] theLegalPackageNames, float theUIOrder, + boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); checkValidPackages(theDefault, theLegalPackageNames); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index e37b9e0112..7b9ce94008 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -26,11 +26,7 @@ import net.sourceforge.pmd.util.StringUtil; /* default */ abstract class AbstractMultiValueProperty extends AbstractProperty> implements MultiValuePropertyDescriptor { - /** Default delimiter for multi-valued properties other than numeric ones. */ - public static final char DEFAULT_DELIMITER = '|'; - /** Default delimiter for numeric multi-valued properties. */ - public static final char DEFAULT_NUMERIC_DELIMITER = ','; /** The default value. */ private final List defaultValue; @@ -47,8 +43,9 @@ import net.sourceforge.pmd.util.StringUtil; * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder) { - this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER); + AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder, + boolean isDefinedExternally) { + this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER, isDefinedExternally); } @@ -64,9 +61,9 @@ import net.sourceforge.pmd.util.StringUtil; * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ AbstractMultiValueProperty(String theName, String theDescription, List theDefault, - float theUIOrder, char delimiter) { + float theUIOrder, char delimiter, boolean isDefinedExternally) { - super(theName, theDescription, theUIOrder); + super(theName, theDescription, theUIOrder, isDefinedExternally); defaultValue = Collections.unmodifiableList(theDefault); multiValueDelimiter = delimiter; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index f338437454..1ef679fb64 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -9,6 +9,7 @@ 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; @@ -25,8 +26,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; implements NumericPropertyDescriptor { public static final Map NUMBER_FIELD_TYPES_BY_KEY - = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, - new Boolean[] {true, true}); + = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, + new Boolean[] {true, true}); private T lowerLimit; private T upperLimit; @@ -46,8 +47,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; * bounds */ protected AbstractNumericProperty(String theName, String theDescription, T lower, T upper, T theDefault, - float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); lowerLimit = lower; upperLimit = upper; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index c2c1d9e3b2..0b657c7fe4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -10,6 +10,7 @@ import java.util.Arrays; import java.util.Map; import java.util.regex.Pattern; +import net.sourceforge.pmd.AbstractPropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.StringUtil; @@ -26,8 +27,8 @@ import net.sourceforge.pmd.util.StringUtil; /** Required keys in the map. */ protected static final Map PACKAGED_FIELD_TYPES_BY_KEY - = BasicPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, - new Boolean[] {false}); + = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, + new Boolean[] {false}); private static final char PACKAGE_NAME_DELIMITER = ' '; private static Pattern packageNamePattern = Pattern.compile("(\\w+)(\\.\\w+)*"); @@ -46,8 +47,8 @@ import net.sourceforge.pmd.util.StringUtil; * @throws IllegalArgumentException */ protected AbstractPackagedProperty(String theName, String theDescription, T theDefault, - String[] theLegalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); + String[] theLegalPackageNames, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); checkValidPackages(theDefault, theLegalPackageNames); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index d66f84010b..24ef0fb376 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -28,6 +28,7 @@ import net.sourceforge.pmd.util.StringUtil; private final String name; private final String description; private final float uiOrder; + private final boolean isDefinedExternally; /** @@ -39,8 +40,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - protected AbstractProperty(String theName, String theDescription, - float theUIOrder) { + protected AbstractProperty(String theName, String theDescription, float theUIOrder, boolean isDefinedExternally) { if (theUIOrder < 0) { throw new IllegalArgumentException("Property attribute 'UI order' cannot be null or blank"); } @@ -48,6 +48,7 @@ import net.sourceforge.pmd.util.StringUtil; name = checkNotEmpty(theName, NAME); description = checkNotEmpty(theDescription, DESCRIPTION); uiOrder = theUIOrder; + this.isDefinedExternally = isDefinedExternally; } @@ -156,4 +157,9 @@ import net.sourceforge.pmd.util.StringUtil; */ /* default */ abstract PropertyDescriptorWrapper getWrapper(); + + @Override + public boolean isDefinedExternally() { + return isDefinedExternally; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index d1f37748be..44e83b085c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -31,8 +31,9 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ - protected AbstractSingleValueProperty(String theName, String theDescription, T theDefault, float theUIOrder) { - super(theName, theDescription, theUIOrder); + protected AbstractSingleValueProperty(String theName, String theDescription, T theDefault, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theUIOrder, isDefinedExternally); defaultValue = theDefault; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index 3fc5e35d07..997855fe29 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -24,12 +24,13 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Boolean.class) { @Override - public BooleanMultiProperty createWith(Map valuesById) { + public BooleanMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new BooleanMultiProperty(nameIn(valuesById), descriptionIn(valuesById), parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -43,7 +44,7 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder) { - super(theName, theDescription, defaultValues, theUIOrder); + this(theName, theDescription, defaultValues, theUIOrder, false); + } + + + private BooleanMultiProperty(String theName, String theDescription, List defaultValues, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index e7a47e1348..ffbb43a3cd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -23,11 +23,12 @@ public final class BooleanProperty extends AbstractSingleValueProperty public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Boolean.class) { @Override - public BooleanProperty createWith(Map valuesById) { + public BooleanProperty createWith(Map valuesById, boolean isDefinedExternally) { return new BooleanProperty(nameIn(valuesById), descriptionIn(valuesById), BOOLEAN_PARSER.valueOf(defaultValueIn(valuesById)), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -41,10 +42,10 @@ public final class BooleanProperty extends AbstractSingleValueProperty * @param defaultBoolStr String representing the default value. * @param theUIOrder UI order * - * @deprecated ? + * @deprecated will be removed in 7.0.0 */ public BooleanProperty(String theName, String theDescription, String defaultBoolStr, float theUIOrder) { - this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder); + this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder, false); } @@ -57,10 +58,14 @@ public final class BooleanProperty extends AbstractSingleValueProperty * @param theUIOrder UI order */ public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) { - super(theName, theDescription, defaultValue, theUIOrder); + this(theName, theDescription, defaultValue, theUIOrder, false); } + private BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); + } + @Override public Class type() { return Boolean.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 811f3352fd..5b2ef644db 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -25,13 +25,14 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Character.class) { @Override - public CharacterMultiProperty createWith(Map valuesById) { + public CharacterMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new CharacterMultiProperty(nameIn(valuesById), descriptionIn(valuesById), parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParser.CHARACTER_PARSER), 0.0f, - delimiter); + delimiter, + isDefinedExternally); } }; // @formatter:on @@ -47,9 +48,22 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder, + char delimiter, boolean isDefinedExternally) { + super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally); + + if (defaultValues != null) { + for (Character c : defaultValues) { + if (c == delimiter) { + throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); + } + } + } } @@ -64,17 +78,8 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder, - char delimiter) { - super(theName, theDescription, defaultValues, theUIOrder, delimiter); - - if (defaultValues != null) { - for (Character c : defaultValues) { - if (c == delimiter) { - throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); - } - } - } + public CharacterMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder, char delimiter) { + this(theName, theDescription, defaultValues, theUIOrder, delimiter, false); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 43af6603a8..6c2426acab 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -22,12 +22,13 @@ public final class CharacterProperty extends AbstractSingleValueProperty FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Character.class) { @Override - public CharacterProperty createWith(Map valuesById) { + public CharacterProperty createWith(Map valuesById, boolean isDefinedExternally) { return new CharacterProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById) == null ? null : defaultValueIn(valuesById).charAt(0), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -41,9 +42,10 @@ public final class CharacterProperty extends AbstractSingleValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public DoubleMultiProperty createWith(Map valuesById) { + public DoubleMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER); @@ -35,7 +35,8 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty defaultValues, float theUIOrder) { - super(theName, theDescription, min, max, defaultValues, theUIOrder); + this(theName, theDescription, min, max, defaultValues, theUIOrder, false); + } + + private DoubleMultiProperty(String theName, String theDescription, Double min, Double max, + List defaultValues, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 2b3f1da8ae..a2650ad8c8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -23,14 +23,16 @@ public final class DoubleProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public DoubleProperty createWith(Map valuesById) { + public DoubleProperty createWith(Map valuesById, + boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); return new DoubleProperty(nameIn(valuesById), descriptionIn(valuesById), DOUBLE_PARSER.valueOf(minMax[0]), DOUBLE_PARSER.valueOf(minMax[1]), DOUBLE_PARSER.valueOf(numericDefaultValueIn(valuesById)), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -47,11 +49,11 @@ public final class DoubleProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - * @deprecated ? + * @deprecated will be removed in 7.0.0 */ public DoubleProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { - this(theName, theDescription, doubleFrom(minStr), doubleFrom(maxStr), doubleFrom(defaultStr), theUIOrder); + this(theName, theDescription, doubleFrom(minStr), doubleFrom(maxStr), doubleFrom(defaultStr), theUIOrder, false); } @@ -69,7 +71,13 @@ public final class DoubleProperty extends AbstractNumericProperty { */ public DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); + this(theName, theDescription, min, max, theDefault, theUIOrder, false); + } + + + private DoubleProperty(String theName, String theDescription, Double min, Double max, Double theDefault, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index 3f1c52e09a..f53f28d76b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -16,7 +16,7 @@ import net.sourceforge.pmd.util.CollectionUtil; /** * Multi-valued property which can take only a fixed set of values of any type, then selected via String labels. The - * choices method returns the set of mappings between the labels and their values. + * mappings method returns the set of mappings between the labels and their values. * * @param The type of the values * @@ -30,14 +30,15 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty public static final PropertyDescriptorFactory> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Object.class) { // TODO:cf is Object the right type? @Override - public EnumeratedMultiProperty createWith(Map valuesById) { + public EnumeratedMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { + Object[] choices = choicesIn(valuesById); return new EnumeratedMultiProperty<>(nameIn(valuesById), descriptionIn(valuesById), - labelsIn(valuesById), - choicesIn(valuesById), - indicesIn(valuesById), + CollectionUtil.mapFrom(labelsIn(valuesById), choices), + selection(indicesIn(valuesById), choices), classIn(valuesById), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -60,10 +61,9 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - selection(choiceIndices, theChoices), valueType, theUIOrder); + selection(choiceIndices, theChoices), valueType, theUIOrder, false); } - /** * Constructor using a map to define the label-value mappings. The default values are specified with a list. * @@ -75,7 +75,14 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty */ public EnumeratedMultiProperty(String theName, String theDescription, Map choices, List defaultValues, Class valueType, float theUIOrder) { - super(theName, theDescription, defaultValues, theUIOrder); + this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false); + } + + + private EnumeratedMultiProperty(String theName, String theDescription, Map choices, + List defaultValues, Class valueType, float theUIOrder, + boolean isDefinedExternally) { + super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally); checkDefaults(defaultValues, choices); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index fd386b6e67..db6c8f1539 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -14,12 +14,12 @@ import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.CollectionUtil; /** - * Defines a datatype with a set of preset values of any type as held within a - * pair of maps. While the values are not serialized out, the labels are and - * serve as keys to obtain the values. The choices() method provides the ordered - * selections to be used in an editor widget. + * Property which can take only a fixed set of values of any type, then selected via String labels. The + * mappings method returns the set of mappings between the labels and their values. * - * @param Type of the choices + *

This property currently doesn't support serialization and cannot be defined in a ruleset file.z + * + * @param Type of the values * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) @@ -32,14 +32,16 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty = new SingleValuePropertyDescriptorFactory(Enumeration.class) { // TODO:cf Enumeration? Object? @Override - public EnumeratedProperty createWith(Map valuesById) { + public EnumeratedProperty createWith(Map valuesById, boolean isDefinedExternally) { + Map labelsToChoices = CollectionUtil.mapFrom(labelsIn(valuesById), // this is not implemented + choicesIn(valuesById)); // ditto return new EnumeratedProperty<>(nameIn(valuesById), descriptionIn(valuesById), - labelsIn(valuesById), // this is not implemented - choicesIn(valuesById), // ditto - indexIn(valuesById), // ditto + labelsToChoices, + choicesIn(valuesById)[indexIn(valuesById)], classIn(valuesById), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -49,16 +51,44 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty private final Class valueType; + /** + * Constructor using arrays to define the label-value mappings. The correct construction of the property depends + * on the correct ordering of the arrays. + * + * @param theName Name + * @param theDescription Description + * @param theLabels Labels of the choices + * @param theChoices Values that can be chosen + * @param defaultIndex The index of the default value. + * @param theUIOrder UI order + * + * @deprecated will be removed in 7.0.0. Use a map. + */ public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int defaultIndex, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - theChoices[defaultIndex], valueType, theUIOrder); + theChoices[defaultIndex], valueType, theUIOrder, false); } + /** + * Constructor using a map to define the label-value mappings. + * + * @param theName Name + * @param theDescription Description + * @param labelsToChoices Map of labels to values + * @param defaultValue Default value + * @param theUIOrder UI order + */ public EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, E defaultValue, Class valueType, float theUIOrder) { - super(theName, theDescription, defaultValue, theUIOrder); + this(theName, theDescription, labelsToChoices, defaultValue, valueType, theUIOrder, false); + } + + + private EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, + E defaultValue, Class valueType, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); this.valueType = valueType; choicesByLabel = Collections.unmodifiableMap(labelsToChoices); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index bfed9815e1..a1055fdfe5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -23,17 +23,33 @@ public final class FileProperty extends AbstractSingleValueProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(File.class) { @Override - public FileProperty createWith(Map valuesById) { - return new FileProperty(nameIn(valuesById), descriptionIn(valuesById), null, 0f); + public FileProperty createWith(Map valuesById, boolean isDefinedExternally) { + return new FileProperty(nameIn(valuesById), + descriptionIn(valuesById), + null, + 0f, + isDefinedExternally); } }; // @formatter:on + /** + * Constructor for file property. + * + * @param theName Name of the property + * @param theDescription Description + * @param theDefault Default value + * @param theUIOrder UI order + */ public FileProperty(String theName, String theDescription, File theDefault, float theUIOrder) { - super(theName, theDescription, theDefault, theUIOrder); + super(theName, theDescription, theDefault, theUIOrder, false); } + private FileProperty(String theName, String theDescription, File theDefault, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); + } + @Override public Class type() { return File.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 99382bd738..6ba7af0bbc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -26,7 +26,8 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public FloatMultiProperty createWith(Map valuesById) { + public FloatMultiProperty createWith(Map valuesById, + boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); @@ -34,7 +35,9 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty defaultValues, float theUIOrder) { - super(theName, theDescription, min, max, defaultValues, theUIOrder); + this(theName, theDescription, min, max, defaultValues, theUIOrder, false); + } + + + private FloatMultiProperty(String theName, String theDescription, Float min, Float max, + List defaultValues, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index d7b8503d90..4240e88138 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -23,13 +23,15 @@ public final class FloatProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public FloatProperty createWith(Map valuesById) { + public FloatProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); return new FloatProperty(nameIn(valuesById), descriptionIn(valuesById), FLOAT_PARSER.valueOf(minMax[0]), FLOAT_PARSER.valueOf(minMax[1]), - FLOAT_PARSER.valueOf(numericDefaultValueIn(valuesById)), 0f); + FLOAT_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f, + isDefinedExternally); } }; // @formatter:on @@ -46,11 +48,12 @@ public final class FloatProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - * @deprecated ? + * @deprecated will be removed in 7.0.0 */ public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { - this(theName, theDescription, FLOAT_PARSER.valueOf(minStr), FLOAT_PARSER.valueOf(maxStr), FLOAT_PARSER.valueOf(defaultStr), theUIOrder); + this(theName, theDescription, FLOAT_PARSER.valueOf(minStr), + FLOAT_PARSER.valueOf(maxStr), FLOAT_PARSER.valueOf(defaultStr), theUIOrder, false); } @@ -68,7 +71,13 @@ public final class FloatProperty extends AbstractNumericProperty { */ public FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); + this(theName, theDescription, min, max, theDefault, theUIOrder, false); + } + + + private FloatProperty(String theName, String theDescription, Float min, Float max, Float theDefault, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 51f02f1588..a6ce64db55 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -26,7 +26,8 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public IntegerMultiProperty createWith(Map valuesById) { + public IntegerMultiProperty createWith(Map valuesById, boolean + isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); @@ -35,7 +36,8 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty defaultValues, float theUIOrder) { - super(theName, theDescription, min, max, defaultValues, theUIOrder); + this(theName, theDescription, min, max, defaultValues, theUIOrder, false); + } + + + private IntegerMultiProperty(String theName, String theDescription, Integer min, Integer max, + List defaultValues, float theUIOrder, boolean isDefinedExternally) { + + super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index bbe2e29bb7..694349e9d7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -22,14 +22,15 @@ public final class IntegerProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public IntegerProperty createWith(Map valuesById) { + public IntegerProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); return new IntegerProperty(nameIn(valuesById), descriptionIn(valuesById), INTEGER_PARSER.valueOf(minMax[0]), INTEGER_PARSER.valueOf(minMax[1]), INTEGER_PARSER.valueOf(numericDefaultValueIn(valuesById)), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -48,7 +49,13 @@ public final class IntegerProperty extends AbstractNumericProperty { */ public IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); + this(theName, theDescription, min, max, theDefault, theUIOrder, false); + } + + + private IntegerProperty(String theName, String theDescription, Integer min, Integer max, Integer theDefault, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, theDefault, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 12f7616385..8eaf0af35d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -26,7 +26,7 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty public static final PropertyDescriptorFactory> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public LongMultiProperty createWith(Map valuesById) { + public LongMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); List defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); @@ -34,7 +34,9 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty descriptionIn(valuesById), LONG_PARSER.valueOf(minMax[0]), LONG_PARSER.valueOf(minMax[1]), - defaultValues, 0f); + defaultValues, + 0f, + isDefinedExternally); } }; // @formatter:on @@ -53,7 +55,7 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty */ public LongMultiProperty(String theName, String theDescription, Long min, Long max, Long[] defaultValues, float theUIOrder) { - super(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder); + this(theName, theDescription, min, max, Arrays.asList(defaultValues), theUIOrder, false); } @@ -71,7 +73,13 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty */ public LongMultiProperty(String theName, String theDescription, Long min, Long max, List defaultValues, float theUIOrder) { - super(theName, theDescription, min, max, defaultValues, theUIOrder); + this(theName, theDescription, min, max, defaultValues, theUIOrder, false); + } + + + private LongMultiProperty(String theName, String theDescription, Long min, Long max, + List defaultValues, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index a4adba5aa9..2683d0c86a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -23,13 +23,15 @@ public final class LongProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override - public LongProperty createWith(Map valuesById) { + public LongProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); return new LongProperty(nameIn(valuesById), descriptionIn(valuesById), LONG_PARSER.valueOf(minMax[0]), LONG_PARSER.valueOf(minMax[1]), - LONG_PARSER.valueOf(numericDefaultValueIn(valuesById)), 0f); + LONG_PARSER.valueOf(numericDefaultValueIn(valuesById)), + 0f, + isDefinedExternally); } }; // @formatter:on @@ -47,11 +49,12 @@ public final class LongProperty extends AbstractNumericProperty { * @param theUIOrder UI order * * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds - * @deprecated ? + * @deprecated will be removed in 7.0.0 */ public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { - this(theName, theDescription, Long.valueOf(minStr), Long.valueOf(maxStr), Long.valueOf(defaultStr), theUIOrder); + this(theName, theDescription, Long.valueOf(minStr), Long.valueOf(maxStr), + Long.valueOf(defaultStr), theUIOrder, false); } @@ -68,7 +71,12 @@ public final class LongProperty extends AbstractNumericProperty { * @throws IllegalArgumentException if min > max or one of the defaults is not between the bounds */ public LongProperty(String theName, String theDescription, Long min, Long max, Long theDefault, float theUIOrder) { - super(theName, theDescription, min, max, theDefault, theUIOrder); + 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); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 747c7ccf6c..71e01afb9c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -31,10 +31,14 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override - public MethodMultiProperty createWith(Map valuesById) { + public MethodMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); - return new MethodMultiProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), 0f); + return new MethodMultiProperty(nameIn(valuesById), + descriptionIn(valuesById), + methodsFrom(defaultValueIn(valuesById)), + legalPackageNamesIn(valuesById, delimiter), + 0f, + isDefinedExternally); } }; // @formatter:on @@ -58,7 +62,13 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty theDefaults, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); + this(theName, theDescription, theDefaults, legalPackageNames, theUIOrder, false); + } + + + private MethodMultiProperty(String theName, String theDescription, List theDefaults, + String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder, isDefinedExternally); } @@ -75,7 +85,7 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty otherParams, float theUIOrder) { - this(theName, theDescription, methodsFrom(methodDefaults), packageNamesIn(otherParams), theUIOrder); - } - - @Override public String asString(Method value) { return value == null ? "" : MethodProperty.asStringFor(value); @@ -113,8 +116,7 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override - public MethodProperty createWith(Map valuesById) { + public MethodProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new MethodProperty(nameIn(valuesById), descriptionIn(valuesById), - defaultValueIn(valuesById), + methodFrom(defaultValueIn(valuesById)), legalPackageNamesIn(valuesById, delimiter), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on private static final String ARRAY_FLAG = "[]"; @@ -48,15 +49,37 @@ public final class MethodProperty extends AbstractPackagedProperty { public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); + this(theName, theDescription, theDefault, legalPackageNames, theUIOrder, false); } + /** + * Constructor for MethodProperty using a string as a default value. + * + * @param theName Name of the property + * @param theDescription Description + * @param defaultMethodStr Default value, that will be parsed into a Method object + * @param legalPackageNames Legal packages + * @param theUIOrder UI order + */ public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder); + this(theName, theDescription, methodFrom(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) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java index c77b67aa49..e256ae0ad7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.List; import java.util.Map; +import net.sourceforge.pmd.AbstractPropertyDescriptorFactory; import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; @@ -18,7 +19,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; * @author Clément Fournier * @since 6.0.0 */ -public abstract class MultiValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory> { +public abstract class MultiValuePropertyDescriptorFactory extends AbstractPropertyDescriptorFactory> { public MultiValuePropertyDescriptorFactory(Class theValueType) { super(theValueType); @@ -32,7 +33,8 @@ public abstract class MultiValuePropertyDescriptorFactory extends BasicProper @Override - public abstract MultiValuePropertyDescriptor createWith(Map valuesById); + protected abstract MultiValuePropertyDescriptor createWith(Map valuesById, + boolean isDefinedExternally); @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java index 00947d4869..fe76361d8c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java @@ -110,6 +110,12 @@ public class PropertyDescriptorWrapper implements PropertyDescriptor { } + @Override + public boolean isDefinedExternally() { + return false; + } + + @Override public boolean equals(Object obj) { if (obj instanceof PropertyDescriptorWrapper) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java index beb4c70a30..c04b829170 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.Map; +import net.sourceforge.pmd.AbstractPropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.SingleValuePropertyDescriptor; @@ -17,7 +18,7 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; * @author Clément Fournier * @since 6.0.0 */ -public abstract class SingleValuePropertyDescriptorFactory extends BasicPropertyDescriptorFactory { +public abstract class SingleValuePropertyDescriptorFactory extends AbstractPropertyDescriptorFactory { public SingleValuePropertyDescriptorFactory(Class theValueType) { super(theValueType); @@ -31,7 +32,8 @@ public abstract class SingleValuePropertyDescriptorFactory extends BasicPrope @Override - public abstract SingleValuePropertyDescriptor createWith(Map valuesById); + public abstract SingleValuePropertyDescriptor createWith(Map valuesById, + boolean isDefinedExternally); @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 56b4b3687b..e1eb927dff 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.ValueParser.STRING_PARSER; + import java.util.Arrays; import java.util.List; import java.util.Map; @@ -25,13 +27,14 @@ public final class StringMultiProperty extends AbstractMultiValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(String.class) { @Override - public StringMultiProperty createWith(Map valuesById) { + public StringMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new StringMultiProperty(nameIn(valuesById), descriptionIn(valuesById), - StringUtil.substringsOf(defaultValueIn(valuesById), delimiter), + parsePrimitives(defaultValueIn(valuesById), delimiter, STRING_PARSER), 0.0f, - delimiter); + delimiter, + isDefinedExternally); } }; // @formatter:on @@ -68,7 +71,14 @@ public final class StringMultiProperty extends AbstractMultiValueProperty defaultValues, float theUIOrder, char delimiter) { - super(theName, theDescription, defaultValues, theUIOrder, delimiter); + this(theName, theDescription, defaultValues, theUIOrder, delimiter, false); + } + + + /** For external defition. */ + private StringMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder, + char delimiter, boolean isDefinedExternally) { + super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally); checkDefaults(defaultValues, delimiter); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 83f8426b94..58f94d757c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -21,8 +21,12 @@ public final class StringProperty extends AbstractSingleValueProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(String.class) { @Override - public StringProperty createWith(Map valuesById) { - return new StringProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById), 0f); + public StringProperty createWith(Map valuesById, boolean isDefinedExternally) { + return new StringProperty(nameIn(valuesById), + descriptionIn(valuesById), + defaultValueIn(valuesById), + 0f, + isDefinedExternally); } }; // @formatter:on @@ -36,7 +40,13 @@ public final class StringProperty extends AbstractSingleValueProperty { * @param theUIOrder UI order */ public StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder) { - super(theName, theDescription, defaultValue, theUIOrder); + this(theName, theDescription, defaultValue, theUIOrder, false); + } + + + private StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder, boolean + isDefinedExternally) { + super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 766b08f56f..7db4f1be85 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; @@ -27,7 +26,7 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override - public TypeMultiProperty createWith(Map valuesById) { + public TypeMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new TypeMultiProperty(nameIn(valuesById), descriptionIn(valuesById), @@ -38,23 +37,6 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty theDefaults, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefaults, legalPackageNames, theUIOrder); + this(theName, theDescription, theDefaults, legalPackageNames, theUIOrder, false); } @@ -86,11 +68,16 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty theTypeDefaults, + String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theTypeDefaults, legalPackageNames, theUIOrder, isDefinedExternally); + } + /** * Returns a list of Class objects parsed from the input string. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java index 884882a1a1..0751cc2387 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeProperty.java @@ -25,13 +25,14 @@ public final class TypeProperty extends AbstractPackagedProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override - public TypeProperty createWith(Map valuesById) { + public TypeProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); return new TypeProperty(nameIn(valuesById), descriptionIn(valuesById), - defaultValueIn(valuesById), + classFrom(defaultValueIn(valuesById)), legalPackageNamesIn(valuesById, delimiter), - 0f); + 0f, + isDefinedExternally); } }; // @formatter:on @@ -46,10 +47,11 @@ public final class TypeProperty extends AbstractPackagedProperty { * @param theUIOrder float * * @throws IllegalArgumentException if the default string could not be parsed into a Class + * @deprecated will be removed in 7.0.0 */ public TypeProperty(String theName, String theDescription, String defaultTypeStr, String[] legalPackageNames, float theUIOrder) { - this(theName, theDescription, classFrom(defaultTypeStr), legalPackageNames, theUIOrder); + this(theName, theDescription, classFrom(defaultTypeStr), legalPackageNames, theUIOrder, false); } @@ -62,11 +64,16 @@ public final class TypeProperty extends AbstractPackagedProperty { * @param legalPackageNames String[] * @param theUIOrder float * - * @throws IllegalArgumentException */ public TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, float theUIOrder) { - super(theName, theDescription, theDefault, legalPackageNames, theUIOrder); + this(theName, theDescription, theDefault, legalPackageNames, theUIOrder, false); + } + + + private TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, legalPackageNames, theUIOrder, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java index 21cd075f4c..d66f9370e4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java @@ -24,6 +24,15 @@ public interface ValueParser { } }; + + /** Extracts strings. That's a dummy used to return a list in StringMultiProperty. */ + ValueParser STRING_PARSER = new ValueParser() { + @Override + public String valueOf(String value) { + return value; + } + }; + // FUTURE Integer::valueOf /** Extracts integers. */ ValueParser INTEGER_PARSER = new ValueParser() { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java index a8858d4b59..3fbd0a95a0 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.properties; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.List; import net.sourceforge.pmd.RuleContext; @@ -71,7 +72,7 @@ public class NonRuleWithAllPropertyTypes extends AbstractRule { public static final TypeProperty SINGLE_TYPE = new TypeProperty("singleType", "Single type", String.class, new String[] {"java.lang"}, 5.0f); public static final TypeMultiProperty MULTI_TYPE = new TypeMultiProperty("multiType", "Multiple types", - new Class[] {Integer.class, Object.class}, new String[] {"java.lang"}, 6.0f); + Arrays.asList(Integer.class, Object.class), new String[] {"java.lang"}, 6.0f); public static final EnumeratedProperty ENUM_TYPE = new EnumeratedProperty<>("enumType", "Enumerated choices", new String[] {"String", "Object"}, new Class[] {String.class, Object.class}, 1, Class.class, 5.0f); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java index bf7fa53430..852011c584 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.properties; +import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -28,46 +30,54 @@ import net.sourceforge.pmd.lang.rule.properties.TypeProperty; */ public class TypePropertyTest extends AbstractPropertyDescriptorTester { - private static final Class[] JAVA_LANG_CLASSES = {String.class, Integer.class, Thread.class, - Object.class, Runtime.class, }; - private static final Class[] JAVA_UTIL_CLASSES = {HashMap.class, Map.class, Comparator.class, Set.class, - Observer.class, }; + private static final List JAVA_LANG_CLASSES = Arrays.asList(String.class, Integer.class, Thread.class, + Object.class, Runtime.class); + private static final List JAVA_UTIL_CLASSES = Arrays.asList(HashMap.class, Map.class, + Comparator.class, Set.class, + Observer.class); + public TypePropertyTest() { super("Class"); } + @Override protected Class createValue() { - return randomChoice(JAVA_LANG_CLASSES); + return JAVA_LANG_CLASSES.get(randomInt(0, JAVA_LANG_CLASSES.size())); } + @Override protected Class createBadValue() { - return randomChoice(JAVA_UTIL_CLASSES); + return JAVA_UTIL_CLASSES.get(randomInt(0, JAVA_UTIL_CLASSES.size())); } + @Override protected PropertyDescriptor createProperty() { - return new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] {"java.lang"}, + return new TypeProperty("testType", "Test type property", createValue(), new String[] {"java.lang"}, 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new TypeMultiProperty("testType", "Test type property", JAVA_LANG_CLASSES, new String[] {"java.lang"}, 1.0f); } + @Override protected PropertyDescriptor createBadProperty() { - return new TypeProperty("testType", "Test type property", JAVA_LANG_CLASSES[0], new String[] {"java.util"}, + return new TypeProperty("testType", "Test type property", createValue(), new String[] {"java.util"}, 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { - return new TypeMultiProperty("testType", "Test type property", new Class[] {Set.class}, + return new TypeMultiProperty("testType", "Test type property", Collections.singletonList(Set.class), new String[] {"java.lang"}, 1.0f); } } From 8474131f5bd11c3851de4ea40e3041b60c8fe22c Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 16:53:26 +0200 Subject: [PATCH 43/53] Removed wrappers altogether --- .../AbstractMultiNumericProperty.java | 4 - .../AbstractMultiValueProperty.java | 5 - .../properties/AbstractNumericProperty.java | 5 - .../rule/properties/AbstractProperty.java | 9 - .../AbstractSingleValueProperty.java | 5 - .../properties/EnumeratedMultiProperty.java | 5 - .../rule/properties/EnumeratedProperty.java | 5 - .../EnumeratedPropertyDescriptorWrapper.java | 28 --- ...ValueNumericPropertyDescriptorWrapper.java | 33 ---- .../MultiValuePropertyDescriptorWrapper.java | 33 ---- .../properties/PropertyDescriptorFactory.java | 160 ----------------- .../properties/PropertyDescriptorWrapper.java | 162 ------------------ ...ValueNumericPropertyDescriptorWrapper.java | 31 ---- .../SingleValuePropertyDescriptorWrapper.java | 25 --- .../lang/rule/xpath/SaxonXPathRuleQuery.java | 5 - ...stractNumericPropertyDescriptorTester.java | 24 --- .../AbstractPropertyDescriptorTester.java | 40 ----- .../SimpleEnumeratedPropertyTest.java | 19 -- 18 files changed, 598 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 6559bd517d..7945bdc1f0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -100,8 +100,4 @@ import net.sourceforge.pmd.PropertyDescriptorField; } - @Override - /* default */ PropertyDescriptorWrapper> getWrapper() { - return new MultiValueNumericPropertyDescriptorWrapper<>(this); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index 7b9ce94008..c5a646f176 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -206,9 +206,4 @@ import net.sourceforge.pmd.util.StringUtil; } - @Override - /* default */ PropertyDescriptorWrapper> getWrapper() { - return new MultiValuePropertyDescriptorWrapper<>(this); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 1ef679fb64..3b115a0116 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -139,9 +139,4 @@ import net.sourceforge.pmd.PropertyDescriptorField; } - @Override - /* default */ PropertyDescriptorWrapper getWrapper() { - return new SingleValueNumericPropertyDescriptorWrapper<>(this); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 24ef0fb376..16e29d07ca 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -149,15 +149,6 @@ import net.sourceforge.pmd.util.StringUtil; protected abstract String defaultAsString(); - /** - * Gets a wrapper for this property. This method ensures that a wrapper of a property always implements the same - * interfaces as that property using double dispatch. - * - * @return A wrapper for this property. - */ - /* default */ abstract PropertyDescriptorWrapper getWrapper(); - - @Override public boolean isDefinedExternally() { return isDefinedExternally; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java index 44e83b085c..2be7c22dec 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java @@ -140,9 +140,4 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; protected abstract T createFrom(String toParse); // this is there to be symmetrical to multi values - @Override - /* default */ PropertyDescriptorWrapper getWrapper() { - return new SingleValuePropertyDescriptorWrapper<>(this); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index f53f28d76b..b81b55aeed 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -162,9 +162,4 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty } - @Override - /* default */ PropertyDescriptorWrapper> getWrapper() { - return new EnumeratedPropertyDescriptorWrapper<>(this); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index db6c8f1539..70ef645d49 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -140,9 +140,4 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty } - @Override - /* default */ PropertyDescriptorWrapper getWrapper() { - return new EnumeratedPropertyDescriptorWrapper<>(this); - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java deleted file mode 100644 index 46b71c98bc..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedPropertyDescriptorWrapper.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.Map; - -import net.sourceforge.pmd.EnumeratedPropertyDescriptor; - -/** - * @author Clément Fournier - */ -/* default */ class EnumeratedPropertyDescriptorWrapper extends PropertyDescriptorWrapper - implements EnumeratedPropertyDescriptor { - - EnumeratedPropertyDescriptorWrapper(EnumeratedPropertyDescriptor propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public Map mappings() { - return ((EnumeratedPropertyDescriptor) propertyDescriptor).mappings(); - } - - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java deleted file mode 100644 index 388317efb2..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValueNumericPropertyDescriptorWrapper.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.List; - -import net.sourceforge.pmd.MultiValuePropertyDescriptor; -import net.sourceforge.pmd.NumericPropertyDescriptor; - -/** - * @author Clément Fournier - */ -/* default */ class MultiValueNumericPropertyDescriptorWrapper - extends MultiValuePropertyDescriptorWrapper implements NumericPropertyDescriptor> { - - > & MultiValuePropertyDescriptor> MultiValueNumericPropertyDescriptorWrapper(D propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public Number upperLimit() { - return ((NumericPropertyDescriptor) propertyDescriptor).upperLimit(); - } - - - @Override - public Number lowerLimit() { - return ((NumericPropertyDescriptor) propertyDescriptor).lowerLimit(); - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java deleted file mode 100644 index a7d9a211ca..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorWrapper.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.List; - -import net.sourceforge.pmd.MultiValuePropertyDescriptor; - -/** - * @author Clément Fournier - */ -/* default */ class MultiValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper> - implements MultiValuePropertyDescriptor { - - MultiValuePropertyDescriptorWrapper(MultiValuePropertyDescriptor propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public Class type() { - return ((MultiValuePropertyDescriptor) propertyDescriptor).type(); - } - - - @Override - public char multiValueDelimiter() { - return ((MultiValuePropertyDescriptor) propertyDescriptor).multiValueDelimiter(); - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java deleted file mode 100644 index b0461bf568..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorFactory.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.List; - -import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.util.StringUtil; - - -/** - * @deprecated - */ -public class PropertyDescriptorFactory { - - private PropertyDescriptorFactory() { } - - - /** - * Returns the String type of the PropertyDescriptor for use in XML - * serialization. If the value is null the type cannot be - * serialized. - * - * @deprecated - */ - public static String getPropertyDescriptorType(PropertyDescriptor propertyDescriptor) { - Class type = propertyDescriptor.type(); - - String typeName = null; - // TODO - yes we can, investigate - if (propertyDescriptor instanceof EnumeratedProperty || propertyDescriptor instanceof MethodProperty - || propertyDescriptor instanceof TypeProperty) { - // Cannot serialize these kinds of PropertyDescriptors - } else if ("java.lang".equals(type.getPackage().getName())) { - typeName = type.getSimpleName(); - } - if (typeName == null) { - throw new IllegalArgumentException("Cannot encode type for PropertyDescriptor class: " + type.getName()); - } - if (propertyDescriptor.isMultiValue()) { - typeName = "List<" + typeName + ">"; // TODO:cf - } - - return typeName; - } - - - /** - * @param name - * @param description - * @param type - * @param delimiter - * @param min - * @param max - * @param value - * - * @return - * - * @deprecated - */ - public static PropertyDescriptor createPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { - return new PropertyDescriptorWrapper<>( - createRawPropertyDescriptor(name, description, type, delimiter, min, max, value)); - } - - - private static PropertyDescriptor createRawPropertyDescriptor(String name, String description, String type, - String delimiter, String min, String max, String value) { - if ("Boolean".equals(type)) { - return new BooleanProperty(name, description, value, 0.0f); - } else if ("List".equals(type)) { - BooleanMultiProperty property = new BooleanMultiProperty(name, description, (List) null, 0.0f); - return new BooleanMultiProperty(name, description, property.valueFrom(value), 0.0f); - } else if ("Character".equals(type)) { - return new CharacterProperty(name, description, CharacterProperty.charFrom(value), 0.0f); - } else if ("List".equals(type)) { - checkDelimiter(name, type, delimiter); - char delim = delimiter.charAt(0); - CharacterMultiProperty property = new CharacterMultiProperty(name, description, (List) null, 0.0f, delim); - return new CharacterMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); - } else if ("Double".equals(type)) { - checkMinMax(name, type, min, max); - return new DoubleProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - DoubleMultiProperty property = new DoubleMultiProperty(name, description, 0d, 0d, (List) null, 0.0f); - return new DoubleMultiProperty(name, description, DoubleProperty.doubleFrom(min), - DoubleProperty.doubleFrom(max), property.valueFrom(value), 0.0f); - } else if ("Float".equals(type)) { - checkMinMax(name, type, min, max); - return new FloatProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - FloatMultiProperty property = new FloatMultiProperty(name, description, 0f, 0f, (List) null, 0.0f); - return new FloatMultiProperty(name, description, Float.valueOf(min), Float.valueOf(max), - property.valueFrom(value), 0.0f); - } else if ("Integer".equals(type)) { - checkMinMax(name, type, min, max); - return new IntegerProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), ValueParser.INTEGER_PARSER.valueOf(max), - ValueParser.INTEGER_PARSER.valueOf(value), 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - IntegerMultiProperty property = new IntegerMultiProperty(name, description, 0, 0, (List) null, - 0.0f); - return new IntegerMultiProperty(name, description, ValueParser.INTEGER_PARSER.valueOf(min), - ValueParser.INTEGER_PARSER.valueOf(max), property.valueFrom(value), 0.0f); - } else if ("Long".equals(type)) { - checkMinMax(name, type, min, max); - return new LongProperty(name, description, min, max, value, 0.0f); - } else if ("List".equals(type)) { - checkMinMax(name, type, min, max); - LongMultiProperty property = new LongMultiProperty(name, description, 0L, 0L, (List) null, 0.0f); - return new LongMultiProperty(name, description, Long.valueOf(min), Long.valueOf(max), - property.valueFrom(value), 0.0f); - - // TODO - include legal package names for next four types - } else if ("Type".equals(type)) { - return new TypeProperty(name, description, value, (String[]) null, 0.0f); - } else if ("List".equals(type)) { - return new TypeMultiProperty(name, description, value, (String[]) null, 0.0f); - } else if ("Method".equals(type)) { - return new MethodProperty(name, description, value, (String[]) null, 0.0f); - } else if ("List".equals(type)) { - return new MethodMultiProperty(name, description, value, (String[]) null, 0.0f); - - } else if ("String".equals(type)) { - return new StringProperty(name, description, value, 0.0f); - } else if ("List".equals(type)) { - checkDelimiter(name, type, delimiter); - char delim = delimiter.charAt(0); - StringMultiProperty property = new StringMultiProperty(name, description, (String[]) null, 0.0f, delim); - return new StringMultiProperty(name, description, property.valueFrom(value), 0.0f, delim); - } else { - throw new IllegalArgumentException("Cannot define property type '" + type + "'."); - } - } - - - private static void checkDelimiter(String name, String type, String delimiter) { - if (delimiter == null || delimiter.length() == 0) { - throw new IllegalArgumentException( - "Delimiter must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - } - - - private static void checkMinMax(String name, String type, String min, String max) { - if (StringUtil.isEmpty(min)) { - throw new IllegalArgumentException( - "Min must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - if (StringUtil.isEmpty(max)) { - throw new IllegalArgumentException( - "Max must be provided to create PropertyDescriptor for " + name + " of type " + type + "."); - } - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java deleted file mode 100644 index fe76361d8c..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorWrapper.java +++ /dev/null @@ -1,162 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import java.util.Map; - -import net.sourceforge.pmd.PropertyDescriptor; -import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.Rule; - -/** - * This class serves as a wrapper class for a PropertyDescriptor instance. It - * exists to allowing the {@link PropertyDescriptorFactory} to readily flag - * properties it has created, versus those created by Rule classes. This is used - * in the encoding of a Rule to XML format to distinguish Rule defined - * PropertyDescriptors and those which were originally defined in XML. - * - * @param The type of the underlying PropertyDescriptor. - */ -public class PropertyDescriptorWrapper implements PropertyDescriptor { - - protected final PropertyDescriptor propertyDescriptor; - - - /* default */ PropertyDescriptorWrapper(PropertyDescriptor propertyDescriptor) { - if (propertyDescriptor == null) { - throw new IllegalArgumentException("PropertyDescriptor cannot be null."); - } - this.propertyDescriptor = propertyDescriptor; - } - - - @Override - public String asDelimitedString(T value) { - return propertyDescriptor.asDelimitedString(value); - } - - - @Override - public int compareTo(PropertyDescriptor o) { - return propertyDescriptor.compareTo(o); - } - - - @Override - public T defaultValue() { - return propertyDescriptor.defaultValue(); - } - - - @Override - public String description() { - return propertyDescriptor.description(); - } - - - @Override - public String errorFor(T value) { - return propertyDescriptor.errorFor(value); - } - - - @Override - public boolean isMultiValue() { - return propertyDescriptor.isMultiValue(); - } - - - @Override - public String name() { - return propertyDescriptor.name(); - } - - - @Override - public int preferredRowCount() { - return propertyDescriptor.preferredRowCount(); - } - - - @Override - public String propertyErrorFor(Rule rule) { - return propertyDescriptor.propertyErrorFor(rule); - } - - - @Override - public Class type() { - return propertyDescriptor.type(); - } - - - @Override - public float uiOrder() { - return propertyDescriptor.uiOrder(); - } - - - @Override - public T valueFrom(String propertyString) throws IllegalArgumentException { - return propertyDescriptor.valueFrom(propertyString); - } - - - @Override - public Map attributeValuesById() { - return propertyDescriptor.attributeValuesById(); - } - - - @Override - public boolean isDefinedExternally() { - return false; - } - - - @Override - public boolean equals(Object obj) { - if (obj instanceof PropertyDescriptorWrapper) { - return this.propertyDescriptor.equals(((PropertyDescriptorWrapper) obj).getPropertyDescriptor()); - } - return this.propertyDescriptor.equals(obj); - } - - - /** - * Returns the underlying property descriptor. - * - * @return The underlying property descriptor - */ - public PropertyDescriptor getPropertyDescriptor() { - return propertyDescriptor; - } - - - @Override - public int hashCode() { - return this.getPropertyDescriptor().hashCode(); - } - - - @Override - public String toString() { - return "wrapped:" + propertyDescriptor.toString(); - } - - - /** - * Gets the wrapper of this property descriptor. - * - * @param desc The descriptor - * @param The type of the descriptor - * - * @return The wrapper of this descriptor - */ - public static PropertyDescriptorWrapper getWrapper(PropertyDescriptor desc) { - return ((AbstractProperty) desc).getWrapper(); - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java deleted file mode 100644 index ddb5824942..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValueNumericPropertyDescriptorWrapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import net.sourceforge.pmd.NumericPropertyDescriptor; -import net.sourceforge.pmd.SingleValuePropertyDescriptor; - -/** - * @author Clément Fournier - */ -/* default */ class SingleValueNumericPropertyDescriptorWrapper - extends SingleValuePropertyDescriptorWrapper implements NumericPropertyDescriptor { - - & SingleValuePropertyDescriptor> SingleValueNumericPropertyDescriptorWrapper(D propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public Number upperLimit() { - return ((NumericPropertyDescriptor) propertyDescriptor).upperLimit(); - } - - - @Override - public Number lowerLimit() { - return ((NumericPropertyDescriptor) propertyDescriptor).lowerLimit(); - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java deleted file mode 100644 index e870292b91..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorWrapper.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule.properties; - -import net.sourceforge.pmd.SingleValuePropertyDescriptor; - -/** - * @author Clément Fournier - */ -/* default */ class SingleValuePropertyDescriptorWrapper extends PropertyDescriptorWrapper - implements SingleValuePropertyDescriptor { - - SingleValuePropertyDescriptorWrapper(SingleValuePropertyDescriptor propertyDescriptor) { - super(propertyDescriptor); - } - - - @Override - public Class type() { - return ((SingleValuePropertyDescriptor) propertyDescriptor).type(); - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 507ece2516..b8ecb7f5f1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -17,7 +17,6 @@ import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.lang.rule.properties.StringProperty; import net.sourceforge.pmd.lang.xpath.Initializer; @@ -85,10 +84,6 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { for (Map.Entry, Object> entry : super.properties.entrySet()) { if (name.equals(entry.getKey().name())) { PropertyDescriptor propertyDescriptor = entry.getKey(); - if (propertyDescriptor instanceof PropertyDescriptorWrapper) { - propertyDescriptor = ((PropertyDescriptorWrapper) propertyDescriptor) - .getPropertyDescriptor(); - } Object value = entry.getValue(); ValueRepresentation valueRepresentation; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java index 2b624b3cda..80018b666e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java @@ -4,16 +4,11 @@ package net.sourceforge.pmd.properties; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - -import java.util.List; import org.junit.Test; import net.sourceforge.pmd.NumericPropertyDescriptor; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; /** * @author Clément Fournier @@ -34,25 +29,6 @@ public abstract class AbstractNumericPropertyDescriptorTester extends Abstrac } - @Test - @SuppressWarnings("unchecked") - public void testWrapper() { - NumericPropertyDescriptor prop = (NumericPropertyDescriptor) createProperty(); - NumericPropertyDescriptor> multi = (NumericPropertyDescriptor>) createMultiProperty(); - NumericPropertyDescriptor propW = null; - NumericPropertyDescriptor> multiW = null; - try { - propW = (NumericPropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); - multiW = (NumericPropertyDescriptor>) PropertyDescriptorWrapper.getWrapper(multi); - } catch (ClassCastException ioe) { - fail(); - } - - assertEquals(prop.lowerLimit(), propW.lowerLimit()); - assertEquals(prop.upperLimit(), propW.upperLimit()); - assertEquals(multi.lowerLimit(), multiW.lowerLimit()); - assertEquals(multi.upperLimit(), multiW.upperLimit()); - } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index e58b890a3b..de20923523 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -18,13 +18,10 @@ import java.util.Map; import org.junit.Test; -import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.SingleValuePropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; /** * Base functionality for all concrete subclasses that evaluate type-specific @@ -275,44 +272,7 @@ public abstract class AbstractPropertyDescriptorTester { assertTrue(multiAtts.containsKey(PropertyDescriptorField.DEFAULT_VALUE)); } - @Test - @SuppressWarnings("unchecked") - public void testWrapper() { - PropertyDescriptor prop = createProperty(); - PropertyDescriptor> multi = createMultiProperty(); - PropertyDescriptor propW = null; - PropertyDescriptor> multiW = null; - try { - propW = (SingleValuePropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); - multiW = (MultiValuePropertyDescriptor) PropertyDescriptorWrapper.getWrapper(multi); - } catch (ClassCastException ioe) { - fail(); - } - - assertEquals(prop.type(), propW.type()); - assertEquals(prop.defaultValue(), propW.defaultValue()); - assertEquals(prop.description(), propW.description()); - assertEquals(prop.isMultiValue(), propW.isMultiValue()); - assertEquals(prop.name(), propW.name()); - assertEquals(prop.preferredRowCount(), propW.preferredRowCount()); - assertEquals(prop.uiOrder(), propW.uiOrder(), 0); - assertEquals(prop.attributeValuesById(), propW.attributeValuesById()); - assertEquals(prop.hashCode(), propW.hashCode()); - - - - assertEquals(multi.type(), multiW.type()); - assertEquals(multi.defaultValue(), multiW.defaultValue()); - assertEquals(multi.description(), multiW.description()); - assertEquals(multi.isMultiValue(), multiW.isMultiValue()); - assertEquals(multi.name(), multiW.name()); - assertEquals(multi.preferredRowCount(), multiW.preferredRowCount()); - assertEquals(multi.uiOrder(), multiW.uiOrder(), 0); - assertEquals(multi.attributeValuesById(), multiW.attributeValuesById()); - assertEquals(multi.hashCode(), multiW.hashCode()); - - } @Test diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index 26169e9209..89424bc6c8 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -21,7 +21,6 @@ import net.sourceforge.pmd.EnumeratedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorWrapper; import net.sourceforge.pmd.properties.SimpleEnumeratedPropertyTest.Foo; /** @@ -53,25 +52,7 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest } - @Test - @SuppressWarnings("unchecked") - public void testWrapper() { - EnumeratedPropertyDescriptor prop = (EnumeratedPropertyDescriptor) createProperty(); - EnumeratedPropertyDescriptor> multi = (EnumeratedPropertyDescriptor>) createMultiProperty(); - EnumeratedPropertyDescriptor propW = null; - EnumeratedPropertyDescriptor> multiW = null; - try { - propW = (EnumeratedPropertyDescriptor) PropertyDescriptorWrapper.getWrapper(prop); - multiW = (EnumeratedPropertyDescriptor>) PropertyDescriptorWrapper.getWrapper(multi); - } catch (ClassCastException ioe) { - fail(); - } - - assertEquals(prop.mappings(), propW.mappings()); - assertEquals(multi.mappings(), multiW.mappings()); - - } @Override From 282cf5bd66e1de09aef307c9bd1b9fe07d85efe1 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 19:03:10 +0200 Subject: [PATCH 44/53] Added PackagedPropertyDescriptor interface --- .../AbstractPropertyDescriptorFactory.java | 6 +++++ .../pmd/NumericPropertyDescriptor.java | 2 +- .../pmd/PackagedPropertyDescriptor.java | 23 +++++++++++++++++++ .../pmd/PropertyDescriptorField.java | 19 +++++++-------- .../AbstractMultiPackagedProperty.java | 10 ++++---- .../properties/AbstractPackagedProperty.java | 10 ++++---- .../properties/PropertyDescriptorUtil.java | 4 ++-- ...stractNumericPropertyDescriptorTester.java | 2 -- 8 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index 9aae00a602..ae8c6d836c 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -184,6 +184,12 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe } + /** + * Returns a map of mappings of property descriptor fields + * @param otherKeys + * @param otherValues + * @return + */ public static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, Boolean[] otherValues) { Map largerMap = new HashMap<>( diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index 15146e0242..cb4cd948a7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -5,7 +5,7 @@ package net.sourceforge.pmd; /** - * Defines a descriptor type whose instance values are required lie within + * Defines a descriptor type whose instance values are required to lie within * specified upper and lower limits. * * @param type of the property value diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java new file mode 100644 index 0000000000..d13ce719c9 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java @@ -0,0 +1,23 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd; + +/** + * 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}. + * + * @param type of the property value + * + * @author Clément Fournier + */ +public interface PackagedPropertyDescriptor extends PropertyDescriptor { + + /** + * Returns the legal package names. + * + * @return The legal package names + */ + String[] legalPackageNames(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java index 55f97a21a8..c849666b72 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorField.java @@ -7,18 +7,16 @@ package net.sourceforge.pmd; import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; /** - * Field names for parsing the properties out of the ruleset xml files. + * Field names for parsing the properties out of the ruleset xml files. These are intended to be used as the keys to + * a map of fields to values. Most property descriptors can be built directly from such a map using their factory. * * @author Brian Remedios * @see RuleSetFactory + * @see PropertyDescriptorUtil */ public enum PropertyDescriptorField { - /** - * The type of the property. - * - * @see PropertyDescriptorUtil - */ + /** The type of the property. */ TYPE("type"), /** The name of the property. */ NAME("name"), @@ -28,11 +26,14 @@ public enum PropertyDescriptorField { DEFAULT_VALUE("value"), /** For multi-valued properties, this defines the delimiter of the single values. */ DELIMITER("delimiter"), - /** The minium allowed value. */ + /** The minimum allowed value for numeric properties. */ MIN("min"), - /** The maximum allowed value. */ + /** The maximum allowed value for numeric properties. */ MAX("max"), - /** To limit the range of valid values, {@literal e.g.} to Enums. */ + /** + * To limit the range of valid values, package names. + * @see PackagedPro + */ LEGAL_PACKAGES("legalPackages"), /** Labels for enumerated properties. */ LABELS("labels"), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index 5b73987465..0ea1ab7060 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Set; import net.sourceforge.pmd.AbstractPropertyDescriptorFactory; +import net.sourceforge.pmd.PackagedPropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; /** @@ -23,7 +24,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -/* default */ abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty { +/* default */ abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty + implements PackagedPropertyDescriptor>{ /** Delimiter between values. */ protected static final char DELIMITER = '|'; @@ -164,11 +166,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; protected abstract String itemTypeName(); - /** - * Returns the legal package names. - * - * @return The legal package names - */ + @Override public String[] legalPackageNames() { return Arrays.copyOf(legalPackageNames, legalPackageNames.length); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index 0b657c7fe4..250122e8b0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -11,6 +11,7 @@ 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; @@ -23,7 +24,8 @@ import net.sourceforge.pmd.util.StringUtil; * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ -/* default */ abstract class AbstractPackagedProperty extends AbstractSingleValueProperty { +/* default */ abstract class AbstractPackagedProperty extends AbstractSingleValueProperty + implements PackagedPropertyDescriptor { /** Required keys in the map. */ protected static final Map PACKAGED_FIELD_TYPES_BY_KEY @@ -153,11 +155,7 @@ import net.sourceforge.pmd.util.StringUtil; protected abstract String itemTypeName(); - /** - * Returns the legal package names. - * - * @return The legal package names - */ + @Override public String[] legalPackageNames() { return Arrays.copyOf(legalPackageNames, legalPackageNames.length); // defensive copy } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index 5ac30e810e..fa3e9c8ae4 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -38,8 +38,8 @@ public class PropertyDescriptorUtil { temp.put("Double", DoubleProperty.FACTORY); temp.put("List", DoubleMultiProperty.FACTORY); - temp.put("Enum", EnumeratedProperty.FACTORY); - temp.put("List", EnumeratedMultiProperty.FACTORY); + // temp.put("Enum", EnumeratedProperty.FACTORY); + // temp.put("List", EnumeratedMultiProperty.FACTORY); temp.put("Class", TypeProperty.FACTORY); temp.put("List", TypeMultiProperty.FACTORY); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java index 80018b666e..461ca25728 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java @@ -29,6 +29,4 @@ public abstract class AbstractNumericPropertyDescriptorTester extends Abstrac } - - } From 4adfebffdf24f9cc2665c5cffc705b04b503f688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Thu, 13 Jul 2017 15:42:30 -0300 Subject: [PATCH 45/53] Update changelog, refs #501 --- src/site/markdown/overview/changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index a8232684de..c8280741ed 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -34,7 +34,7 @@ CPD will therefore have less false positives and false negatives. As part of Google Summer of Code 2017, [Bendegúz Nagy](https://github.com/WinterGrascph)'s work on type resolution for Java continues. For this release he has extended support for method calls. -Method shadowing and overloading are supported, as is varargs management. However, the selection of the target method upon the presence +Method shadowing and overloading are supported, as are varargs. However, the selection of the target method upon the presence of generics and type inference is still work in progress. Expect it in forecoming releases. #### Metrics Framework @@ -83,4 +83,5 @@ Based on those metrics, rules like "GodClass" detection can be implemented more * [#486](https://github.com/pmd/pmd/pull/486): \[java] Add basic method typeresolution - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#492](https://github.com/pmd/pmd/pull/492): \[java] Typeresolution for overloaded methods - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#495](https://github.com/pmd/pmd/pull/495): \[core] Custom rule reinitialization code - [Clément Fournier](https://github.com/oowekyala) +* [#501](https://github.com/pmd/pmd/pull/501): \[java] Add support for most specific vararg method type resolution - [Bendegúz Nagy](https://github.com/WinterGrascph) From 879a7d375cb88d997b32fff84b810e97b216bbb1 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 13 Jul 2017 21:43:18 +0200 Subject: [PATCH 46/53] Modularized numeric and packaged properties --- .../AbstractPropertyDescriptorFactory.java | 79 +++--- .../pmd/NumericPropertyDescriptor.java | 10 + .../pmd/PackagedPropertyDescriptor.java | 15 ++ .../AbstractMultiNumericProperty.java | 46 +--- .../AbstractMultiPackagedProperty.java | 138 ++-------- .../AbstractMultiValueProperty.java | 1 - .../properties/AbstractNumericProperty.java | 79 +----- .../properties/AbstractPackagedProperty.java | 137 ++-------- .../rule/properties/BooleanMultiProperty.java | 16 +- .../lang/rule/properties/BooleanProperty.java | 10 +- .../properties/CharacterMultiProperty.java | 4 +- .../rule/properties/CharacterProperty.java | 27 +- .../rule/properties/DoubleMultiProperty.java | 16 +- .../lang/rule/properties/DoubleProperty.java | 37 +-- .../properties/EnumeratedMultiProperty.java | 29 ++- .../rule/properties/EnumeratedProperty.java | 20 +- .../lang/rule/properties/FileProperty.java | 2 + .../rule/properties/FloatMultiProperty.java | 17 +- .../lang/rule/properties/FloatProperty.java | 13 +- .../rule/properties/IntegerMultiProperty.java | 19 +- .../lang/rule/properties/IntegerProperty.java | 3 +- .../rule/properties/LongMultiProperty.java | 17 +- .../lang/rule/properties/LongProperty.java | 12 +- .../rule/properties/MethodMultiProperty.java | 44 ++-- .../lang/rule/properties/MethodProperty.java | 241 +++--------------- .../MultiValuePropertyDescriptorFactory.java | 2 +- .../properties/PropertyDescriptorUtil.java | 25 +- .../SingleValuePropertyDescriptorFactory.java | 6 +- .../rule/properties/StringMultiProperty.java | 5 +- .../lang/rule/properties/StringProperty.java | 1 + .../rule/properties/TypeMultiProperty.java | 51 ++-- .../lang/rule/properties/TypeProperty.java | 66 +---- .../pmd/lang/rule/properties/ValueParser.java | 184 ++++++++++++- .../modules/MethodPropertyModule.java | 110 ++++++++ .../modules/NumericPropertyModule.java | 93 +++++++ .../modules/PackagedPropertyModule.java | 155 +++++++++++ .../modules/TypePropertyModule.java | 30 +++ .../AbstractPropertyDescriptorTester.java | 4 +- .../pmd/properties/BooleanPropertyTest.java | 7 + .../pmd/properties/CharacterPropertyTest.java | 12 +- .../pmd/properties/DoublePropertyTest.java | 6 + .../pmd/properties/FloatPropertyTest.java | 72 +++--- .../pmd/properties/MethodPropertyTest.java | 19 +- .../pmd/properties/PropertyAccessorTest.java | 5 + .../SimpleEnumeratedPropertyTest.java | 21 +- .../pmd/properties/StringPropertyTest.java | 18 +- .../pmd/properties/TypePropertyTest.java | 12 +- 47 files changed, 1012 insertions(+), 924 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/NumericPropertyModule.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/TypePropertyModule.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index ae8c6d836c..f8153253ea 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -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 implements PropertyDe } + @Override + public final PropertyDescriptor createWith(Map valuesById) { + return createWith(valuesById, false); + } + + /** - * Parses a string into a list of values of type {@literal }. + * 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 } - * @param 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 List parsePrimitives(String toParse, char delimiter, ValueParser extractor) { - String[] values = StringUtil.substringsOf(toParse, delimiter); - List result = new ArrayList<>(); - for (String s : values) { - result.add(extractor.valueOf(s)); - } - return result; + protected abstract PropertyDescriptor createWith(Map 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 createExternalWith(Map valuesById) { + return createWith(valuesById, true); } @@ -185,9 +195,11 @@ public abstract class AbstractPropertyDescriptorFactory 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 expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, @@ -202,37 +214,4 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe } - @Override - public final PropertyDescriptor createWith(Map 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 createExternalWith(Map 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 createWith(Map valuesById, boolean isExternallyDefined); - - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index cb4cd948a7..66e1f57fe1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -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 extends PropertyDescriptor { + Map 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. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java index d13ce719c9..c3baaaea6c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PackagedPropertyDescriptor.java @@ -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 extends PropertyDescriptor { + /** Required additional fields. */ + Map 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. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java index 7945bdc1f0..b6365ab62b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiNumericProperty.java @@ -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 extends AbstractMultiValueProperty implements NumericPropertyDescriptor> { - private final T lowerLimit; - private final T upperLimit; + private final NumericPropertyModule 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 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 attributes) { super.addAttributesTo(attributes); - attributes.put(MIN, lowerLimit.toString()); - attributes.put(MAX, upperLimit.toString()); + module.addAttributesTo(attributes); } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java index 0ea1ab7060..a313c52db3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiPackagedProperty.java @@ -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 extends AbstractMultiValueProperty - implements PackagedPropertyDescriptor>{ + implements PackagedPropertyDescriptor> { - /** Delimiter between values. */ - protected static final char DELIMITER = '|'; - /** Required keys in the map. */ - protected static final Map 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 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 theDefault, - String[] theLegalPackageNames, float theUIOrder, - boolean isDefinedExternally) { - super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); - - checkValidPackages(theDefault, theLegalPackageNames); - - legalPackageNames = theLegalPackageNames; + float theUIOrder, boolean isDefinedExternally, + PackagedPropertyModule 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 items, String[] legalNamePrefixes) { - - Set nameSet = new HashSet<>(); - - for (T item : items) { - nameSet.add(packageNameOf(item)); - } - - Set 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 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 params) { - // TODO - return null; + protected String[] packageNamesIn(Map params) { + return module.packageNamesIn(params); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java index c5a646f176..8332e6355e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java @@ -27,7 +27,6 @@ import net.sourceforge.pmd.util.StringUtil; implements MultiValuePropertyDescriptor { - /** The default value. */ private final List defaultValue; private final char multiValueDelimiter; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java index 3b115a0116..128cb81f13 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractNumericProperty.java @@ -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 extends AbstractSingleValueProperty implements NumericPropertyDescriptor { - public static final Map NUMBER_FIELD_TYPES_BY_KEY - = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, - new Boolean[] {true, true}); - private T lowerLimit; - private T upperLimit; + private final NumericPropertyModule 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 attributes) { super.addAttributesTo(attributes); - attributes.put(MIN, lowerLimit.toString()); - attributes.put(MAX, upperLimit.toString()); + module.addAttributesTo(attributes); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java index 250122e8b0..f8f5f344f6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractPackagedProperty.java @@ -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 extends AbstractSingleValueProperty implements PackagedPropertyDescriptor { - /** Required keys in the map. */ - protected static final Map 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 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 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 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 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 params) { + return module.packageNamesIn(params); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java index 997855fe29..792d417670 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java @@ -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 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 defaultValues, - float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally); - } - - @Override protected Boolean createFrom(String toParse) { return BOOLEAN_PARSER.valueOf(toParse); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java index ffbb43a3cd..3520e4918f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java @@ -49,6 +49,12 @@ public final class BooleanProperty extends AbstractSingleValueProperty } + /** 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 } - private BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); - } - @Override public Class type() { return Boolean.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 5b2ef644db..331cfce5f1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -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 defaultValues, float theUIOrder, char delimiter, boolean isDefinedExternally) { super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 6c2426acab..ad97abbc85 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -49,19 +49,7 @@ public final class CharacterProperty extends AbstractSingleValueProperty type() { return Character.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index f33868ce2c..b6dbb8e1c0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -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 valuesById, boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, DOUBLE_PARSER); + List 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 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 defaultValues, float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); - } - @Override public Class type() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index a2650ad8c8..900a83d618 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -57,6 +57,25 @@ public final class DoubleProperty extends AbstractNumericProperty { } + /** 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 { } - 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 type() { return Double.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java index b81b55aeed..f511e94f6e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java @@ -64,20 +64,6 @@ public final class EnumeratedMultiProperty 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 choices, - List defaultValues, Class valueType, float theUIOrder) { - this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false); - } - private EnumeratedMultiProperty(String theName, String theDescription, Map choices, List defaultValues, Class valueType, float theUIOrder, @@ -113,6 +99,21 @@ public final class EnumeratedMultiProperty 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 choices, + List defaultValues, Class valueType, float theUIOrder) { + this(theName, theDescription, choices, defaultValues, valueType, theUIOrder, false); + } + + @Override public Map mappings() { return choicesByLabel; // unmodifiable diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java index 70ef645d49..0bfc785d87 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedProperty.java @@ -71,6 +71,16 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty } + private EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, + E defaultValue, Class 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 extends AbstractSingleValueProperty } - private EnumeratedProperty(String theName, String theDescription, Map labelsToChoices, - E defaultValue, Class 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 type() { return valueType; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java index a1055fdfe5..58527a6a25 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FileProperty.java @@ -46,10 +46,12 @@ public final class FileProperty extends AbstractSingleValueProperty { } + /** Master constructor. */ private FileProperty(String theName, String theDescription, File theDefault, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally); } + @Override public Class type() { return File.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 6ba7af0bbc..25dc7badfa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -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 defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); + List 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 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 defaultValues, float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); - } - - @Override public Class type() { return Float.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 4240e88138..0861deb897 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -57,6 +57,13 @@ public final class FloatProperty extends AbstractNumericProperty { } + /** 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 { } - 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 type() { return Float.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index a6ce64db55..1a4e529362 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -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 defaultValues = parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); + List 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 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 defaultValues, float theUIOrder, boolean isDefinedExternally) { - - super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); - } - - @Override public Class type() { return Integer.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 694349e9d7..35322bcd48 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -53,8 +53,9 @@ public final class IntegerProperty extends AbstractNumericProperty { } + /** 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); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java index 8eaf0af35d..0611c52ab6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongMultiProperty.java @@ -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 public LongMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); + List 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 } + /** Master constructor. */ + private LongMultiProperty(String theName, String theDescription, Long min, Long max, + List 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 } - private LongMultiProperty(String theName, String theDescription, Long min, Long max, - List defaultValues, float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, min, max, defaultValues, theUIOrder, isDefinedExternally); - } - - @Override public Class type() { return Long.class; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index 2683d0c86a..138651c2b3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -58,6 +58,13 @@ public final class LongProperty extends AbstractNumericProperty { } + /** 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 { 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 type() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index 71e01afb9c..a0af6ed34c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -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 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 methodsFrom(String methodsStr) { - String[] values = StringUtil.substringsOf(methodsStr, DELIMITER); - - List 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 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); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java index 4f6022e6bb..f2488a1ff2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodProperty.java @@ -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 { - - 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 FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override @@ -37,22 +36,37 @@ public final class MethodProperty extends AbstractPackagedProperty { 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, 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 { * @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 { @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.: - * - *

"String#isEmpty()" "String#indexOf(int)" "String#substring(int,int)" - * - *

If a method isn't part of the specified class we will walk up any - * superclasses to Object to try and find it. - * - *

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. - * - *

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); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java index e256ae0ad7..03c85b24b7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MultiValuePropertyDescriptorFactory.java @@ -34,7 +34,7 @@ public abstract class MultiValuePropertyDescriptorFactory extends AbstractPro @Override protected abstract MultiValuePropertyDescriptor createWith(Map valuesById, - boolean isDefinedExternally); + boolean isDefinedExternally); @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index fa3e9c8ae4..43e1514332 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -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> DESCRIPTOR_FACTORIES_BY_TYPE; @@ -38,8 +41,8 @@ public class PropertyDescriptorUtil { temp.put("Double", DoubleProperty.FACTORY); temp.put("List", DoubleMultiProperty.FACTORY); - // temp.put("Enum", EnumeratedProperty.FACTORY); - // temp.put("List", EnumeratedMultiProperty.FACTORY); + // temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf implement that + // temp.put("List", EnumeratedMultiProperty.FACTORY); temp.put("Class", TypeProperty.FACTORY); temp.put("List", 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> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) { return entry.getKey(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java index c04b829170..92935f2df1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/SingleValuePropertyDescriptorFactory.java @@ -20,13 +20,13 @@ import net.sourceforge.pmd.SingleValuePropertyDescriptor; */ public abstract class SingleValuePropertyDescriptorFactory extends AbstractPropertyDescriptorFactory { - public SingleValuePropertyDescriptorFactory(Class theValueType) { + /* default */ SingleValuePropertyDescriptorFactory(Class theValueType) { super(theValueType); } - public SingleValuePropertyDescriptorFactory(Class theValueType, - Map additionalFieldTypesByKey) { + /* default */ SingleValuePropertyDescriptorFactory(Class theValueType, + Map additionalFieldTypesByKey) { super(theValueType, additionalFieldTypesByKey); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index e1eb927dff..e07406ce1e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -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 defaultValues, float theUIOrder, char delimiter, boolean isDefinedExternally) { super(theName, theDescription, defaultValues, theUIOrder, delimiter, isDefinedExternally); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 58f94d757c..83a9fe91ca 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -44,6 +44,7 @@ public final class StringProperty extends AbstractSingleValueProperty { } + /** Master constructor. */ private StringProperty(String theName, String theDescription, String defaultValue, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, defaultValue, theUIOrder, isDefinedExternally); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java index 7db4f1be85..8b913c42c4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/TypeMultiProperty.java @@ -4,13 +4,12 @@ package net.sourceforge.pmd.lang.rule.properties; -import java.util.ArrayList; 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.TypePropertyModule; /** * Defines a property that supports multiple class types, even for primitive @@ -55,6 +54,14 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty theTypeDefaults, + String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theTypeDefaults, theUIOrder, isDefinedExternally, + new TypePropertyModule(legalPackageNames, theTypeDefaults)); + } + + /** * Constructor for TypeProperty. * @@ -68,37 +75,15 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty theTypeDefaults, - String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, theTypeDefaults, legalPackageNames, theUIOrder, isDefinedExternally); - } - - /** - * Returns a list of Class objects parsed from the input string. - * - * @param classesStr String to parse - * - * @return A list of class objects - */ - private static List typesFrom(String classesStr) { - String[] values = StringUtil.substringsOf(classesStr, DELIMITER); - - List classes = new ArrayList<>(values.length); - for (int i = 0; i < values.length; i++) { - classes.add(TypeProperty.classFrom(values[i])); - } - return classes; - } - - - @Override - protected String packageNameOf(Class item) { - return ((Class) item).getName(); + private static List typesFrom(String valueString) { + return ValueParser.Companion.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, ValueParser.CLASS_PARSER); } @@ -108,12 +93,6 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty { char delimiter = delimiterIn(valuesById); return new TypeProperty(nameIn(valuesById), descriptionIn(valuesById), - classFrom(defaultValueIn(valuesById)), + ValueParser.CLASS_PARSER.valueOf(defaultValueIn(valuesById)), legalPackageNamesIn(valuesById, delimiter), 0f, isDefinedExternally); @@ -51,7 +51,15 @@ public final class TypeProperty extends AbstractPackagedProperty { */ public TypeProperty(String theName, String theDescription, String defaultTypeStr, String[] legalPackageNames, float theUIOrder) { - this(theName, theDescription, classFrom(defaultTypeStr), legalPackageNames, theUIOrder, false); + this(theName, theDescription, ValueParser.CLASS_PARSER.valueOf(defaultTypeStr), legalPackageNames, theUIOrder, false); + } + + + /** Master constructor. */ + private TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, + float theUIOrder, boolean isDefinedExternally) { + super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally, + new TypePropertyModule(legalPackageNames, Collections.singletonList(theDefault))); } @@ -63,7 +71,6 @@ public final class TypeProperty extends AbstractPackagedProperty { * @param theDefault Class * @param legalPackageNames String[] * @param theUIOrder float - * */ public TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, float theUIOrder) { @@ -71,59 +78,12 @@ public final class TypeProperty extends AbstractPackagedProperty { } - private TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, - float theUIOrder, boolean isDefinedExternally) { - super(theName, theDescription, theDefault, legalPackageNames, theUIOrder, isDefinedExternally); - } - - - static Class classFrom(String className) { - if (StringUtil.isEmpty(className)) { - return null; - } - - Class cls = ClassUtil.getTypeFor(className); - if (cls != null) { - return cls; - } - - try { - return Class.forName(className); - } catch (Exception ex) { - throw new IllegalArgumentException(className); - } - } - - - /** - * Deprecated constructor. - * - * @deprecated - */ - public TypeProperty(String theName, String theDescription, String defaultTypeStr, Map otherParams, - float theUIOrder) { - this(theName, theDescription, classFrom(defaultTypeStr), packageNamesIn(otherParams), theUIOrder); - } - - - @Override - protected String packageNameOf(Class item) { - return item.getName(); - } - - @Override public Class type() { return Class.class; } - @Override - protected String itemTypeName() { - return "type"; - } - - @Override protected String asString(Class value) { return value == null ? "" : value.getName(); @@ -132,6 +92,6 @@ public final class TypeProperty extends AbstractPackagedProperty { @Override public Class createFrom(String valueString) { - return classFrom(valueString); + return ValueParser.CLASS_PARSER.valueOf(valueString); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java index d66f9370e4..ce7d633a54 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ValueParser.java @@ -4,6 +4,19 @@ package net.sourceforge.pmd.lang.rule.properties; +import static net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule.ARRAY_FLAG; +import static net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule.CLASS_METHOD_DELIMITER; +import static net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule.METHOD_ARG_DELIMITER; +import static net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule.METHOD_GROUP_DELIMITERS; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import net.sourceforge.pmd.util.ClassUtil; +import net.sourceforge.pmd.util.StringUtil; + /** * Parses a value from a string. * @@ -12,7 +25,6 @@ package net.sourceforge.pmd.lang.rule.properties; // FUTURE @FunctionalInterface public interface ValueParser { - /** Extracts characters. */ ValueParser CHARACTER_PARSER = new ValueParser() { @Override @@ -24,7 +36,6 @@ public interface ValueParser { } }; - /** Extracts strings. That's a dummy used to return a list in StringMultiProperty. */ ValueParser STRING_PARSER = new ValueParser() { @Override @@ -33,7 +44,6 @@ public interface ValueParser { } }; - // FUTURE Integer::valueOf /** Extracts integers. */ ValueParser INTEGER_PARSER = new ValueParser() { @Override @@ -42,7 +52,7 @@ public interface ValueParser { } }; - // FUTURE Boolean::valueOf + // FUTURE Integer::valueOf /** Extracts booleans. */ ValueParser BOOLEAN_PARSER = new ValueParser() { @Override @@ -51,7 +61,7 @@ public interface ValueParser { } }; - // FUTURE Float::valueOf + // FUTURE Boolean::valueOf /** Extracts floats. */ ValueParser FLOAT_PARSER = new ValueParser() { @Override @@ -60,7 +70,7 @@ public interface ValueParser { } }; - // FUTURE Long::valueOf + // FUTURE Float::valueOf /** Extracts longs. */ ValueParser LONG_PARSER = new ValueParser() { @Override @@ -69,7 +79,7 @@ public interface ValueParser { } }; - // FUTURE Double::valueOf + // FUTURE Long::valueOf /** Extracts doubles. */ ValueParser DOUBLE_PARSER = new ValueParser() { @Override @@ -78,6 +88,137 @@ public interface ValueParser { } }; + /** Extract classes. */ + ValueParser CLASS_PARSER = new ValueParser() { + @Override + public Class valueOf(String value) throws IllegalArgumentException { + if (StringUtil.isEmpty(value)) { + return null; + } + + Class cls = ClassUtil.getTypeFor(value); + if (cls != null) { + return cls; + } + + try { + return Class.forName(value); + } catch (Exception ex) { + throw new IllegalArgumentException(value); + } + } + }; + + + /** Extracts methods. */ + ValueParser METHOD_PARSER = new ValueParser() { + @Override + public Method valueOf(String value) throws IllegalArgumentException { + return methodFrom(value, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER); + } + + + /** + * 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.: + * + *

"String#isEmpty()" "String#indexOf(int)" "String#substring(int,int)" + * + *

If a method isn't part of the specified class we will walk up any + * superclasses to Object to try and find it. + * + *

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. + * + *

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 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); + } + + + private 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; + } + } + + }; + /** * Extracts a primitive from a string. @@ -90,4 +231,33 @@ public interface ValueParser { */ U valueOf(String value) throws IllegalArgumentException; + + /** Companion object. */ + class Companion { + + private Companion() { + + } + + + /** + * Parses a string into a list of values of type {@literal }. + * + * @param toParse The string to parse + * @param delimiter The delimiter to use + * @param extractor The function mapping a string to an instance of {@code } + * @param The type of the values to parse + * + * @return A list of values + */ + public static List parsePrimitives(String toParse, char delimiter, ValueParser extractor) { + String[] values = StringUtil.substringsOf(toParse, delimiter); + List result = new ArrayList<>(); + for (String s : values) { + result.add(extractor.valueOf(s)); + } + return result; + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java new file mode 100644 index 0000000000..5df4007eb8 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java @@ -0,0 +1,110 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.modules; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.util.ClassUtil; + +/** + * @author Clément Fournier + */ +public class MethodPropertyModule extends PackagedPropertyModule { + + public static final char CLASS_METHOD_DELIMITER = '#'; + public static final char METHOD_ARG_DELIMITER = ','; + public static final char[] METHOD_GROUP_DELIMITERS = {'(', ')'}; + public static final String ARRAY_FLAG = "[]"; + private static final Map, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames(); + + + public MethodPropertyModule(String[] legalPackageNames, List defaults) { + super(legalPackageNames, defaults); + } + + + @Override + protected String packageNameOf(Method method) { + return method == null ? null : method.getDeclaringClass().getName() + '.' + method.getName(); + } + + + @Override + protected String itemTypeName() { + return "method"; + } + + + public static String asString(Method method) { + return method == null ? "" : asStringFor(method); + } + + + /** + * 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 + */ + private static String asStringFor(Method method) { // TODO:cf we could replace that with a QualifiedName's toString + StringBuilder sb = new StringBuilder(); // once it can parse Class and Method + asStringOn(method, sb); + return sb.toString(); + } + + + /** + * Serializes the method signature onto the specified buffer. + * + * @param method Method + * @param sb StringBuilder + */ + private 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); + } + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/NumericPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/NumericPropertyModule.java new file mode 100644 index 0000000000..e8555cd2ba --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/NumericPropertyModule.java @@ -0,0 +1,93 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.modules; + +import static net.sourceforge.pmd.PropertyDescriptorField.MAX; +import static net.sourceforge.pmd.PropertyDescriptorField.MIN; + +import java.util.Map; + +import net.sourceforge.pmd.PropertyDescriptorField; + +/** + * Common utilities for implementations of numeric property descriptors. + * + * @author Clément Fournier + */ +public class NumericPropertyModule { + + private final T lowerLimit; + private final T upperLimit; + + + public NumericPropertyModule(T lowerLimit, T upperLimit) { + this.lowerLimit = lowerLimit; + this.upperLimit = upperLimit; + + checkNumber(lowerLimit); + checkNumber(upperLimit); + + if (lowerLimit.doubleValue() > upperLimit.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); + } + } + + + public 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; + } + + + /** + * Returns a string representing the range defined by the two bounds. + * + * @param low Lower bound + * @param up Upper bound + * + * @return String + */ + private static String rangeString(Number low, Number up) { + return "(" + low + " -> " + up + ")"; + } + + + public T getLowerLimit() { + return lowerLimit; + } + + + public T getUpperLimit() { + return upperLimit; + } + + + public void addAttributesTo(Map attributes) { + attributes.put(MIN, lowerLimit.toString()); + attributes.put(MAX, upperLimit.toString()); + } + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java new file mode 100644 index 0000000000..5e36bc8202 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java @@ -0,0 +1,155 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.modules; + +import static net.sourceforge.pmd.PackagedPropertyDescriptor.PACKAGE_NAME_DELIMITER; +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 java.util.regex.Pattern; + +import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.util.StringUtil; + +/** + * @author Clément Fournier + */ +public abstract class PackagedPropertyModule { + + private static final Pattern PACKAGE_NAME_PATTERN = Pattern.compile("(\\w+)(\\.\\w+)*"); + + private final String[] legalPackageNames; + + + public PackagedPropertyModule(String[] legalPackageNames, List defaults) { + + checkValidPackages(defaults, legalPackageNames); + + this.legalPackageNames = legalPackageNames; + } + + + /** + * 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 items, String[] legalNamePrefixes) { + + if (legalNamePrefixes == null) { + return; + } + + Set nameSet = new HashSet<>(); + + for (T item : items) { + nameSet.add(packageNameOf(item)); + } + + Set 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); + + + public String valueErrorFor(T value) { + + 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; + } + + + /** + * Returns the name of the type of item. + * + * @return The name of the type of item + */ + protected abstract String itemTypeName(); + + + public String[] legalPackageNames() { + return Arrays.copyOf(legalPackageNames, legalPackageNames.length); + } + + + public void addAttributesTo(Map 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(); + } + + + public String[] packageNamesIn(Map params) { + String[] packageNames = StringUtil.substringsOf(params.get(LEGAL_PACKAGES), PACKAGE_NAME_DELIMITER); + + for (String name : packageNames) { + if (!PACKAGE_NAME_PATTERN.matcher(name).matches()) { + throw new IllegalArgumentException("One name is not a package: '" + name + "'"); + } + } + + return packageNames; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/TypePropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/TypePropertyModule.java new file mode 100644 index 0000000000..232a20635a --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/TypePropertyModule.java @@ -0,0 +1,30 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.modules; + +import java.util.List; + +/** + * @author Clément Fournier + */ +public class TypePropertyModule extends PackagedPropertyModule { + + public TypePropertyModule(String[] legalPackageNames, List defaults) { + super(legalPackageNames, defaults); + } + + + @Override + protected String packageNameOf(Class item) { + return item.getName(); + } + + + @Override + protected String itemTypeName() { + return "type"; + } + +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index de20923523..600f739169 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -251,12 +251,14 @@ public abstract class AbstractPropertyDescriptorTester { return res; } + @Test public void testIsMultiValue() { assertFalse(createProperty().isMultiValue()); assertTrue(createMultiProperty().isMultiValue()); } + @Test public void testAddAttributes() { Map atts = createProperty().attributeValuesById(); @@ -273,8 +275,6 @@ public abstract class AbstractPropertyDescriptorTester { } - - @Test public void testType() { assertNotNull(createMultiProperty().type()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java index 69652d3066..c8a65a4db7 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/BooleanPropertyTest.java @@ -27,39 +27,46 @@ public class BooleanPropertyTest extends AbstractPropertyDescriptorTester 0 ? Boolean.TRUE : Boolean.FALSE; } + @Override @Test public void testErrorForBadSingle() { // override, cannot create a 'bad' boolean per se } + @Override @Test public void testErrorForBadMulti() { // override, cannot create a 'bad' boolean per se } + @Override protected Boolean createBadValue() { return null; } + @Override protected PropertyDescriptor createProperty() { return new BooleanProperty("testBoolean", "Test boolean property", false, 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new BooleanMultiProperty("testBoolean", "Test boolean property", new Boolean[] {false, true, true}, 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { return new BooleanMultiProperty("", "Test boolean property", new Boolean[] {false, true, true}, 1.0f); } + @Override protected PropertyDescriptor createBadProperty() { return new BooleanProperty("testBoolean", "", false, 1.0f); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java index 57e36fe616..fa4c4bd34d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/CharacterPropertyTest.java @@ -24,6 +24,7 @@ public class CharacterPropertyTest extends AbstractPropertyDescriptorTester createProperty() { return new CharacterProperty("testCharacter", "Test character property", 'a', 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new CharacterMultiProperty("testCharacter", "Test character property", - new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER); + new Character[] {'a', 'b', 'c'}, 1.0f, DELIMITER); } + @Override protected PropertyDescriptor createBadProperty() { return new CharacterProperty("", "Test character property", 'a', 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { return new CharacterMultiProperty("testCharacter", "Test character property", - new Character[] { 'a', 'b', 'c' }, 1.0f, DELIMITER); + new Character[] {'a', 'b', 'c'}, 1.0f, DELIMITER); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java index 91de40b395..024954bbea 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/DoublePropertyTest.java @@ -24,6 +24,7 @@ public class DoublePropertyTest extends AbstractNumericPropertyDescriptorTester< private static final double MAX = 100.0; private static final double SHIFT = 5.0; + public DoublePropertyTest() { super("Double"); } @@ -34,28 +35,33 @@ public class DoublePropertyTest extends AbstractNumericPropertyDescriptorTester< return randomDouble(MIN, MAX); } + @Override protected Double createBadValue() { return randomBool() ? randomDouble(MIN - SHIFT, MIN - 0.01) : randomDouble(MAX + 0.01, MAX + SHIFT); } + @Override protected PropertyDescriptor createProperty() { return new DoubleProperty("testDouble", "Test double property", MIN, MAX, 9.0, 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, new Double[] {-1d, 0d, 1d, 2d}, 1.0f); } + @Override protected PropertyDescriptor createBadProperty() { return new DoubleProperty("testDouble", "Test double property", MAX, MIN, 9.0, 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { return new DoubleMultiProperty("testDouble", "Test double property", MIN, MAX, diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java index 137be50b4b..879c8fcb6a 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java @@ -24,10 +24,50 @@ public class FloatPropertyTest extends AbstractPropertyDescriptorTester { private static final float MAX = 11.0f; private static final float SHIFT = 3.0f; + public FloatPropertyTest() { super("Float"); } + + @Override + protected Float createValue() { + return randomFloat(MIN, MAX); + } + + + @Override + protected Float createBadValue() { + return randomBool() ? randomFloat(MIN - SHIFT, MIN) : randomFloat(MAX, MAX + SHIFT); + } + + + @Override + protected PropertyDescriptor createProperty() { + return new FloatProperty("testFloat", "Test float property", MIN, MAX, 9.0f, 1.0f); + } + + + @Override + protected PropertyDescriptor> createMultiProperty() { + return new FloatMultiProperty("testFloat", "Test float property", MIN, MAX, + new Float[] {-1f, 0f, 1f, 2f}, 1.0f); + } + + + @Override + protected PropertyDescriptor createBadProperty() { + return new FloatProperty("testFloat", "Test float property", 5f, 4f, 9.0f, 1.0f); + } + + + @Override + protected PropertyDescriptor> createBadMultiProperty() { + return new FloatMultiProperty("testFloat", "Test float property", 0f, 5f, + new Float[] {-1f, 0f, 1f, 2f}, 1.0f); + } + + public static FloatProperty randomProperty(int nameLength, int descLength, boolean multiValue) { float defalt = randomFloat(0, 1000f); @@ -35,36 +75,4 @@ public class FloatPropertyTest extends AbstractPropertyDescriptorTester { return new FloatProperty(randomString(nameLength), randomString(descLength), defalt - 1000f, defalt + 1000, defalt, 0f); } - - @Override - protected Float createValue() { - return randomFloat(MIN, MAX); - } - - @Override - protected Float createBadValue() { - return randomBool() ? randomFloat(MIN - SHIFT, MIN) : randomFloat(MAX, MAX + SHIFT); - } - - @Override - protected PropertyDescriptor createProperty() { - return new FloatProperty("testFloat", "Test float property", MIN, MAX, 9.0f, 1.0f); - } - - @Override - protected PropertyDescriptor> createMultiProperty() { - return new FloatMultiProperty("testFloat", "Test float property", MIN, MAX, - new Float[] {-1f, 0f, 1f, 2f}, 1.0f); - } - - @Override - protected PropertyDescriptor createBadProperty() { - return new FloatProperty("testFloat", "Test float property", 5f, 4f, 9.0f, 1.0f); - } - - @Override - protected PropertyDescriptor> createBadMultiProperty() { - return new FloatMultiProperty("testFloat", "Test float property", 0f, 5f, - new Float[] {-1f, 0f, 1f, 2f}, 1.0f); - } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java index 9b5e3652ba..d4cada806c 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java @@ -16,6 +16,8 @@ import org.junit.Test; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.lang.rule.properties.MethodMultiProperty; import net.sourceforge.pmd.lang.rule.properties.MethodProperty; +import net.sourceforge.pmd.lang.rule.properties.ValueParser; +import net.sourceforge.pmd.lang.rule.properties.modules.MethodPropertyModule; import net.sourceforge.pmd.util.ClassUtil; /** @@ -37,69 +39,76 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester "java.lang.String#substring(int,int)", "Integer#parseInt(String)", "java.util.HashMap#put(Object,Object)", "HashMap#containsKey(Object)", }; + public MethodPropertyTest() { super("Method"); } + @Test public void testAsStringOn() { Method method = null; for (int i = 0; i < METHOD_SIGNATURES.length; i++) { - method = MethodProperty.methodFrom(METHOD_SIGNATURES[i], MethodProperty.CLASS_METHOD_DELIMITER, - MethodProperty.METHOD_ARG_DELIMITER); + method = ValueParser.METHOD_PARSER.valueOf(METHOD_SIGNATURES[i]); assertNotNull("Unable to identify method: " + METHOD_SIGNATURES[i], method); } } + @Test public void testAsMethodOn() { Method[] methods = new Method[METHOD_SIGNATURES.length]; for (int i = 0; i < METHOD_SIGNATURES.length; i++) { - methods[i] = MethodProperty.methodFrom(METHOD_SIGNATURES[i], MethodProperty.CLASS_METHOD_DELIMITER, - MethodProperty.METHOD_ARG_DELIMITER); + methods[i] = ValueParser.METHOD_PARSER.valueOf(METHOD_SIGNATURES[i]); assertNotNull("Unable to identify method: " + METHOD_SIGNATURES[i], methods[i]); } String translatedMethod = null; for (int i = 0; i < methods.length; i++) { - translatedMethod = MethodProperty.asStringFor(methods[i]); + translatedMethod = MethodPropertyModule.asString(methods[i]); assertTrue("Translated method does not match", ClassUtil.withoutPackageName(METHOD_SIGNATURES[i]) .equals(ClassUtil.withoutPackageName(translatedMethod))); } } + @Override protected Method createValue() { return randomChoice(ALL_METHODS); } + @Override protected Method createBadValue() { return randomChoice(HashMap.class.getDeclaredMethods()); } + @Override protected PropertyDescriptor createProperty() { return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.lang", "org.apache"}, 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new MethodMultiProperty("methodProperty", "asdf", new Method[] {ALL_METHODS[2], ALL_METHODS[3]}, new String[] {"java.lang"}, 1.0f); } + @Override protected PropertyDescriptor createBadProperty() { return new MethodProperty("methodProperty", "asdf", ALL_METHODS[1], new String[] {"java.util"}, 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { return new MethodMultiProperty("methodProperty", "asdf", new Method[] {ALL_METHODS[2], ALL_METHODS[3]}, diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java index 338e37eaf4..624a27f926 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyAccessorTest.java @@ -25,11 +25,13 @@ public class PropertyAccessorTest { private Rule rule; + @Before public void setUpSingleRule() { rule = new NonRuleWithAllPropertyTypes(); } + @Test public void testIntegers() { rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_INT, NumericConstants.ZERO); @@ -40,6 +42,7 @@ public class PropertyAccessorTest { assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_INT), Arrays.asList(0, 1)); } + @Test public void testBooleans() { @@ -50,6 +53,7 @@ public class PropertyAccessorTest { assertEquals(rule.getProperty(NonRuleWithAllPropertyTypes.MULTI_BOOL), Arrays.asList(true, false)); } + @Ignore @Test public void testFloats() throws ReportException { @@ -73,6 +77,7 @@ public class PropertyAccessorTest { */ } + @Test public void testStrings() { rule.setProperty(NonRuleWithAllPropertyTypes.SINGLE_STR, "brian"); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java index 89424bc6c8..dcb3c2f5f3 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/SimpleEnumeratedPropertyTest.java @@ -52,7 +52,16 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest } + @Test + public void testMappings() { + EnumeratedPropertyDescriptor prop + = (EnumeratedPropertyDescriptor) createProperty(); + EnumeratedPropertyDescriptor> multi + = (EnumeratedPropertyDescriptor>) createMultiProperty(); + assertEquals(MAPPINGS, prop.mappings()); + assertEquals(MAPPINGS, multi.mappings()); + } @Override @@ -75,18 +84,6 @@ public class SimpleEnumeratedPropertyTest extends AbstractPropertyDescriptorTest } - @Test - public void testMappings() { - EnumeratedPropertyDescriptor prop - = (EnumeratedPropertyDescriptor) createProperty(); - EnumeratedPropertyDescriptor> multi - = (EnumeratedPropertyDescriptor>) createMultiProperty(); - - assertEquals(MAPPINGS, prop.mappings()); - assertEquals(MAPPINGS, multi.mappings()); - } - - @Test public void testDefaultIndexOutOfBounds() { try { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java index dc6c743317..4e62f80594 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java @@ -24,10 +24,18 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester private static final char DELIMITER = '|'; private static final char[] CHARSET = filter(ALL_CHARS.toCharArray(), DELIMITER); + public StringPropertyTest() { super("String"); } + + @Override + protected String createValue() { + return newString(); + } + + /** * Method newString. * @@ -44,6 +52,7 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester return new String(chars); } + /** * Method randomCharIn. * @@ -56,32 +65,31 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester } - @Override - protected String createValue() { - return newString(); - } - @Override protected String createBadValue() { return null; } + @Override protected PropertyDescriptor createProperty() { return new StringProperty("testString", "Test string property", "brian", 1.0f); } + @Override protected PropertyDescriptor> createMultiProperty() { return new StringMultiProperty("testString", "Test string property", new String[] {"hello", "world"}, 1.0f, DELIMITER); } + @Override protected PropertyDescriptor createBadProperty() { return new StringProperty("", "Test string property", "brian", 1.0f); } + @Override protected PropertyDescriptor> createBadMultiProperty() { return new StringMultiProperty("testString", "Test string property", diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java index 852011c584..873cb7ad71 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java @@ -42,12 +42,6 @@ public class TypePropertyTest extends AbstractPropertyDescriptorTester { } - @Override - protected Class createValue() { - return JAVA_LANG_CLASSES.get(randomInt(0, JAVA_LANG_CLASSES.size())); - } - - @Override protected Class createBadValue() { return JAVA_UTIL_CLASSES.get(randomInt(0, JAVA_UTIL_CLASSES.size())); @@ -61,6 +55,12 @@ public class TypePropertyTest extends AbstractPropertyDescriptorTester { } + @Override + protected Class createValue() { + return JAVA_LANG_CLASSES.get(randomInt(0, JAVA_LANG_CLASSES.size())); + } + + @Override protected PropertyDescriptor> createMultiProperty() { return new TypeMultiProperty("testType", "Test type property", JAVA_LANG_CLASSES, new String[] {"java.lang"}, From 278e857bf66feee2588d45e799bc87eb9cc17cf4 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Fri, 14 Jul 2017 02:15:50 +0200 Subject: [PATCH 47/53] Reworked factories --- .../AbstractPropertyDescriptorFactory.java | 144 +++++++- .../pmd/NumericPropertyDescriptor.java | 5 +- .../sourceforge/pmd/PropertyDescriptor.java | 17 + .../pmd/PropertyDescriptorFactory.java | 19 +- .../net/sourceforge/pmd/RuleSetFactory.java | 21 +- .../rule/properties/AbstractProperty.java | 2 + .../properties/CharacterMultiProperty.java | 6 + .../rule/properties/CharacterProperty.java | 7 + .../rule/properties/DoubleMultiProperty.java | 5 +- .../lang/rule/properties/DoubleProperty.java | 4 +- .../rule/properties/FloatMultiProperty.java | 2 +- .../lang/rule/properties/FloatProperty.java | 2 +- .../rule/properties/IntegerMultiProperty.java | 2 +- .../lang/rule/properties/IntegerProperty.java | 8 +- .../lang/rule/properties/LongProperty.java | 2 +- .../rule/properties/MethodMultiProperty.java | 13 +- .../properties/PropertyDescriptorUtil.java | 50 +++ .../rule/properties/StringMultiProperty.java | 6 + .../lang/rule/properties/StringProperty.java | 7 + .../modules/MethodPropertyModule.java | 2 +- .../modules/PackagedPropertyModule.java | 44 ++- .../net/sourceforge/pmd/util/StringUtil.java | 348 ++++++++++-------- ...stractNumericPropertyDescriptorTester.java | 27 ++ ...tractPackagedPropertyDescriptorTester.java | 38 ++ .../AbstractPropertyDescriptorTester.java | 10 +- .../pmd/properties/FloatPropertyTest.java | 2 +- .../pmd/properties/IntegerPropertyTest.java | 2 +- .../pmd/properties/LongPropertyTest.java | 11 +- .../pmd/properties/MethodPropertyTest.java | 6 +- .../pmd/properties/StringPropertyTest.java | 2 +- .../pmd/properties/TypePropertyTest.java | 2 +- 31 files changed, 573 insertions(+), 243 deletions(-) create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index f8153253ea..29bea13d47 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd; +import static net.sourceforge.pmd.PropertyDescriptor.CORE_FIELD_TYPES_BY_KEY; import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION; @@ -15,8 +16,9 @@ import static net.sourceforge.pmd.PropertyDescriptorField.NAME; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; -import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** @@ -28,30 +30,42 @@ import net.sourceforge.pmd.util.StringUtil; */ public abstract class AbstractPropertyDescriptorFactory implements PropertyDescriptorFactory { - protected static final Map CORE_FIELD_TYPES_BY_KEY - = CollectionUtil.mapFrom(new PropertyDescriptorField[] {NAME, DESCRIPTION, DEFAULT_VALUE, DELIMITER}, - new Boolean[] {true, true, true, false}); + + + + static { + System.err.println(CORE_FIELD_TYPES_BY_KEY); + } + private final Class valueType; - private final Map fieldTypesByKey; + /** + * Denote the identifiers of the expected fields paired with booleans + * denoting whether they are required (non-null) or not. + */ + private final Map expectedFields; public AbstractPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; - fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY); + expectedFields = CORE_FIELD_TYPES_BY_KEY; } public AbstractPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { valueType = theValueType; + if (additionalFieldTypesByKey == null) { + expectedFields = CORE_FIELD_TYPES_BY_KEY; + return; + } Map temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); temp.putAll(CORE_FIELD_TYPES_BY_KEY); temp.putAll(additionalFieldTypesByKey); - fieldTypesByKey = Collections.unmodifiableMap(temp); + expectedFields = Collections.unmodifiableMap(temp); } @@ -62,38 +76,70 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe @Override - public Map expectedFields() { - return fieldTypesByKey; + public Set expectableFields() { + return Collections.unmodifiableSet(expectedFields.keySet()); } + /** + * Retrieves the name of the descriptor from the map. + * + * @param valuesById Map of attributes + * + * @return The name, which is null if none is specified + */ protected String nameIn(Map valuesById) { return valuesById.get(NAME); } + /** + * Retrieves the description from the map. + * + * @param valuesById Map of attributes + * + * @return The description, which is null if none is specified + */ protected String descriptionIn(Map valuesById) { return valuesById.get(DESCRIPTION); } - protected String numericDefaultValueIn(Map valuesById) { - String number = defaultValueIn(valuesById); - return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0 reasonable if undefined? - } - - + /** + * Retrieves the default value from the map. + * + * @param valuesById Map of attributes + * + * @return The default value + * + * @throws RuntimeException if the default value is null, empty, or missing + */ protected String defaultValueIn(Map valuesById) { - return valuesById.get(DEFAULT_VALUE); + String deft = valuesById.get(DEFAULT_VALUE); + if (StringUtil.isEmpty(deft)) { + throw new RuntimeException("Default value was null, empty, or missing"); + } + return deft; } @Override public final PropertyDescriptor createWith(Map valuesById) { + // checkRequiredFields(valuesById); return createWith(valuesById, false); } + /** Checks whether all required fields are present in the map. */ + private void checkRequiredFields(Map valuesById) { + for (Entry entry : expectedFields.entrySet()) { + if (entry.getValue() && StringUtil.isEmpty(valuesById.get(entry.getKey()))) { + throw new RuntimeException("Missing required value for key: " + entry.getKey()); + } + } + } + + /** * Creates a new property descriptor specifying whether the descriptor is externally defined or not. This is * meant to be implemented by subclasses. @@ -106,6 +152,20 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe protected abstract PropertyDescriptor createWith(Map valuesById, boolean isExternallyDefined); + /** + * Checks if the value is considered as missing or not. Some properties support whitespace values, hence the + * check. By default this does not support it. The factory can override this method to change the predicate. + * + * @param value The value to check + * + * @return True if the value must be considered missing, false otherwise + */ + protected boolean isValueMissing(String value) { + // return StringUtil.isEmpty(value); + return false; + } + + /** * Creates a new property descriptor which was defined externally. * @@ -117,54 +177,98 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe */ /* default */ final PropertyDescriptor createExternalWith(Map valuesById) { + checkRequiredFields(valuesById); return createWith(valuesById, true); } + /** + * Gets the labels for enumerated properties, returns a string array of length 0 if none are specified. + * + * @param valuesById Map of attributes + * + * @return An array containing the labels + */ protected static String[] labelsIn(Map valuesById) { return StringUtil.substringsOf(valuesById.get(PropertyDescriptorField.LABELS), MultiValuePropertyDescriptor.DEFAULT_DELIMITER); } + // For enumerated properties protected static Object[] choicesIn(Map valuesById) { - return null; // TODO: find a way to extract an arbitrary object from a string + throw new UnsupportedOperationException(); // TODO: find a way to extract an arbitrary object from a string // Maybe reason enough to only allow enums... } + // For enumerated properties protected static int indexIn(Map valuesById) { - return 0; // TODO + throw new UnsupportedOperationException(); // TODO } + // For enumerated properties protected static Class classIn(Map valuesById) { - return Object.class; // TODO + throw new UnsupportedOperationException(); // TODO } + // For enumerated properties protected static int[] indicesIn(Map valuesById) { - return null; // TODO + throw new UnsupportedOperationException(); // TODO } + /** + * Finds the delimiter in the map, taking {@link MultiValuePropertyDescriptor#DEFAULT_DELIMITER} if none is + * mentioned. + * + * @param valuesById Map of attributes + * + * @return The delimiter or the default + */ protected static char delimiterIn(Map valuesById) { return delimiterIn(valuesById, MultiValuePropertyDescriptor.DEFAULT_DELIMITER); } + /** + * Finds the delimiter in the map, taking the specified default delimiter if none is specified. + * + * @param valuesById Map of attributes + * @param defaultDelimiter The default delimiter to take + * + * @return The delimiter or the default + * + * @throws RuntimeException If the delimiter is present but is more than 1 character + */ protected static char delimiterIn(Map valuesById, char defaultDelimiter) { String characterStr = ""; if (valuesById.containsKey(DELIMITER)) { characterStr = valuesById.get(DELIMITER).trim(); } + if (StringUtil.isEmpty(characterStr)) { return defaultDelimiter; } + + if (characterStr.length() != 1) { + throw new RuntimeException("Ambiguous delimiter character, must have length 1: \"" + characterStr + "\""); + } return characterStr.charAt(0); } + /** + * Retrieves the minimum and maximum values from the map. + * + * @param valuesById Map of attributes + * + * @return An array of 2 string, min at the left, max at the right + * + * @throws RuntimeException If one of them is missing + */ protected static String[] minMaxFrom(Map valuesById) { String min = minValueIn(valuesById); String max = maxValueIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index 66e1f57fe1..6ce13033a3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -9,6 +9,8 @@ import static net.sourceforge.pmd.PropertyDescriptorField.MIN; import java.util.Map; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; + /** * Defines a descriptor type whose instance values are required to lie within * specified upper and lower limits. @@ -20,8 +22,7 @@ import java.util.Map; public interface NumericPropertyDescriptor extends PropertyDescriptor { Map NUMBER_FIELD_TYPES_BY_KEY - = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {MIN, MAX}, - new Boolean[] {true, true}); + = PropertyDescriptorUtil.expectedFields().put(MIN, true).put(MAX, true).get(); /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 1fbf7a8694..2e990f25ac 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -4,8 +4,15 @@ package net.sourceforge.pmd; +import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; +import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; +import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION; +import static net.sourceforge.pmd.PropertyDescriptorField.NAME; + import java.util.Map; +import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil.ExpectedFieldsBuilder; + /** * Property value descriptor that defines the use & requirements for setting * property values for use within PMD and any associated GUIs. While concrete @@ -27,6 +34,16 @@ import java.util.Map; */ public interface PropertyDescriptor extends Comparable> { + /** Default expected fields. Unmodifiable. */ + Map CORE_FIELD_TYPES_BY_KEY + = (new ExpectedFieldsBuilder()) + .put(NAME, true) + .put(DESCRIPTION, true) + .put(DEFAULT_VALUE, true) + .put(DELIMITER, false) + .get(); + + /** * The name of the property without spaces as it serves as the key into the * property map. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java index 0990938b6e..2eaf84f8f7 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptorFactory.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd; import java.util.Map; +import java.util.Set; /** * A factory to create {@link PropertyDescriptor}s based on a map of values. @@ -12,6 +13,7 @@ import java.util.Map; * @param The type of values property descriptor returned by this factory. This can be a list. * * @author Brian Remedios + * @version Refactored July 2017 (6.0.0) */ public interface PropertyDescriptorFactory { @@ -19,26 +21,27 @@ public interface PropertyDescriptorFactory { * The type of the value of the {@link PropertyDescriptor} created by this * factory. * - * @return the type of the value. + * @return The type of the value. */ Class valueType(); /** - * Returns true if the wrapped property descriptor is multi-valued. + * Returns true if the built property descriptor is multi-valued. * - * @return true if the wrapped property descriptor is multi-valued. + * @return True if the built property descriptor is multi-valued. */ boolean isMultiValue(); /** - * Denote the identifiers of the expected fields paired with booleans - * denoting whether they are required (non-null) or not. + * Denote the identifiers of all fields that contribute to building + * this descriptor. Control of the required fields is performed + * inside the factory. * - * @return Map + * @return A set of field identifiers */ - Map expectedFields(); + Set expectableFields(); /** @@ -47,7 +50,7 @@ public interface PropertyDescriptorFactory { * * @param valuesById the map of values * - * @return a new and initialized {@link PropertyDescriptor} + * @return A new and initialized {@link PropertyDescriptor} */ PropertyDescriptor createWith(Map valuesById); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index cc1c3751d9..b3ff0b3021 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -83,7 +83,7 @@ public class RuleSetFactory { /** * Constructor copying all configuration from another factory. - * + * * @param factory * The factory whose configuration to copy. * @param warnDeprecated @@ -109,7 +109,7 @@ public class RuleSetFactory { * "rulesets.properties" resource for each Language with Rule support. * * @return An Iterator of RuleSet objects. - * + * * @throws RuleSetNotFoundException if the ruleset file could not be found */ public Iterator getRegisteredRuleSets() throws RuleSetNotFoundException { @@ -262,7 +262,7 @@ public class RuleSetFactory { /** * Creates a new RuleSet for a single rule - * + * * @param rule * The rule being created * @return The newly created RuleSet @@ -831,24 +831,21 @@ public class RuleSetFactory { return; } - net.sourceforge.pmd.PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId); + PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId); if (pdFactory == null) { throw new RuntimeException("No property descriptor factory for type: " + typeId); } - Map valueKeys = pdFactory.expectedFields(); + Set valueKeys = pdFactory.expectableFields(); Map values = new HashMap<>(valueKeys.size()); // populate a map of values for an individual descriptor - for (Map.Entry entry : valueKeys.entrySet()) { - String valueStr = propertyElement.getAttribute(entry.getKey().attributeName()); - if (entry.getValue() && StringUtil.isEmpty(valueStr)) { - // TODO debug pt - System.out.println("Missing required value for: " + entry.getKey()); - } - values.put(entry.getKey(), valueStr); + for (PropertyDescriptorField field : valueKeys) { + String valueStr = propertyElement.getAttribute(field.attributeName()); + values.put(field, valueStr); } + // casting is not pretty but prevents the interface from having this method PropertyDescriptor desc = ((AbstractPropertyDescriptorFactory) pdFactory).createExternalWith(values); rule.definePropertyDescriptor(desc); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java index 16e29d07ca..30bd9db0e7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java @@ -153,4 +153,6 @@ import net.sourceforge.pmd.util.StringUtil; public boolean isDefinedExternally() { return isDefinedExternally; } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index 331cfce5f1..ed97dbe004 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -25,6 +25,12 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(Character.class) { + + @Override + protected boolean isValueMissing(String value) { + return StringUtil.isMissing(value); + } + @Override public CharacterMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index ad97abbc85..934d831226 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -10,6 +10,7 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.util.StringUtil; /** * Defines a property type that supports single Character values. @@ -21,6 +22,12 @@ public final class CharacterProperty extends AbstractSingleValueProperty FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Character.class) { + + @Override + protected boolean isValueMissing(String value) { + return StringUtil.isMissing(value); + } + @Override public CharacterProperty createWith(Map valuesById, boolean isDefinedExternally) { return new CharacterProperty(nameIn(valuesById), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java index b6dbb8e1c0..53a48f7e14 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleMultiProperty.java @@ -28,8 +28,9 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty valuesById, boolean isDefinedExternally) { String[] minMax = minMaxFrom(valuesById); char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = ValueParser.Companion.parsePrimitives(numericDefaultValueIn(valuesById), - delimiter, DOUBLE_PARSER); + List defaultValues + = ValueParser.Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, DOUBLE_PARSER); + return new DoubleMultiProperty(nameIn(valuesById), descriptionIn(valuesById), DOUBLE_PARSER.valueOf(minMax[0]), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 900a83d618..73cee61bf0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.rule.properties; import static net.sourceforge.pmd.lang.rule.properties.ValueParser.DOUBLE_PARSER; +import java.util.Arrays; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; @@ -26,11 +27,12 @@ public final class DoubleProperty extends AbstractNumericProperty { public DoubleProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); + System.out.println(Arrays.asList(minMax)); return new DoubleProperty(nameIn(valuesById), descriptionIn(valuesById), DOUBLE_PARSER.valueOf(minMax[0]), DOUBLE_PARSER.valueOf(minMax[1]), - DOUBLE_PARSER.valueOf(numericDefaultValueIn(valuesById)), + DOUBLE_PARSER.valueOf(defaultValueIn(valuesById)), 0f, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java index 25dc7badfa..27c5da56dc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatMultiProperty.java @@ -30,7 +30,7 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty defaultValues = Companion.parsePrimitives(numericDefaultValueIn(valuesById), delimiter, FLOAT_PARSER); + List defaultValues = Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, FLOAT_PARSER); return new FloatMultiProperty(nameIn(valuesById), descriptionIn(valuesById), FLOAT_PARSER.valueOf(minMax[0]), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 0861deb897..761039e27a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -29,7 +29,7 @@ public final class FloatProperty extends AbstractNumericProperty { descriptionIn(valuesById), FLOAT_PARSER.valueOf(minMax[0]), FLOAT_PARSER.valueOf(minMax[1]), - FLOAT_PARSER.valueOf(numericDefaultValueIn(valuesById)), + FLOAT_PARSER.valueOf(defaultValueIn(valuesById)), 0f, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java index 1a4e529362..70d5f39e28 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerMultiProperty.java @@ -30,7 +30,7 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty defaultValues = Companion.parsePrimitives(numericDefaultValueIn(valuesById), delimiter, INTEGER_PARSER); + List defaultValues = Companion.parsePrimitives(defaultValueIn(valuesById), delimiter, INTEGER_PARSER); return new IntegerMultiProperty(nameIn(valuesById), descriptionIn(valuesById), INTEGER_PARSER.valueOf(minMax[0]), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index 35322bcd48..d0aefd36d5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -21,6 +21,7 @@ public final class IntegerProperty extends AbstractNumericProperty { public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { + @Override public IntegerProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); @@ -28,13 +29,18 @@ public final class IntegerProperty extends AbstractNumericProperty { descriptionIn(valuesById), INTEGER_PARSER.valueOf(minMax[0]), INTEGER_PARSER.valueOf(minMax[1]), - INTEGER_PARSER.valueOf(numericDefaultValueIn(valuesById)), + INTEGER_PARSER.valueOf(defaultValueIn(valuesById)), 0f, isDefinedExternally); } }; // @formatter:on + static { + System.err.println(FACTORY); + } + + /** * Constructor that limits itself to a single value within the specified limits. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java index 138651c2b3..346fe25913 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/LongProperty.java @@ -29,7 +29,7 @@ public final class LongProperty extends AbstractNumericProperty { descriptionIn(valuesById), LONG_PARSER.valueOf(minMax[0]), LONG_PARSER.valueOf(minMax[1]), - LONG_PARSER.valueOf(numericDefaultValueIn(valuesById)), + LONG_PARSER.valueOf(defaultValueIn(valuesById)), 0f, isDefinedExternally); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java index a0af6ed34c..a75014367c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/MethodMultiProperty.java @@ -33,7 +33,7 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { @Override public MethodMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); + char delimiter = delimiterIn(valuesById, MULTI_VALUE_DELIMITER); return new MethodMultiProperty(nameIn(valuesById), descriptionIn(valuesById), methodsFrom(defaultValueIn(valuesById)), @@ -45,6 +45,15 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty requiredFields = new HashMap<>(); + + + public ExpectedFieldsBuilder() { + + } + + + /** + * Adds a mapping of field/ required to the map. + * + * @param field The field to expect + * @param isRequired Whether it's required or not + * + * @return This instance, so that we have a fluent interface + */ + public ExpectedFieldsBuilder put(PropertyDescriptorField field, boolean isRequired) { + requiredFields.put(field, isRequired); + return this; + } + + + /** + * Gets an immutable map containing the fields we've put here. + * + * @return The map of field/ isRequired mappings + */ + public Map get() { + return Collections.unmodifiableMap(requiredFields); + } + + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index e07406ce1e..9bd2d8f2da 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -27,6 +27,12 @@ public final class StringMultiProperty extends AbstractMultiValueProperty> FACTORY // @formatter:off = new MultiValuePropertyDescriptorFactory(String.class) { + + @Override + protected boolean isValueMissing(String value) { + return StringUtil.isMissing(value); + } + @Override public StringMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { char delimiter = delimiterIn(valuesById); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index 83a9fe91ca..e4a4e4c4ae 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -8,6 +8,7 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; +import net.sourceforge.pmd.util.StringUtil; /** * Defines a datatype that supports single String values. @@ -20,6 +21,12 @@ public final class StringProperty extends AbstractSingleValueProperty { /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(String.class) { + + @Override + protected boolean isValueMissing(String value) { + return StringUtil.isMissing(value); + } + @Override public StringProperty createWith(Map valuesById, boolean isDefinedExternally) { return new StringProperty(nameIn(valuesById), diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java index 5df4007eb8..1a20efeb4f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/MethodPropertyModule.java @@ -29,7 +29,7 @@ public class MethodPropertyModule extends PackagedPropertyModule { @Override protected String packageNameOf(Method method) { - return method == null ? null : method.getDeclaringClass().getName() + '.' + method.getName(); + return method.getDeclaringClass().getName() + '.' + method.getName(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java index 5e36bc8202..90699fc097 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/PackagedPropertyModule.java @@ -29,12 +29,38 @@ public abstract class PackagedPropertyModule { public PackagedPropertyModule(String[] legalPackageNames, List defaults) { - checkValidPackages(defaults, legalPackageNames); + checkValidPackages(legalPackageNames); + checkValidDefaults(defaults, legalPackageNames); this.legalPackageNames = legalPackageNames; } + /** + * Checks that the legal packages are okay. + * + * @param legalNamePrefixes Prefixes to check. Can be null, but not contain null + * + * @throws IllegalArgumentException If the prefixes contain null + * @throws IllegalArgumentException If one name that does not look like a package name + */ + private void checkValidPackages(String[] legalNamePrefixes) throws IllegalArgumentException { + if (legalNamePrefixes == null) { + return; + } + + for (String name : legalNamePrefixes) { + if (name == null) { + throw new IllegalArgumentException("Null is not allowed in the legal package names:" + + Arrays.toString(legalNamePrefixes)); + } else if (!PACKAGE_NAME_PATTERN.matcher(name).matches()) { + throw new IllegalArgumentException("One name is not a package: '" + name + "'"); + + } + } + } + + /** * 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. @@ -44,15 +70,18 @@ public abstract class PackagedPropertyModule { * * @throws IllegalArgumentException if some items are not allowed */ - private void checkValidPackages(List items, String[] legalNamePrefixes) { + private void checkValidDefaults(List items, String[] legalNamePrefixes) { - if (legalNamePrefixes == null) { + if (legalNamePrefixes == null) { // valid value, matches everything return; } Set nameSet = new HashSet<>(); for (T item : items) { + if (item == null) { + continue; + } nameSet.add(packageNameOf(item)); } @@ -79,7 +108,7 @@ public abstract class PackagedPropertyModule { /** * Returns the package name of the item. * - * @param item Item + * @param item Item (not null) * * @return Package name of the item */ @@ -142,13 +171,6 @@ public abstract class PackagedPropertyModule { public String[] packageNamesIn(Map params) { String[] packageNames = StringUtil.substringsOf(params.get(LEGAL_PACKAGES), PACKAGE_NAME_DELIMITER); - - for (String name : packageNames) { - if (!PACKAGE_NAME_PATTERN.matcher(name).matches()) { - throw new IllegalArgumentException("One name is not a package: '" + name + "'"); - } - } - return packageNames; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java index fe9e7ac160..759bd406db 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java @@ -18,17 +18,20 @@ public final class StringUtil { private static final String[] EMPTY_STRINGS = new String[0]; private static final boolean SUPPORTS_UTF8 = "yes" - .equals(System.getProperty("net.sourceforge.pmd.supportUTF8", "no")); + .equals(System.getProperty("net.sourceforge.pmd.supportUTF8", "no")); + private StringUtil() { } + /** * Return whether the non-null text arg starts with any of the prefix * values. * * @param text * @param prefixes + * * @return boolean */ public static boolean startsWithAny(String text, String... prefixes) { @@ -42,11 +45,13 @@ public final class StringUtil { return false; } + /** * Returns whether the non-null text arg matches any of the test values. * * @param text * @param tests + * * @return boolean */ public static boolean isAnyOf(String text, String... tests) { @@ -60,12 +65,14 @@ public final class StringUtil { return false; } + /** * Checks for the existence of any of the listed prefixes on the non-null * text and removes them. * * @param text * @param prefixes + * * @return String */ public static String withoutPrefixes(String text, String... prefixes) { @@ -79,21 +86,50 @@ public final class StringUtil { return text; } + + /** + * @param value String + * + * @return boolean + */ + public static boolean isNotEmpty(String value) { + return !isEmpty(value); + } + + /** * Returns true if the value arg is either null, empty, or full of * whitespace characters. More efficient that calling * (string).trim().length() == 0 * * @param value - * @return true if the value is empty, false - * otherwise. + * + * @return true if the value is empty, false otherwise. */ public static boolean isEmpty(String value) { + return isMissing(value) || nullSafeIsBlank(value); + } + + + /** + * Returns true if the argument is null or the empty string. + * + * @param value String to test + * + * @return True if the argument is null or the empty string + */ + public static boolean isMissing(String value) { if (value == null || "".equals(value)) { return true; } + return false; + } + + + /** Argument must not be null. */ + private static boolean nullSafeIsBlank(String value) { for (int i = 0; i < value.length(); i++) { if (!Character.isWhitespace(value.charAt(i))) { return false; @@ -103,22 +139,31 @@ public final class StringUtil { return true; } + /** + * Returns true if the argument is null or entirely composed of whitespace characters. * - * @param value - * String - * @return boolean + * @param value String to test + * + * @return True if the argument is null or entirely composed of whitespace characters. */ - public static boolean isNotEmpty(String value) { - return !isEmpty(value); + public static boolean isBlank(String value) { + + if (value == null) { + return true; + } + + return nullSafeIsBlank(value); } + /** * Returns true if both strings are effectively null or whitespace, returns * false otherwise if they have actual text that differs. * * @param a * @param b + * * @return boolean */ public static boolean areSemanticEquals(String a, String b) { @@ -133,43 +178,12 @@ public final class StringUtil { return a.equals(b); } - /** - * - * @param original - * String - * @param oldChar - * char - * @param newString - * String - * @return String - */ - public static String replaceString(final String original, char oldChar, final String newString) { - int index = original.indexOf(oldChar); - if (index < 0) { - return original; - } else { - final String replace = newString == null ? "" : newString; - final StringBuilder buf = new StringBuilder(Math.max(16, original.length() + replace.length())); - int last = 0; - while (index != -1) { - buf.append(original.substring(last, index)); - buf.append(replace); - last = index + 1; - index = original.indexOf(oldChar, last); - } - buf.append(original.substring(last)); - return buf.toString(); - } - } /** + * @param original String + * @param oldString String + * @param newString String * - * @param original - * String - * @param oldString - * String - * @param newString - * String * @return String */ public static String replaceString(final String original, final String oldString, final String newString) { @@ -191,64 +205,28 @@ public final class StringUtil { } } + /** * Appends to a StringBuilder the String src where non-ASCII and XML special * chars are escaped. * - * @param buf - * The destination XML stream - * @param src - * The String to append to the stream + * @param buf The destination XML stream + * @param src The String to append to the stream * - * @deprecated use {@link #appendXmlEscaped(StringBuilder, String, boolean)} - * instead + * @deprecated use {@link #appendXmlEscaped(StringBuilder, String, boolean)} instead */ @Deprecated public static void appendXmlEscaped(StringBuilder buf, String src) { appendXmlEscaped(buf, src, SUPPORTS_UTF8); } - /** - * Replace some whitespace characters so they are visually apparent. - * - * @param o - * @return String - */ - public static String escapeWhitespace(Object o) { - - if (o == null) { - return null; - } - String s = String.valueOf(o); - s = s.replace("\n", "\\n"); - s = s.replace("\r", "\\r"); - s = s.replace("\t", "\\t"); - return s; - } /** - * - * @param string - * String - * @return String - * - * @deprecated Use StringEscapeUtils#escapeHtml4 instead - */ - @Deprecated - public static String htmlEncode(String string) { - String encoded = replaceString(string, '&', "&"); - encoded = replaceString(encoded, '<', "<"); - return replaceString(encoded, '>', ">"); - } - - /** - * * @param buf * @param src - * @param supportUTF8 - * override the default setting, whether special characters - * should be replaced with entities ( false) or - * should be included as is ( true). + * @param supportUTF8 override the default setting, whether special characters should be replaced with entities ( + * false) or should be included as is ( true). + * * @see #appendXmlEscaped(StringBuilder, String) */ public static void appendXmlEscaped(StringBuilder buf, String src, boolean supportUTF8) { @@ -283,6 +261,69 @@ public final class StringUtil { } } + + /** + * Replace some whitespace characters so they are visually apparent. + * + * @param o + * + * @return String + */ + public static String escapeWhitespace(Object o) { + + if (o == null) { + return null; + } + String s = String.valueOf(o); + s = s.replace("\n", "\\n"); + s = s.replace("\r", "\\r"); + s = s.replace("\t", "\\t"); + return s; + } + + + /** + * @param string String + * + * @return String + * + * @deprecated Use StringEscapeUtils#escapeHtml4 instead + */ + @Deprecated + public static String htmlEncode(String string) { + String encoded = replaceString(string, '&', "&"); + encoded = replaceString(encoded, '<', "<"); + return replaceString(encoded, '>', ">"); + } + + + /** + * @param original String + * @param oldChar char + * @param newString String + * + * @return String + */ + public static String replaceString(final String original, char oldChar, final String newString) { + int index = original.indexOf(oldChar); + if (index < 0) { + return original; + } else { + final String replace = newString == null ? "" : newString; + final StringBuilder buf = new StringBuilder(Math.max(16, original.length() + replace.length())); + int last = 0; + while (index != -1) { + buf.append(original.substring(last, index)); + buf.append(replace); + last = index + 1; + index = original.indexOf(oldChar, last); + } + buf.append(original.substring(last)); + return buf.toString(); + } + } + + /** * Parses the input source using the delimiter specified. This method is * much faster than using the StringTokenizer or String.split(char) approach @@ -291,10 +332,9 @@ public final class StringUtil { * * FIXME - we're on JDK 1.4 now, can we replace this with String.split? * - * @param source - * String - * @param delimiter - * char + * @param source String + * @param delimiter char + * * @return String[] */ public static String[] substringsOf(String source, char delimiter) { @@ -314,7 +354,7 @@ public final class StringUtil { } if (delimiterCount == 0) { - return new String[] { source }; + return new String[] {source}; } String[] results = new String[delimiterCount + 1]; @@ -334,13 +374,13 @@ public final class StringUtil { return results; } + /** * Much more efficient than StringTokenizer. * - * @param str - * String - * @param separator - * char + * @param str String + * @param separator char + * * @return String[] */ public static String[] substringsOf(String str, String separator) { @@ -351,7 +391,7 @@ public final class StringUtil { int index = str.indexOf(separator); if (index == -1) { - return new String[] { str }; + return new String[] {str}; } List list = new ArrayList<>(); @@ -366,16 +406,14 @@ public final class StringUtil { return list.toArray(new String[list.size()]); } + /** * Copies the elements returned by the iterator onto the string buffer each * delimited by the separator. * - * @param sb - * StringBuffer - * @param iter - * Iterator - * @param separator - * String + * @param sb StringBuffer + * @param iter Iterator + * @param separator String */ public static void asStringOn(StringBuffer sb, Iterator iter, String separator) { @@ -391,16 +429,14 @@ public final class StringUtil { } } + /** * Copies the array items onto the string builder each delimited by the * separator. Does nothing if the array is null or empty. * - * @param sb - * StringBuilder - * @param items - * Object[] - * @param separator - * String + * @param sb StringBuilder + * @param items Object[] + * @param separator String */ public static void asStringOn(StringBuilder sb, Object[] items, String separator) { @@ -416,31 +452,6 @@ public final class StringUtil { } } - /** - * Return the length of the shortest string in the array. If the collection - * is empty or any one of them is null then it returns 0. - * - * @param strings - * String[] - * @return int - */ - public static int lengthOfShortestIn(String[] strings) { - - if (CollectionUtil.isEmpty(strings)) { - return 0; - } - - int minLength = Integer.MAX_VALUE; - - for (int i = 0; i < strings.length; i++) { - if (strings[i] == null) { - return 0; - } - minLength = Math.min(minLength, strings[i].length()); - } - - return minLength; - } /** * Determine the maximum number of common leading whitespace characters the @@ -448,8 +459,8 @@ public final class StringUtil { * leading characters can be removed to shift all the text in the strings to * the left without misaligning them. * - * @param strings - * String[] + * @param strings String[] + * * @return int */ public static int maxCommonLeadingWhitespaceForAll(String[] strings) { @@ -478,12 +489,41 @@ public final class StringUtil { return shortest; } + + /** + * Return the length of the shortest string in the array. If the collection + * is empty or any one of them is null then it returns 0. + * + * @param strings String[] + * + * @return int + */ + public static int lengthOfShortestIn(String[] strings) { + + if (CollectionUtil.isEmpty(strings)) { + return 0; + } + + int minLength = Integer.MAX_VALUE; + + for (int i = 0; i < strings.length; i++) { + if (strings[i] == null) { + return 0; + } + minLength = Math.min(minLength, strings[i].length()); + } + + return minLength; + } + + /** * Trims off the leading characters off the strings up to the trimDepth * specified. Returns the same strings if trimDepth = 0 * * @param strings * @param trimDepth + * * @return String[] */ public static String[] trimStartOn(String[] strings, int trimDepth) { @@ -499,13 +539,13 @@ public final class StringUtil { return results; } + /** * Left pads a string. * - * @param s - * The String to pad - * @param length - * The desired minimum length of the resulting padded String + * @param s The String to pad + * @param length The desired minimum length of the resulting padded String + * * @return The resulting left padded String */ public static String lpad(String s, int length) { @@ -518,29 +558,23 @@ public final class StringUtil { return res; } + /** * Are the two String values the same. The Strings can be optionally trimmed * before checking. The Strings can be optionally compared ignoring case. * The Strings can be have embedded whitespace standardized before * comparing. Two null values are treated as equal. * - * @param s1 - * The first String. - * @param s2 - * The second String. - * @param trim - * Indicates if the Strings should be trimmed before comparison. - * @param ignoreCase - * Indicates if the case of the Strings should ignored during - * comparison. - * @param standardizeWhitespace - * Indicates if the embedded whitespace should be standardized - * before comparison. - * @return true if the Strings are the same, false - * otherwise. + * @param s1 The first String. + * @param s2 The second String. + * @param trim Indicates if the Strings should be trimmed before comparison. + * @param ignoreCase Indicates if the case of the Strings should ignored during comparison. + * @param standardizeWhitespace Indicates if the embedded whitespace should be standardized before comparison. + * + * @return true if the Strings are the same, false otherwise. */ public static boolean isSame(String s1, String s2, boolean trim, boolean ignoreCase, - boolean standardizeWhitespace) { + boolean standardizeWhitespace) { if (s1 == null && s2 == null) { return true; } else if (s1 == null || s2 == null) { @@ -560,14 +594,14 @@ public final class StringUtil { } } + /** * Formats all items onto a string with separators if more than one exists, * return an empty string if the items are null or empty. * - * @param items - * Object[] - * @param separator - * String + * @param items Object[] + * @param separator String + * * @return String */ public static String asString(Object[] items, String separator) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java index 461ca25728..cc1eafb427 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java @@ -6,9 +6,12 @@ package net.sourceforge.pmd.properties; import static org.junit.Assert.assertNotNull; +import java.util.Map; + import org.junit.Test; import net.sourceforge.pmd.NumericPropertyDescriptor; +import net.sourceforge.pmd.PropertyDescriptorField; /** * @author Clément Fournier @@ -29,4 +32,28 @@ public abstract class AbstractNumericPropertyDescriptorTester extends Abstrac } + @Test(expected = RuntimeException.class) + public void testMissingMinThreshold() { + Map attributes = getPropertyDescriptorValues(); + attributes.remove(PropertyDescriptorField.MIN); + getSingleFactory().createWith(attributes); + } + + + @Override + protected Map getPropertyDescriptorValues() { + Map attributes = super.getPropertyDescriptorValues(); + attributes.put(PropertyDescriptorField.MIN, "0"); + attributes.put(PropertyDescriptorField.MAX, "10"); + return attributes; + } + + + @Test(expected = RuntimeException.class) + public void testMissingMaxThreshold() { + Map attributes = getPropertyDescriptorValues(); + attributes.remove(PropertyDescriptorField.MAX); + getSingleFactory().createWith(attributes); + + } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java new file mode 100644 index 0000000000..0d8460cf92 --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java @@ -0,0 +1,38 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties; + +import java.util.Map; + +import org.junit.Test; + +import net.sourceforge.pmd.PropertyDescriptorField; + +/** + * @author Clément Fournier + */ +public abstract class AbstractPackagedPropertyDescriptorTester extends AbstractPropertyDescriptorTester { + + /* default */ AbstractPackagedPropertyDescriptorTester(String typeName) { + super(typeName); + } + + + @Test + public void testMissingPackageNames() { + Map attributes = getPropertyDescriptorValues(); + attributes.remove(PropertyDescriptorField.LEGAL_PACKAGES); + getMultiFactory().createWith(attributes); // no exception, null is ok + getSingleFactory().createWith(attributes); + } + + + @Override + protected Map getPropertyDescriptorValues() { + Map attributes = super.getPropertyDescriptorValues(); + attributes.put(PropertyDescriptorField.LEGAL_PACKAGES, "java.lang"); + return attributes; + } +} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index 600f739169..31ec26fa30 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -34,9 +34,9 @@ public abstract class AbstractPropertyDescriptorTester { public static final String PUNCTUATION_CHARS = "!@#$%^&*()_-+=[]{}\\|;:'\",.<>/?`~"; public static final String WHITESPACE_CHARS = " \t\n"; - public static final String DIGIST_CHARS = "0123456789"; + public static final String DIGIT_CHARS = "0123456789"; public static final String ALPHA_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmniopqrstuvwxyz"; - public static final String ALPHA_NUMERIC_CHARS = DIGIST_CHARS + ALPHA_CHARS; + public static final String ALPHA_NUMERIC_CHARS = DIGIT_CHARS + ALPHA_CHARS; public static final String ALL_CHARS = PUNCTUATION_CHARS + WHITESPACE_CHARS + ALPHA_NUMERIC_CHARS; private static final int MULTI_VALUE_COUNT = 10; protected final String typeName; @@ -62,18 +62,18 @@ public abstract class AbstractPropertyDescriptorTester { } + @SuppressWarnings("unchecked") protected final PropertyDescriptorFactory getSingleFactory() { return (PropertyDescriptorFactory) PropertyDescriptorUtil.factoryFor(typeName); } - private Map getPropertyDescriptorValues() { + protected Map getPropertyDescriptorValues() { Map valuesById = new HashMap<>(); valuesById.put(PropertyDescriptorField.NAME, "test"); valuesById.put(PropertyDescriptorField.DESCRIPTION, "desc"); - valuesById.put(PropertyDescriptorField.MIN, "0"); - valuesById.put(PropertyDescriptorField.MAX, "10"); + valuesById.put(PropertyDescriptorField.DEFAULT_VALUE, createProperty().asDelimitedString(createValue())); return valuesById; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java index 879c8fcb6a..846d9f1546 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/FloatPropertyTest.java @@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.FloatProperty; * * @author Brian Remedios */ -public class FloatPropertyTest extends AbstractPropertyDescriptorTester { +public class FloatPropertyTest extends AbstractNumericPropertyDescriptorTester { private static final float MIN = 1.0f; private static final float MAX = 11.0f; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java index b8c644f6da..be37bb04e8 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/IntegerPropertyTest.java @@ -18,7 +18,7 @@ import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; * * @author Brian Remedios */ -public class IntegerPropertyTest extends AbstractPropertyDescriptorTester { +public class IntegerPropertyTest extends AbstractNumericPropertyDescriptorTester { private static final int MIN = 1; private static final int MAX = 12; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java index e3c1736214..6f3aac47fc 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/LongPropertyTest.java @@ -13,7 +13,7 @@ import net.sourceforge.pmd.lang.rule.properties.LongProperty; /** * @author Clément Fournier */ -public class LongPropertyTest extends AbstractPropertyDescriptorTester { +public class LongPropertyTest extends AbstractNumericPropertyDescriptorTester { private static final long MIN = 10L; private static final long MAX = 11000L; @@ -62,13 +62,4 @@ public class LongPropertyTest extends AbstractPropertyDescriptorTester { new Long[] {-1000L, 0L, 100L, 20L}, 1.0f); } - - public static LongProperty randomProperty(int nameLength, int descLength, boolean multiValue) { - - long defalt = randomLong(0, 1000); - - return new LongProperty(randomString(nameLength), randomString(descLength), defalt - 10000, defalt + 10000, - defalt, 0f); - } - } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java index d4cada806c..0cffce21ed 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/MethodPropertyTest.java @@ -31,7 +31,7 @@ import net.sourceforge.pmd.util.ClassUtil; * * @author Brian Remedios */ -public class MethodPropertyTest extends AbstractPropertyDescriptorTester { +public class MethodPropertyTest extends AbstractPackagedPropertyDescriptorTester { private static final Method[] ALL_METHODS = String.class.getDeclaredMethods(); @@ -48,7 +48,7 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester @Test public void testAsStringOn() { - Method method = null; + Method method; for (int i = 0; i < METHOD_SIGNATURES.length; i++) { method = ValueParser.METHOD_PARSER.valueOf(METHOD_SIGNATURES[i]); @@ -67,7 +67,7 @@ public class MethodPropertyTest extends AbstractPropertyDescriptorTester assertNotNull("Unable to identify method: " + METHOD_SIGNATURES[i], methods[i]); } - String translatedMethod = null; + String translatedMethod; for (int i = 0; i < methods.length; i++) { translatedMethod = MethodPropertyModule.asString(methods[i]); assertTrue("Translated method does not match", ClassUtil.withoutPackageName(METHOD_SIGNATURES[i]) diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java index 4e62f80594..e2387ff45d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/StringPropertyTest.java @@ -43,7 +43,7 @@ public class StringPropertyTest extends AbstractPropertyDescriptorTester */ private String newString() { - int strLength = randomInt(0, MAX_STRING_LENGTH); + int strLength = randomInt(1, MAX_STRING_LENGTH); char[] chars = new char[strLength]; for (int i = 0; i < chars.length; i++) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java index 873cb7ad71..f7333968f5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/TypePropertyTest.java @@ -28,7 +28,7 @@ import net.sourceforge.pmd.lang.rule.properties.TypeProperty; * * @author Brian Remedios */ -public class TypePropertyTest extends AbstractPropertyDescriptorTester { +public class TypePropertyTest extends AbstractPackagedPropertyDescriptorTester { private static final List JAVA_LANG_CLASSES = Arrays.asList(String.class, Integer.class, Thread.class, Object.class, Runtime.class); From 35dee58bc809ff9254e3214f6898594cadab0121 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Sat, 15 Jul 2017 16:36:11 +0200 Subject: [PATCH 48/53] Fix initialisation bug --- .../AbstractPropertyDescriptorFactory.java | 49 +++++++-------- .../pmd/MultiValuePropertyDescriptor.java | 6 +- .../pmd/NumericPropertyDescriptor.java | 4 +- .../sourceforge/pmd/PropertyDescriptor.java | 8 +-- .../java/net/sourceforge/pmd/RuleSet.java | 6 +- .../net/sourceforge/pmd/RuleSetFactory.java | 21 +++++-- .../sourceforge/pmd/RuleSetReferenceId.java | 2 +- .../properties/CharacterMultiProperty.java | 4 +- .../rule/properties/CharacterProperty.java | 4 +- .../lang/rule/properties/DoubleProperty.java | 12 ++-- .../properties/ExpectedFieldsBuilder.java | 59 +++++++++++++++++++ .../lang/rule/properties/FloatProperty.java | 2 + .../lang/rule/properties/IntegerProperty.java | 6 +- .../properties/PropertyDescriptorUtil.java | 52 +--------------- .../rule/properties/StringMultiProperty.java | 4 +- .../lang/rule/properties/StringProperty.java | 4 +- .../net/sourceforge/pmd/util/StringUtil.java | 44 ++------------ 17 files changed, 141 insertions(+), 146 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ExpectedFieldsBuilder.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index 29bea13d47..308d47d963 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd; -import static net.sourceforge.pmd.PropertyDescriptor.CORE_FIELD_TYPES_BY_KEY; +import static net.sourceforge.pmd.PropertyDescriptor.CORE_EXPECTED_FIELDS; import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER; import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION; @@ -19,6 +19,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.util.StringUtil; /** @@ -30,26 +32,18 @@ import net.sourceforge.pmd.util.StringUtil; */ public abstract class AbstractPropertyDescriptorFactory implements PropertyDescriptorFactory { - - - - static { - System.err.println(CORE_FIELD_TYPES_BY_KEY); - } - - private final Class valueType; /** * Denote the identifiers of the expected fields paired with booleans - * denoting whether they are required (non-null) or not. + * denoting whether they are required or not. */ private final Map expectedFields; public AbstractPropertyDescriptorFactory(Class theValueType) { valueType = theValueType; - expectedFields = CORE_FIELD_TYPES_BY_KEY; + expectedFields = CORE_EXPECTED_FIELDS; } @@ -57,12 +51,12 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe valueType = theValueType; if (additionalFieldTypesByKey == null) { - expectedFields = CORE_FIELD_TYPES_BY_KEY; + expectedFields = CORE_EXPECTED_FIELDS; return; } Map temp - = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size()); - temp.putAll(CORE_FIELD_TYPES_BY_KEY); + = new HashMap<>(CORE_EXPECTED_FIELDS.size() + additionalFieldTypesByKey.size()); + temp.putAll(CORE_EXPECTED_FIELDS); temp.putAll(additionalFieldTypesByKey); expectedFields = Collections.unmodifiableMap(temp); @@ -116,7 +110,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe */ protected String defaultValueIn(Map valuesById) { String deft = valuesById.get(DEFAULT_VALUE); - if (StringUtil.isEmpty(deft)) { + if (isValueMissing(deft)) { throw new RuntimeException("Default value was null, empty, or missing"); } return deft; @@ -125,7 +119,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe @Override public final PropertyDescriptor createWith(Map valuesById) { - // checkRequiredFields(valuesById); + checkRequiredFields(valuesById); return createWith(valuesById, false); } @@ -133,7 +127,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe /** Checks whether all required fields are present in the map. */ private void checkRequiredFields(Map valuesById) { for (Entry entry : expectedFields.entrySet()) { - if (entry.getValue() && StringUtil.isEmpty(valuesById.get(entry.getKey()))) { + if (entry.getValue() && isValueMissing(valuesById.get(entry.getKey()))) { throw new RuntimeException("Missing required value for key: " + entry.getKey()); } } @@ -249,7 +243,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe characterStr = valuesById.get(DELIMITER).trim(); } - if (StringUtil.isEmpty(characterStr)) { + if (StringUtils.isBlank(characterStr)) { return defaultDelimiter; } @@ -272,7 +266,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe protected static String[] minMaxFrom(Map valuesById) { String min = minValueIn(valuesById); String max = maxValueIn(valuesById); - if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) { + if (StringUtils.isBlank(min) || StringUtils.isBlank(max)) { throw new RuntimeException("min and max values must be specified"); } return new String[] {min, max}; @@ -291,7 +285,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { String names = valuesById.get(LEGAL_PACKAGES); - if (StringUtil.isEmpty(names)) { + if (StringUtils.isBlank(names)) { return null; } return StringUtil.substringsOf(names, delimiter); @@ -299,18 +293,19 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe /** - * Returns a map describing which fields are required to build an + * Returns a map describing which fields are required to build a property using this factory. The parameters are + * added to the {@link PropertyDescriptor#CORE_EXPECTED_FIELDS}, which are required for all descriptors. * - * @param otherKeys - * @param otherValues + * @param otherKeys Additional keys + * @param otherValues Whether the corresponding keys are required or not * - * @return + * @return The complete map of expected fields. */ - public static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, + static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, Boolean[] otherValues) { Map largerMap = new HashMap<>( - otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size()); - largerMap.putAll(CORE_FIELD_TYPES_BY_KEY); + otherKeys.length + CORE_EXPECTED_FIELDS.size()); + largerMap.putAll(CORE_EXPECTED_FIELDS); for (int i = 0; i < otherKeys.length; i++) { largerMap.put(otherKeys[i], otherValues[i]); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java index 092bd6edf5..765b6feec1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/MultiValuePropertyDescriptor.java @@ -7,8 +7,10 @@ package net.sourceforge.pmd; import java.util.List; /** - * Specializes property descriptors for single valued descriptors. For this type of property, the return value of the - * {@link #type()} method must be the class literal of the type parameter of the interface {@link PropertyDescriptor}. + * Specializes property descriptors for multi valued descriptors. For this type of property, the return value of the + * {@link #type()} method must be the class literal of the type parameter of this interface, which is the type of the + * components of the list (not the type of the list). Notice that for implementors, the type parameter of this interface + * is not the same as the type parameter of {@link PropertyDescriptor} they inherit! * * @param The type of value this descriptor works with. This is the type of the list's component. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java index 6ce13033a3..d99db5c96e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/NumericPropertyDescriptor.java @@ -9,7 +9,7 @@ import static net.sourceforge.pmd.PropertyDescriptorField.MIN; import java.util.Map; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.lang.rule.properties.ExpectedFieldsBuilder; /** * Defines a descriptor type whose instance values are required to lie within @@ -22,7 +22,7 @@ import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil; public interface NumericPropertyDescriptor extends PropertyDescriptor { Map NUMBER_FIELD_TYPES_BY_KEY - = PropertyDescriptorUtil.expectedFields().put(MIN, true).put(MAX, true).get(); + = ExpectedFieldsBuilder.instance().put(MIN, true).put(MAX, true).build(); /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java index 2e990f25ac..2bdd515460 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java @@ -11,7 +11,7 @@ import static net.sourceforge.pmd.PropertyDescriptorField.NAME; import java.util.Map; -import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil.ExpectedFieldsBuilder; +import net.sourceforge.pmd.lang.rule.properties.ExpectedFieldsBuilder; /** * Property value descriptor that defines the use & requirements for setting @@ -35,13 +35,13 @@ import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil.ExpectedF public interface PropertyDescriptor extends Comparable> { /** Default expected fields. Unmodifiable. */ - Map CORE_FIELD_TYPES_BY_KEY - = (new ExpectedFieldsBuilder()) + Map CORE_EXPECTED_FIELDS + = ExpectedFieldsBuilder.instance() .put(NAME, true) .put(DESCRIPTION, true) .put(DEFAULT_VALUE, true) .put(DELIMITER, false) - .get(); + .build(); /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java index 6dc28c6110..c5e25f052b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java @@ -16,6 +16,8 @@ import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.benchmark.Benchmark; import net.sourceforge.pmd.benchmark.Benchmarker; import net.sourceforge.pmd.cache.ChecksumAware; @@ -179,7 +181,7 @@ public class RuleSet implements ChecksumAware { * @return The same builder, for a fluid programming interface */ public RuleSetBuilder addRuleByReference(final String ruleSetFileName, final Rule rule) { - if (StringUtil.isEmpty(ruleSetFileName)) { + if (StringUtils.isBlank(ruleSetFileName)) { throw new RuntimeException( "Adding a rule by reference is not allowed with an empty rule set file name."); } @@ -246,7 +248,7 @@ public class RuleSet implements ChecksumAware { */ public RuleSetBuilder addRuleSetByReference(final RuleSet ruleSet, final boolean allRules, final String... excludes) { - if (StringUtil.isEmpty(ruleSet.getFileName())) { + if (StringUtils.isBlank(ruleSet.getFileName())) { throw new RuntimeException( "Adding a rule by reference is not allowed with an empty rule set file name."); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index b3ff0b3021..a79c98f6f5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd; +import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE; + import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -23,6 +25,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -414,7 +417,7 @@ public class RuleSetFactory { String ref = ruleElement.getAttribute("ref"); if (ref.endsWith("xml")) { parseRuleSetReferenceNode(ruleSetReferenceId, ruleSetBuilder, ruleElement, ref); - } else if (StringUtil.isEmpty(ref)) { + } else if (StringUtils.isBlank(ref)) { parseSingleRuleNode(ruleSetReferenceId, ruleSetBuilder, ruleNode); } else { parseRuleReferenceNode(ruleSetReferenceId, ruleSetBuilder, ruleNode, ref, withDeprecatedRuleReferences); @@ -812,13 +815,13 @@ public class RuleSetFactory { Element propertyElement = (Element) propertyNode; String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName()); - String strValue = propertyElement.getAttribute(PropertyDescriptorField.DEFAULT_VALUE.attributeName()); - if (StringUtil.isEmpty(strValue)) { + String strValue = propertyElement.getAttribute(DEFAULT_VALUE.attributeName()); + if (StringUtils.isBlank(strValue)) { strValue = valueFrom(propertyElement); } // Setting of existing property, or defining a new property? - if (StringUtil.isEmpty(typeId)) { + if (StringUtils.isBlank(typeId)) { String name = propertyElement.getAttribute(PropertyDescriptorField.NAME.attributeName()); PropertyDescriptor propertyDescriptor = rule.getPropertyDescriptor(name); @@ -842,9 +845,19 @@ public class RuleSetFactory { // populate a map of values for an individual descriptor for (PropertyDescriptorField field : valueKeys) { String valueStr = propertyElement.getAttribute(field.attributeName()); + if (valueStr != null) values.put(field, valueStr); } + if (StringUtils.isBlank(values.get(DEFAULT_VALUE))) { + NodeList children = propertyElement.getElementsByTagName(DEFAULT_VALUE.attributeName()); + if (children.getLength() == 1) { + values.put(DEFAULT_VALUE, children.item(0).getTextContent()); + } else { + throw new RuntimeException("No value defined!"); + } + } + // casting is not pretty but prevents the interface from having this method PropertyDescriptor desc = ((AbstractPropertyDescriptorFactory) pdFactory).createExternalWith(values); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java index dbf958d305..b0c033ceea 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java @@ -408,7 +408,7 @@ public class RuleSetReferenceId { */ public InputStream getInputStream(ClassLoader classLoader) throws RuleSetNotFoundException { if (externalRuleSetReferenceId == null) { - InputStream in = StringUtil.isEmpty(ruleSetFileName) ? null + InputStream in = StringUtils.isBlank(ruleSetFileName) ? null : ResourceLoader.loadResourceAsStream(ruleSetFileName, classLoader); if (in == null) { throw new RuleSetNotFoundException("Can't find resource '" + ruleSetFileName + "' for rule '" + ruleName diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java index ed97dbe004..b325bc1ded 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterMultiProperty.java @@ -9,6 +9,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion; @@ -28,7 +30,7 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { @Override public DoubleProperty createWith(Map valuesById, boolean isDefinedExternally) { final String[] minMax = minMaxFrom(valuesById); - System.out.println(Arrays.asList(minMax)); return new DoubleProperty(nameIn(valuesById), descriptionIn(valuesById), - DOUBLE_PARSER.valueOf(minMax[0]), - DOUBLE_PARSER.valueOf(minMax[1]), - DOUBLE_PARSER.valueOf(defaultValueIn(valuesById)), + doubleFrom(minMax[0]), + doubleFrom(minMax[1]), + doubleFrom(defaultValueIn(valuesById)), 0f, isDefinedExternally); } @@ -73,8 +73,8 @@ public final class DoubleProperty extends AbstractNumericProperty { * * @return Parsed Double */ - public static Double doubleFrom(String numberString) { - return Double.valueOf(numberString); + private static Double doubleFrom(String numberString) { + return DOUBLE_PARSER.valueOf(numberString); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ExpectedFieldsBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ExpectedFieldsBuilder.java new file mode 100644 index 0000000000..11c3160d7d --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/ExpectedFieldsBuilder.java @@ -0,0 +1,59 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.pmd.PropertyDescriptorField; + +/** Builder for an expected fields map. */ +public final class ExpectedFieldsBuilder { + + private final Map requiredFields = new HashMap<>(); + + + private ExpectedFieldsBuilder() { + + } + + + /** + * Adds a mapping of field/ required to the map. + * + * @param field The field to expect + * @param isRequired Whether it's required or not + * + * @return This instance, so that we have a fluent interface + */ + public ExpectedFieldsBuilder put(PropertyDescriptorField field, boolean isRequired) { + requiredFields.put(field, isRequired); + return this; + } + + + /** + * Gets an immutable map containing the fields we've put here. + * + * @return The map of field/ isRequired mappings + */ + public Map build() { + return Collections.unmodifiableMap(requiredFields); + } + + + /** + * Gets a builder for a required fields map. + * + * @return A builder + * + * @see ExpectedFieldsBuilder + */ + public static ExpectedFieldsBuilder instance() { + return new ExpectedFieldsBuilder(); + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java index 761039e27a..c2b6d68cfb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/FloatProperty.java @@ -92,4 +92,6 @@ public final class FloatProperty extends AbstractNumericProperty { protected Float createFrom(String value) { return FLOAT_PARSER.valueOf(value); } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java index d0aefd36d5..da4412232c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/IntegerProperty.java @@ -19,6 +19,7 @@ import net.sourceforge.pmd.PropertyDescriptorField; */ public final class IntegerProperty extends AbstractNumericProperty { + /** Factory. */ public static final PropertyDescriptorFactory FACTORY // @formatter:off = new SingleValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { @@ -36,11 +37,6 @@ public final class IntegerProperty extends AbstractNumericProperty { }; // @formatter:on - static { - System.err.println(FACTORY); - } - - /** * Constructor that limits itself to a single value within the specified limits. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java index 59fafa8298..3b1f87fe7f 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/PropertyDescriptorUtil.java @@ -9,7 +9,6 @@ import java.util.HashMap; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; -import net.sourceforge.pmd.PropertyDescriptorField; /** * Utility class allowing to find the factory of a specific type of descriptor. That's used to define descriptors in @@ -24,7 +23,6 @@ public final class PropertyDescriptorUtil { static { Map> temp = new HashMap<>(18); - temp.put("Boolean", BooleanProperty.FACTORY); temp.put("List", BooleanMultiProperty.FACTORY); @@ -33,6 +31,7 @@ public final class PropertyDescriptorUtil { temp.put("Character", CharacterProperty.FACTORY); temp.put("List", CharacterMultiProperty.FACTORY); + temp.put("Integer", IntegerProperty.FACTORY); temp.put("List", IntegerMultiProperty.FACTORY); temp.put("Long", LongProperty.FACTORY); @@ -41,7 +40,6 @@ public final class PropertyDescriptorUtil { temp.put("List", FloatMultiProperty.FACTORY); temp.put("Double", DoubleProperty.FACTORY); temp.put("List", DoubleMultiProperty.FACTORY); - // temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf implement that // temp.put("List", EnumeratedMultiProperty.FACTORY); @@ -90,52 +88,4 @@ public final class PropertyDescriptorUtil { } - /** - * Gets a builder for a required fields map. - * - * @return A builder - * - * @see ExpectedFieldsBuilder - */ - public static ExpectedFieldsBuilder expectedFields() { - return new ExpectedFieldsBuilder(); - } - - - /** Builder for an expected fields map. */ - public static final class ExpectedFieldsBuilder { - - Map requiredFields = new HashMap<>(); - - - public ExpectedFieldsBuilder() { - - } - - - /** - * Adds a mapping of field/ required to the map. - * - * @param field The field to expect - * @param isRequired Whether it's required or not - * - * @return This instance, so that we have a fluent interface - */ - public ExpectedFieldsBuilder put(PropertyDescriptorField field, boolean isRequired) { - requiredFields.put(field, isRequired); - return this; - } - - - /** - * Gets an immutable map containing the fields we've put here. - * - * @return The map of field/ isRequired mappings - */ - public Map get() { - return Collections.unmodifiableMap(requiredFields); - } - - } - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java index 9bd2d8f2da..805b79b01d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringMultiProperty.java @@ -10,6 +10,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion; @@ -30,7 +32,7 @@ public final class StringMultiProperty extends AbstractMultiValueProperty { @Override protected boolean isValueMissing(String value) { - return StringUtil.isMissing(value); + return StringUtils.isEmpty(value); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java index 759bd406db..375892308a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/StringUtil.java @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.apache.commons.lang3.StringUtils; + /** * A number of String-specific utility methods for use by PMD or its IDE * plugins. @@ -100,14 +102,14 @@ public final class StringUtil { /** * Returns true if the value arg is either null, empty, or full of * whitespace characters. More efficient that calling - * (string).trim().length() == 0 + * (string).trim().length() == 0. * - * @param value + * @param value String to test * * @return true if the value is empty, false otherwise. */ public static boolean isEmpty(String value) { - return isMissing(value) || nullSafeIsBlank(value); + return StringUtils.isBlank(value); } @@ -119,41 +121,7 @@ public final class StringUtil { * @return True if the argument is null or the empty string */ public static boolean isMissing(String value) { - - if (value == null || "".equals(value)) { - return true; - } - - return false; - } - - - /** Argument must not be null. */ - private static boolean nullSafeIsBlank(String value) { - for (int i = 0; i < value.length(); i++) { - if (!Character.isWhitespace(value.charAt(i))) { - return false; - } - } - - return true; - } - - - /** - * Returns true if the argument is null or entirely composed of whitespace characters. - * - * @param value String to test - * - * @return True if the argument is null or entirely composed of whitespace characters. - */ - public static boolean isBlank(String value) { - - if (value == null) { - return true; - } - - return nullSafeIsBlank(value); + return StringUtils.isEmpty(value); } From 31ed6fd5651820f2223f04ee41f567c20bbb33a4 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Sat, 15 Jul 2017 16:41:38 +0200 Subject: [PATCH 49/53] Removed overloads of setProperty --- .../pmd/AbstractPropertySource.java | 18 ++----------- .../net/sourceforge/pmd/PropertySource.java | 27 ++----------------- .../pmd/lang/rule/AbstractDelegateRule.java | 16 ++--------- 3 files changed, 6 insertions(+), 55 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java index b6b297e3b8..da1ccf2127 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertySource.java @@ -133,23 +133,9 @@ public abstract class AbstractPropertySource implements PropertySource { @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value) { + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V... values) { checkValidPropertyDescriptor(propertyDescriptor); - propertyValuesByDescriptor.put(propertyDescriptor, Collections.singletonList(value)); - } - - - @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2) { - checkValidPropertyDescriptor(propertyDescriptor); - propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList(Arrays.asList(value1, value2))); - } - - - @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values) { - checkValidPropertyDescriptor(propertyDescriptor); - propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList(Arrays.asList(value1, value2, values))); + propertyValuesByDescriptor.put(propertyDescriptor, Collections.unmodifiableList(Arrays.asList(values))); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java index 836d26b328..83001ce51e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertySource.java @@ -66,37 +66,14 @@ public interface PropertySource { void setProperty(PropertyDescriptor propertyDescriptor, T value); - /** - * Sets the value of a multi value property descriptor with only one argument. - * - * @param propertyDescriptor The property descriptor for which to add a value - * @param value Value - * @param The type of the values - */ - void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value); - - - /** - * Sets the value of a multi value property descriptor with two arguments. - * - * @param propertyDescriptor The property descriptor for which to add a value - * @param value1 First value - * @param value2 Second value - * @param The type of the values - */ - void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2); - - /** * Sets the value of a multi value property descriptor with a variable number of arguments. * * @param propertyDescriptor The property descriptor for which to add a value - * @param value1 First value - * @param value2 Second value - * @param values Rest of the values + * @param values Values * @param The type of the values */ - void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values); + void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V... values); /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java index 78727fc8d4..97386fdfe8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractDelegateRule.java @@ -209,20 +209,8 @@ public abstract class AbstractDelegateRule implements Rule { @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value) { - rule.setProperty(propertyDescriptor, value); - } - - - @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2) { - rule.setProperty(propertyDescriptor, value1, value2); - } - - - @Override - public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V value1, V value2, V... values) { - rule.setProperty(propertyDescriptor, value1, value2, values); + public void setProperty(MultiValuePropertyDescriptor propertyDescriptor, V... values) { + rule.setProperty(propertyDescriptor, values); } From ca41c6737159ebb6fc8d2cd06125631dc8807ed3 Mon Sep 17 00:00:00 2001 From: oowekyala Date: Sat, 15 Jul 2017 16:50:46 +0200 Subject: [PATCH 50/53] Checkstyle fixes --- .../sourceforge/pmd/AbstractPropertyDescriptorFactory.java | 7 +++---- pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java | 1 - .../src/main/java/net/sourceforge/pmd/RuleSetFactory.java | 5 +++-- .../main/java/net/sourceforge/pmd/RuleSetReferenceId.java | 1 - .../pmd/lang/rule/properties/CharacterProperty.java | 1 - .../pmd/lang/rule/properties/DoubleProperty.java | 1 - .../pmd/lang/rule/properties/StringProperty.java | 1 - 7 files changed, 6 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java index 308d47d963..f936168cb5 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/AbstractPropertyDescriptorFactory.java @@ -155,8 +155,7 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe * @return True if the value must be considered missing, false otherwise */ protected boolean isValueMissing(String value) { - // return StringUtil.isEmpty(value); - return false; + return StringUtils.isBlank(value); } @@ -296,13 +295,13 @@ public abstract class AbstractPropertyDescriptorFactory implements PropertyDe * Returns a map describing which fields are required to build a property using this factory. The parameters are * added to the {@link PropertyDescriptor#CORE_EXPECTED_FIELDS}, which are required for all descriptors. * - * @param otherKeys Additional keys + * @param otherKeys Additional keys * @param otherValues Whether the corresponding keys are required or not * * @return The complete map of expected fields. */ static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, - Boolean[] otherValues) { + Boolean[] otherValues) { Map largerMap = new HashMap<>( otherKeys.length + CORE_EXPECTED_FIELDS.size()); largerMap.putAll(CORE_EXPECTED_FIELDS); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java index c5e25f052b..790a2cd8bb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSet.java @@ -26,7 +26,6 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.util.CollectionUtil; -import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.filter.Filter; import net.sourceforge.pmd.util.filter.Filters; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index a79c98f6f5..79026d54a7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -845,8 +845,9 @@ public class RuleSetFactory { // populate a map of values for an individual descriptor for (PropertyDescriptorField field : valueKeys) { String valueStr = propertyElement.getAttribute(field.attributeName()); - if (valueStr != null) - values.put(field, valueStr); + if (valueStr != null) { + values.put(field, valueStr); + } } if (StringUtils.isBlank(values.get(DEFAULT_VALUE))) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java index b0c033ceea..74a685de99 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetReferenceId.java @@ -16,7 +16,6 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.util.ResourceLoader; -import net.sourceforge.pmd.util.StringUtil; /** * This class is used to parse a RuleSet reference value. Most commonly used for diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java index 7fe83faca1..cc821dc1d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/CharacterProperty.java @@ -12,7 +12,6 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.util.StringUtil; /** * Defines a property type that supports single Character values. diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java index 17f406d631..ad1621d074 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/DoubleProperty.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.rule.properties; import static net.sourceforge.pmd.lang.rule.properties.ValueParser.DOUBLE_PARSER; -import java.util.Arrays; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptorFactory; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java index a02498fdeb..47de949805 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/StringProperty.java @@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.PropertyDescriptorFactory; import net.sourceforge.pmd.PropertyDescriptorField; -import net.sourceforge.pmd.util.StringUtil; /** * Defines a datatype that supports single String values. From fba00843bb523cbeb06157c4793ffc29bd9a6ee7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 16 Jul 2017 21:00:40 +0200 Subject: [PATCH 51/53] [apex] Disable logging of jorje apex lexer Fixes #500 --- .../sourceforge/pmd/cpd/ApexTokenizer.java | 5 ++++ .../pmd/lang/apex/ApexJorjeLogging.java | 25 +++++++++++++++++++ .../pmd/lang/apex/ast/ApexParser.java | 2 ++ src/site/markdown/overview/changelog.md | 1 + 4 files changed, 33 insertions(+) create mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexJorjeLogging.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexTokenizer.java b/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexTokenizer.java index 91ad226773..f83cb65cfa 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexTokenizer.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/cpd/ApexTokenizer.java @@ -11,12 +11,17 @@ import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.Lexer; import org.antlr.runtime.Token; +import net.sourceforge.pmd.lang.apex.ApexJorjeLogging; import net.sourceforge.pmd.lang.ast.TokenMgrError; import apex.jorje.parser.impl.ApexLexer; public class ApexTokenizer implements Tokenizer { + public ApexTokenizer() { + ApexJorjeLogging.disableLogging(); + } + /** * If the properties is false (default), then the case of any token * is ignored. diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexJorjeLogging.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexJorjeLogging.java new file mode 100644 index 0000000000..ae7a827737 --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexJorjeLogging.java @@ -0,0 +1,25 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import apex.jorje.parser.impl.BaseApexLexer; + +public final class ApexJorjeLogging { + private ApexJorjeLogging() { + // this is a utility class + } + + public static void disableLogging() { + // Disable the logging of the ApexLexer, e.g. + // Jul 16, 2017 8:49:56 PM apex.jorje.parser.impl.BaseApexLexer dedupe + // INFORMATION: Deduped array ApexLexer.DFA23_transition. Found 7927114 shorts which is 15MB not + // including array overhead. Removed 7204963 shorts which is 13MB not counting array overhead. Took 18ms. + Logger log = Logger.getLogger(BaseApexLexer.class.getSimpleName()); + log.setLevel(Level.WARNING); + } +} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java index 8a4f4c3aa8..b71f438e12 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java @@ -11,6 +11,7 @@ import java.util.Map; import org.apache.commons.io.IOUtils; +import net.sourceforge.pmd.lang.apex.ApexJorjeLogging; import net.sourceforge.pmd.lang.apex.ApexParserOptions; import net.sourceforge.pmd.lang.ast.ParseException; @@ -29,6 +30,7 @@ public class ApexParser { private String suppressMarker = "NOPMD"; public ApexParser(ApexParserOptions parserOptions) { + ApexJorjeLogging.disableLogging(); this.parserOptions = parserOptions; if (parserOptions.getSuppressMarker() != null) { diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index c8280741ed..d20fb3f177 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -61,6 +61,7 @@ Based on those metrics, rules like "GodClass" detection can be implemented more * apex * [#488](https://github.com/pmd/pmd/pull/488): \[apex] Use Apex lexer for CPD + * [#500](https://github.com/pmd/pmd/issues/500): \[apex] Running through CLI shows jorje optimization messages * cpp * [#448](https://github.com/pmd/pmd/issues/448): \[cpp] Write custom CharStream to handle continuation characters * java From d18b4f99488dfce26a0f980ae2ab1284018bfeb9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 17 Jul 2017 20:23:07 +0200 Subject: [PATCH 52/53] Update changelog, refs #479 --- src/site/markdown/overview/changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index d20fb3f177..1b4e6228ba 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -76,6 +76,9 @@ Based on those metrics, rules like "GodClass" detection can be implemented more * The class `net.sourceforge.pmd.lang.dfa.NodeType` has been converted to an enum. All node types are enum members now instead of int constants. The names for node types are retained. +* The properties API (rule and report properties) have been revamped to be fully typesafe. This is everything + around `net.sourceforge.pmd.PropertyDescriptor`. + ### External Contributions * [#420](https://github.com/pmd/pmd/pull/420): \[java] Fix UR anomaly in assert statements - [Clément Fournier](https://github.com/oowekyala) @@ -84,5 +87,6 @@ Based on those metrics, rules like "GodClass" detection can be implemented more * [#486](https://github.com/pmd/pmd/pull/486): \[java] Add basic method typeresolution - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#492](https://github.com/pmd/pmd/pull/492): \[java] Typeresolution for overloaded methods - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#495](https://github.com/pmd/pmd/pull/495): \[core] Custom rule reinitialization code - [Clément Fournier](https://github.com/oowekyala) +* [#479](https://github.com/pmd/pmd/pull/479): \[core] Typesafe and immutable properties - [Clément Fournier](https://github.com/oowekyala) * [#501](https://github.com/pmd/pmd/pull/501): \[java] Add support for most specific vararg method type resolution - [Bendegúz Nagy](https://github.com/WinterGrascph) From 230994848a74a13c506496562623daeb091aac81 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 17 Jul 2017 20:50:50 +0200 Subject: [PATCH 53/53] Update changelog, refs #487 --- src/site/markdown/overview/changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 1b4e6228ba..cc8e601220 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -66,6 +66,7 @@ Based on those metrics, rules like "GodClass" detection can be implemented more * [#448](https://github.com/pmd/pmd/issues/448): \[cpp] Write custom CharStream to handle continuation characters * java * [#1513](https://sourceforge.net/p/pmd/bugs/1513/): \[java] Remove deprecated rule UseSingleton + * [#487](https://github.com/pmd/pmd/pull/487): \[java] Fix typeresolution for anonymous extending object * java-controversial * [#408](https://github.com/pmd/pmd/issues/408): \[java] DFA not analyzing asserts * java-unnecessarycode