From f747129e8c878492d970ca3a005c4a2b62d993fa Mon Sep 17 00:00:00 2001 From: oowekyala Date: Thu, 17 Aug 2017 18:36:05 +0200 Subject: [PATCH] Internal builder for MetricOptions --- docs/pages/pmd/devdocs/metrics_howto.md | 13 ++- .../impl/AbstractApexMetricTestRule.java | 2 +- .../pmd/lang/metrics/MetricOptions.java | 84 +++++++++++++++---- .../rule/CyclomaticComplexityRule.java | 6 +- .../metrics/ParameterizedMetricKeyTest.java | 4 +- 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/docs/pages/pmd/devdocs/metrics_howto.md b/docs/pages/pmd/devdocs/metrics_howto.md index c1a7c463e5..16f9e4758e 100644 --- a/docs/pages/pmd/devdocs/metrics_howto.md +++ b/docs/pages/pmd/devdocs/metrics_howto.md @@ -78,7 +78,18 @@ Some metrics define options that can be used to slightly modify the computation. gathered inside an enum in the implementation class of the metric, for example `CycloMetric.CycloOptions`. They're also documented on the [index of metrics](/pmd_java_metrics_index.html). -To use options with a metric, you must first bundle them into a `MetricOptions`. +To use options with a metric, you must first bundle them into a `MetricOptions` object. `MetricOptions` provides the +utility method `toOptions(Collection)` to get a `MetricOptions` bundle. You can then pass +this bundle as a parameter to `JavaMetrics.get`: +```java +public Object visit(ASTMethodDeclaration node, Object data) { + int cyclo = (int) JavaMetrics.get(JavaOperationMetricKey.CYCLO, node, MetricOptions.toOptions()); + if (cyclo > 10) { + // add violation + } + return data; +} +``` diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java index 0ee5987327..30f77bc753 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/metrics/impl/AbstractApexMetricTestRule.java @@ -97,7 +97,7 @@ public abstract class AbstractApexMetricTestRule extends AbstractApexRule { /** * Mappings of labels to options for use in the options property. * - * @return A map of labels to options + * @return A map of labels to options& */ protected Map optionMappings() { return new HashMap<>(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java index 7ac6cdba4b..f470d76780 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/metrics/MetricOptions.java @@ -18,7 +18,7 @@ import java.util.Set; */ public class MetricOptions { - private static final Map POOL = new HashMap<>(); + static final Map POOL = new HashMap<>(); private static final MetricOptions EMPTY_OPTIONS; private Set options; @@ -34,7 +34,7 @@ public class MetricOptions { } - private MetricOptions(Set opts) { + private MetricOptions(Set opts) { switch (opts.size()) { case 0: @@ -94,31 +94,81 @@ public class MetricOptions { * * @return An empty options bundle */ + public static MetricOptions emptyOptions() { return EMPTY_OPTIONS; } /** - * Gets an options bundle from a list of options. + * Gets an options bundle from a collection of options. * - * @param opts The options to build the bundle from + * @param options The options to build the bundle from * * @return An options bundle */ - public static MetricOptions ofOptions(Collection opts) { - MetricOptions version; - if (opts instanceof Set) { - version = new MetricOptions((Set) opts); - } else { - version = new MetricOptions(new HashSet<>(opts)); - } - - if (!POOL.containsKey(version)) { - POOL.put(version, version); - } - - return POOL.get(version); + public static MetricOptions ofOptions(Collection options) { + MetricOptionsBuilder builder = new MetricOptionsBuilder(); + builder.addAll(options); + return builder.build(); } + + /** + * Gets an options bundle from options. + * + * @param option Mandatory first argument + * @param options Rest of the options + * + * @return An options bundle + */ + public static MetricOptions ofOptions(MetricOption option, MetricOption... options) { + MetricOptionsBuilder builder = new MetricOptionsBuilder(); + + builder.add(option); + + for (MetricOption opt : options) { + builder.add(opt); + } + + return builder.build(); + } + + + private static class MetricOptionsBuilder { + + + private Set opts = new HashSet<>(); + + + void add(MetricOption option) { + if (option != null) { + opts.add(option); + } + } + + + void addAll(Collection options) { + if (options != null) { + this.opts.addAll(options); + opts.remove(null); + } + } + + + MetricOptions build() { + if (opts.size() == 0) { + return emptyOptions(); + } + + MetricOptions result = new MetricOptions(opts); + + if (!POOL.containsKey(result)) { + POOL.put(result, result); + } + + return POOL.get(result); + } + + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java index 85b6f53bd2..0253ac4b17 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java @@ -45,7 +45,7 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { } - private static final EnumeratedMultiProperty CYCLO_VERSION_DESCRIPTOR = new EnumeratedMultiProperty<>( + private static final EnumeratedMultiProperty CYCLO_OPTIONS_DESCRIPTOR = new EnumeratedMultiProperty<>( "cycloOptions", "Choose options for the computation of Cyclo", VERSION_MAP, Collections.emptyList(), MetricOption.class, 3.0f); @@ -57,7 +57,7 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { public CyclomaticComplexityRule() { definePropertyDescriptor(CLASS_LEVEL_DESCRIPTOR); definePropertyDescriptor(METHOD_LEVEL_DESCRIPTOR); - definePropertyDescriptor(CYCLO_VERSION_DESCRIPTOR); + definePropertyDescriptor(CYCLO_OPTIONS_DESCRIPTOR); } @@ -66,7 +66,7 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { methodReportLevel = getProperty(METHOD_LEVEL_DESCRIPTOR); classReportLevel = getProperty(CLASS_LEVEL_DESCRIPTOR); if (cycloOptions == null) { - cycloOptions = MetricOptions.ofOptions(getProperty(CYCLO_VERSION_DESCRIPTOR)); + cycloOptions = MetricOptions.ofOptions(getProperty(CYCLO_OPTIONS_DESCRIPTOR)); } super.visit(node, data); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ParameterizedMetricKeyTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ParameterizedMetricKeyTest.java index 94db92e798..38a9525dd4 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ParameterizedMetricKeyTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/ParameterizedMetricKeyTest.java @@ -29,8 +29,8 @@ import net.sourceforge.pmd.lang.metrics.ParameterizedMetricKey; */ public class ParameterizedMetricKeyTest { - private static final MetricOptions DUMMY_VERSION_1 = MetricOptions.ofOptions(Arrays.asList(Options.DUMMY1, Options.DUMMY2)); - private static final MetricOptions DUMMY_VERSION_2 = MetricOptions.ofOptions(Collections.singleton(Options.DUMMY2)); + private static final MetricOptions DUMMY_VERSION_1 = MetricOptions.ofOptions(Options.DUMMY1, Options.DUMMY2); + private static final MetricOptions DUMMY_VERSION_2 = MetricOptions.ofOptions(Options.DUMMY2); @Test public void testIdentity() {