From edf8ce073218108d88f07a591fe3bcb97866b88e Mon Sep 17 00:00:00 2001 From: oowekyala Date: Tue, 25 Jul 2017 11:27:55 +0200 Subject: [PATCH] Factorized enumerated property --- .../sourceforge/pmd/lang/rule/XPathRule.java | 23 ++- .../properties/EnumeratedMultiProperty.java | 156 ++++++++---------- .../rule/properties/EnumeratedProperty.java | 49 ++---- .../modules/EnumeratedPropertyModule.java | 71 ++++++++ .../modules/MethodPropertyModule.java | 9 +- .../modules/PackagedPropertyModule.java | 6 +- .../modules/TypePropertyModule.java | 2 + .../pmd/renderers/CodeClimateRule.java | 52 +++++- .../NonRuleWithAllPropertyTypes.java | 33 +++- .../rule/basic/AvoidUsingHardCodedIPRule.java | 20 ++- 10 files changed, 277 insertions(+), 144 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/EnumeratedPropertyModule.java 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 8c5a92b330..b11d7c72c1 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 @@ -8,7 +8,10 @@ import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0; import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0_COMPATIBILITY; import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_2_0; +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.RuleContext; @@ -23,15 +26,27 @@ 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. + *

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); + + private static final Map XPATH_VERSIONS; + + static { + Map tmp = new HashMap<>(); + tmp.put(XPATH_1_0, XPATH_1_0); + tmp.put(XPATH_1_0_COMPATIBILITY, XPATH_1_0_COMPATIBILITY); + tmp.put(XPATH_2_0, XPATH_2_0); + XPATH_VERSIONS = Collections.unmodifiableMap(tmp); + } + + + 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); + "XPath specification version", XPATH_VERSIONS, XPATH_1_0, String.class, 2.0f); private XPathRuleQuery xpathRuleQuery; @@ -96,7 +111,7 @@ public class XPathRule extends AbstractRule { private boolean init() { if (xpathRuleQuery == null) { String xpath = getProperty(XPATH_DESCRIPTOR); - String version = (String) getProperty(VERSION_DESCRIPTOR); + String version = getProperty(VERSION_DESCRIPTOR); if (XPATH_1_0.equals(version)) { xpathRuleQuery = new JaxenXPathRuleQuery(); } else { 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 f511e94f6e..e4eacba4af 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,13 +5,13 @@ package net.sourceforge.pmd.lang.rule.properties; import java.util.ArrayList; -import java.util.Collections; 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.modules.EnumeratedPropertyModule; import net.sourceforge.pmd.util.CollectionUtil; /** @@ -21,6 +21,7 @@ import net.sourceforge.pmd.util.CollectionUtil; * @param The type of the values * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty @@ -42,22 +43,25 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty } }; // @formatter:on - private final Map choicesByLabel; - private final Map labelsByChoice; - private final Class valueType; + private final EnumeratedPropertyModule module; /** - * Constructor using arrays to define the label-value mappings. The correct construction of the property depends - * on the correct ordering of the arrays. + * 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 choiceIndices The indices of the default values. + * @param choiceIndices Indices of the default values + * @param valueType Type of the values * @param theUIOrder UI order + * + * @deprecated Use {@link #EnumeratedMultiProperty(String, String, Map, List, Class, float)}. Will be removed in + * 7.0.0 */ + @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), @@ -65,16 +69,72 @@ 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 valueType Type of the 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, boolean isDefinedExternally) { super(theName, theDescription, defaultValues, theUIOrder, isDefinedExternally); - checkDefaults(defaultValues, choices); + module = new EnumeratedPropertyModule<>(choices, valueType); + checkDefaults(defaultValues); + } - this.valueType = valueType; - choicesByLabel = Collections.unmodifiableMap(choices); - labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel)); + + @Override + public Map mappings() { + return module.getChoicesByLabel(); // unmodifiable + } + + + @Override + public Class type() { + return module.getValueType(); + } + + + @Override + public String errorFor(List values) { + for (E value : values) { + String error = module.errorFor(value); + if (error != null) { + return error; + } + } + return null; + } + + + @Override + protected E createFrom(String toParse) { + return module.choiceFrom(toParse); + } + + + @Override + public String asString(E item) { + return module.getLabelsByChoice().get(item); + } + + + private void checkDefaults(List defaults) { + for (E elt : defaults) { + module.checkValue(elt); + } } @@ -89,78 +149,4 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty 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"); - } - } - } - - - /** - * 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 - } - - - @Override - public Class type() { - return valueType; - } - - - @Override - public String errorFor(List values) { - for (E value : values) { - if (!labelsByChoice.containsKey(value)) { - return nonLegalValueMsgFor(value); - } - } - return null; - } - - - 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 (label == null || result == null) { - throw new IllegalArgumentException(label); - } - return result; - } - - - @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 0bfc785d87..eadf59eb68 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,24 +4,25 @@ package net.sourceforge.pmd.lang.rule.properties; -import java.util.Collections; import java.util.Enumeration; 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.modules.EnumeratedPropertyModule; import net.sourceforge.pmd.util.CollectionUtil; /** - * 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. + * 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. * *

This property currently doesn't support serialization and cannot be defined in a ruleset file.z * * @param Type of the values * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ public final class EnumeratedProperty extends AbstractSingleValueProperty @@ -46,14 +47,12 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty }; // @formatter:on - private final Map choicesByLabel; - private final Map labelsByChoice; - private final Class valueType; + private final EnumeratedPropertyModule module; /** - * Constructor using arrays to define the label-value mappings. The correct construction of the property depends - * on the correct ordering of the arrays. + * 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 @@ -62,8 +61,9 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty * @param defaultIndex The index of the default value. * @param theUIOrder UI order * - * @deprecated will be removed in 7.0.0. Use a map. + * @deprecated will be removed in 7.0.0. Use {@link #EnumeratedProperty(String, String, Map, Object, Class, float)} */ + @Deprecated public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int defaultIndex, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), @@ -75,9 +75,8 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty 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)); + module = new EnumeratedPropertyModule<>(labelsToChoices, valueType); + module.checkValue(defaultValue); } @@ -98,45 +97,31 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty @Override public Class type() { - return valueType; + return module.getValueType(); } @Override - public String errorFor(Object value) { - return labelsByChoice.containsKey(value) ? null : nonLegalValueMsgFor(value); - } - - - private String nonLegalValueMsgFor(Object value) { - return value + " is not a legal value"; + public String errorFor(E value) { + return module.errorFor(value); } @Override public E createFrom(String value) throws IllegalArgumentException { - return choiceFrom(value); - } - - - private E choiceFrom(String label) { - E result = choicesByLabel.get(label); - if (result != null) { - return result; - } - throw new IllegalArgumentException(label); + return module.choiceFrom(value); } @Override public String asString(E value) { - return labelsByChoice.get(value); + return module.getLabelsByChoice().get(value); } @Override public Map mappings() { - return choicesByLabel; // unmodifiable + return module.getChoicesByLabel(); // unmodifiable } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/EnumeratedPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/EnumeratedPropertyModule.java new file mode 100644 index 0000000000..3dd1cfa101 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/modules/EnumeratedPropertyModule.java @@ -0,0 +1,71 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.properties.modules; + +import java.util.Collections; +import java.util.Map; + +import net.sourceforge.pmd.util.CollectionUtil; + +/** + * Factorises common functionality for enumerated properties. + * + * @author Clément Fournier + */ +public class EnumeratedPropertyModule { + + private final Map choicesByLabel; + private final Map labelsByChoice; + private final Class valueType; + + + public EnumeratedPropertyModule(Map choicesByLabel, Class valueType) { + this.valueType = valueType; + this.choicesByLabel = Collections.unmodifiableMap(choicesByLabel); + this.labelsByChoice = Collections.unmodifiableMap(CollectionUtil.invertedMapFrom(choicesByLabel)); + } + + + public Class getValueType() { + return valueType; + } + + + public Map getLabelsByChoice() { + return labelsByChoice; + } + + + public Map getChoicesByLabel() { + return choicesByLabel; + } + + + private String nonLegalValueMsgFor(E value) { + return value + " is not a legal value"; + } + + + public String errorFor(E value) { + return labelsByChoice.containsKey(value) ? null : nonLegalValueMsgFor(value); + } + + + public E choiceFrom(String label) { + E result = choicesByLabel.get(label); + if (result != null) { + return result; + } + throw new IllegalArgumentException(label); + } + + + public void checkValue(E value) { + if (!choicesByLabel.containsValue(value)) { + throw new IllegalArgumentException("Invalid default value: no mapping to this value"); + } + } + +} 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 1a20efeb4f..b9bfacd70c 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 @@ -11,6 +11,8 @@ import java.util.Map; import net.sourceforge.pmd.util.ClassUtil; /** + * Factorises common functionality for method properties. + * * @author Clément Fournier */ public class MethodPropertyModule extends PackagedPropertyModule { @@ -45,15 +47,14 @@ public class MethodPropertyModule extends PackagedPropertyModule { /** - * Return the value of `method' as a string that can be easily recognized - * and parsed when we see it again. + * 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 + private static String asStringFor(Method method) { + StringBuilder sb = new StringBuilder(); asStringOn(method, sb); return sb.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 index 90699fc097..8f9cb31255 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 @@ -18,6 +18,8 @@ import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.util.StringUtil; /** + * Factorises common functionality for packaged properties. + * * @author Clément Fournier */ public abstract class PackagedPropertyModule { @@ -62,8 +64,8 @@ public abstract class PackagedPropertyModule { /** - * 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. + * 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 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 index 232a20635a..1b396af2ed 100644 --- 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 @@ -7,6 +7,8 @@ package net.sourceforge.pmd.lang.rule.properties.modules; import java.util.List; /** + * Factorises common functionality for type properties. + * * @author Clément Fournier */ public class TypePropertyModule extends PackagedPropertyModule { 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 bc323ddbda..109c3bf025 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 @@ -6,6 +6,11 @@ package net.sourceforge.pmd.renderers; import static net.sourceforge.pmd.renderers.CodeClimateRenderer.REMEDIATION_POINTS_DEFAULT; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.lang.rule.properties.BooleanProperty; import net.sourceforge.pmd.lang.rule.properties.EnumeratedMultiProperty; @@ -17,6 +22,40 @@ import net.sourceforge.pmd.lang.rule.properties.IntegerProperty; * two code climate properties "categories" and "remediation multiplier". */ public interface CodeClimateRule extends Rule { + + /** Represent a CodeClimate category. */ + enum CodeClimateCategory { + BUG_RISK("Bug Risk"), + CLARITY("Clarity"), + COMPATIBILITY("Compatibility"), + COMPLEXITY("Complexity"), + DUPLICATION("Duplication"), + PERFORMANCE("Performance"), + SECURITY("Security"), + STYLE("Style"); + + private String name; + + CodeClimateCategory(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + + /** Makes a map to define the categories for use in the descriptor. */ + private static Map categoryMap() { + Map result = new HashMap<>(); + for (CodeClimateCategory cat : values()) { + result.put(cat.name, cat.name); + } + return result; + } + } + + /** * Defines the code climate categories for which this rule will find * violations. Possible categories are: Bug Risk, Clarity, Compatibility, @@ -26,13 +65,12 @@ public interface CodeClimateRule extends Rule { * "https://github.com/codeclimate/spec/blob/master/SPEC.md#categories">Code * Climate Spec */ - EnumeratedMultiProperty CODECLIMATE_CATEGORIES = new EnumeratedMultiProperty<>("cc_categories", - "Code Climate Categories", - new String[] { "Bug Risk", "Clarity", "Compatibility", "Complexity", "Duplication", "Performance", - "Security", "Style", }, - new String[] { "Bug Risk", "Clarity", "Compatibility", "Complexity", "Duplication", "Performance", - "Security", "Style", }, - new int[] { 7 }, String.class, 1.0f); + EnumeratedMultiProperty CODECLIMATE_CATEGORIES // better would be to use CodeClimateCategory as values but might break the API + = new EnumeratedMultiProperty<>("cc_categories", + "Code Climate Categories", + CodeClimateCategory.categoryMap(), + Collections.singletonList(CodeClimateCategory.STYLE.name), + String.class, 1.0f); /** * Defines the remediation points for this rule. The remediation points are 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 3fbd0a95a0..93a999c144 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 @@ -6,7 +6,10 @@ package net.sourceforge.pmd.properties; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; @@ -73,17 +76,31 @@ public class NonRuleWithAllPropertyTypes extends AbstractRule { new String[] {"java.lang"}, 5.0f); public static final TypeMultiProperty MULTI_TYPE = new TypeMultiProperty("multiType", "Multiple types", 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); - 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}, Class.class, 5.0f); + + private static final Map ENUM_MAPPINGS; + + static { + Map tmp = new HashMap<>(); + tmp.put("String", String.class); + tmp.put("Object", Object.class); + ENUM_MAPPINGS = Collections.unmodifiableMap(tmp); + } + + + public static final EnumeratedProperty ENUM_TYPE = new EnumeratedProperty<>("enumType", "Enumerated choices", ENUM_MAPPINGS, Object.class, Class.class, 5.0f); + + + public static final EnumeratedMultiProperty MULTI_ENUM_TYPE = new EnumeratedMultiProperty<>("multiEnumType", "Multiple enumerated choices", ENUM_MAPPINGS, + Arrays.asList(String.class, Object.class), 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); + + 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); 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 735c9220a3..7412a27237 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 @@ -4,6 +4,10 @@ package net.sourceforge.pmd.lang.java.rule.basic; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,9 +23,21 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule { public static final String IPV6 = "IPv6"; public static final String IPV4_MAPPED_IPV6 = "IPv4 mapped IPv6"; + private static final Map ADDRESSES_TO_CHECK; + + static { + Map tmp = new HashMap<>(); + tmp.put(IPV4, IPV4); + tmp.put(IPV6, IPV6); + tmp.put(IPV4_MAPPED_IPV6, IPV4_MAPPED_IPV6); + ADDRESSES_TO_CHECK = Collections.unmodifiableMap(tmp); + } + + 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 }, String.class, 2.0f); + "checkAddressTypes", "Check for IP address types.", ADDRESSES_TO_CHECK, + Arrays.asList(IPV4, IPV6, IPV4_MAPPED_IPV6), + 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})";