Simplify metrics framework
This commit is contained in:
1 parent
84b59c3350
commit
2123ab3d5d
49 files changed
+357
-543
No files matched your search
@@ -135,6 +135,10 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati
|
||||
* Many methods on the {% jdoc core::lang.ast.Node %} interface
|
||||
and {% jdoc core::lang.ast.AbstractNode %} base class. See their javadoc for details.
|
||||
* {% jdoc !!core::lang.ast.Node#isFindBoundary() %} is deprecated for XPath queries.
|
||||
* Many APIs of {% jdoc_package core::lang.metrics %}, though most of them were internal and
|
||||
probably not used directly outside of PMD. Use {% jdoc core::lang.metrics.MetricsUtil %} as
|
||||
a replacement for the language-specific façades too.
|
||||
* {% jdoc core::lang.ast.QualifiableNode %}, {% jdoc core::lang.ast.QualifiedName %}
|
||||
* pmd-java
|
||||
* {% jdoc java::lang.java.AbstractJavaParser %}
|
||||
* {% jdoc java::lang.java.AbstractJavaHandler %}
|
||||
@@ -162,6 +166,8 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati
|
||||
following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression.
|
||||
* {% jdoc java::lang.java.ast.ASTYieldStatement %} will not implement {% jdoc java::lang.java.ast.TypeNode %}
|
||||
anymore come 7.0.0. Test the type of the expression nested within it.
|
||||
* {% jdoc core::lang.java.metrics.JavaMetrics %}, {% jdoc core::lang.java.metrics.JavaMetricsComputer %},
|
||||
{% jdoc core::lang.java.metrics.JavaMetricsProvider %}
|
||||
|
||||
|
||||
### External Contributions
|
||||
|
||||
@@ -4,11 +4,17 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricKey;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricOptions;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricsUtil;
|
||||
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||
|
||||
/**
|
||||
@@ -16,7 +22,10 @@ import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
*
|
||||
* @deprecated Use {@link MetricsUtil}
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ApexMetrics {
|
||||
|
||||
private static final ApexMetricsFacade FACADE = new ApexMetricsFacade();
|
||||
@@ -32,20 +41,12 @@ public final class ApexMetrics {
|
||||
*
|
||||
* @return The facade
|
||||
*/
|
||||
@Deprecated
|
||||
public static ApexMetricsFacade getFacade() {
|
||||
return FACADE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets the entire data structure.
|
||||
* This needs to be done in case PMD is executed multiple times within one JVM run.
|
||||
*/
|
||||
static void reset() {
|
||||
FACADE.reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the standard value of the metric identified by its code on a class AST node.
|
||||
*
|
||||
@@ -55,7 +56,7 @@ public final class ApexMetrics {
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static double get(MetricKey<ASTUserClassOrInterface<?>> key, ASTUserClass node) {
|
||||
return FACADE.computeForType(key, node, MetricOptions.emptyOptions());
|
||||
return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions());
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +71,7 @@ public final class ApexMetrics {
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static double get(MetricKey<ASTUserClassOrInterface<?>> key, ASTUserClass node, MetricOptions options) {
|
||||
return FACADE.computeForType(key, node, options);
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +84,7 @@ public final class ApexMetrics {
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static double get(MetricKey<ASTMethod> key, ASTMethod node) {
|
||||
return FACADE.computeForOperation(key, node, MetricOptions.emptyOptions());
|
||||
return MetricsUtil.computeMetric(key, node, MetricOptions.emptyOptions());
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +99,7 @@ public final class ApexMetrics {
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static double get(MetricKey<ASTMethod> key, ASTMethod node, MetricOptions options) {
|
||||
return FACADE.computeForOperation(key, node, options);
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,10 +112,10 @@ public final class ApexMetrics {
|
||||
* @param resultOption The result option to use
|
||||
*
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed or {@code option} is
|
||||
* {@code null}
|
||||
* {@code null}
|
||||
*/
|
||||
public static double get(MetricKey<ASTMethod> key, ASTUserClassOrInterface<?> node, ResultOption resultOption) {
|
||||
return FACADE.computeWithResultOption(key, node, MetricOptions.emptyOptions(), resultOption);
|
||||
return MetricsUtil.computeAggregate(key, findOps(node), resultOption);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,12 +129,23 @@ public final class ApexMetrics {
|
||||
* @param resultOption The result option to use
|
||||
*
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed or {@code option} is
|
||||
* {@code null}
|
||||
* {@code null}
|
||||
*/
|
||||
public static double get(MetricKey<ASTMethod> key, ASTUserClassOrInterface<?> node, MetricOptions options,
|
||||
ResultOption resultOption) {
|
||||
return FACADE.computeWithResultOption(key, node, options, resultOption);
|
||||
return MetricsUtil.computeAggregate(key, findOps(node), options, resultOption);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
static List<ASTMethod> findOps(ASTUserClassOrInterface<?> node) {
|
||||
List<ASTMethod> candidates = node.findChildrenOfType(ASTMethod.class);
|
||||
List<ASTMethod> result = new ArrayList<>(candidates);
|
||||
for (ASTMethod method : candidates) {
|
||||
if (method.getImage().matches("(<clinit>|<init>|clone)")) {
|
||||
result.remove(method);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+4
-13
@@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
@@ -21,22 +20,14 @@ public class ApexMetricsComputer extends AbstractMetricsComputer<ASTUserClassOrI
|
||||
|
||||
private static final ApexMetricsComputer INSTANCE = new ApexMetricsComputer();
|
||||
|
||||
@Override
|
||||
protected List<ASTMethod> findOperations(ASTUserClassOrInterface<?> node) {
|
||||
return ApexMetrics.findOps(node);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
public static ApexMetricsComputer getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<ASTMethod> findOperations(ASTUserClassOrInterface<?> node) {
|
||||
List<ASTMethod> candidates = node.findChildrenOfType(ASTMethod.class);
|
||||
List<ASTMethod> result = new ArrayList<>(candidates);
|
||||
for (ASTMethod method : candidates) {
|
||||
if (method.getImage().matches("(<clinit>|<init>|clone)")) {
|
||||
result.remove(method);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -13,18 +13,14 @@ import net.sourceforge.pmd.lang.metrics.MetricsComputer;
|
||||
* Backs the static façade.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @deprecated Not useful anymore
|
||||
*/
|
||||
@Deprecated
|
||||
public class ApexMetricsFacade extends AbstractMetricsFacade<ASTUserClassOrInterface<?>, ASTMethod> {
|
||||
|
||||
private final ApexProjectMemoizer memoizer = new ApexProjectMemoizer();
|
||||
|
||||
|
||||
/** Resets the entire project mirror. Used for tests. */
|
||||
void reset() {
|
||||
memoizer.reset();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected MetricsComputer<ASTUserClassOrInterface<?>, ASTMethod> getLanguageSpecificComputer() {
|
||||
return ApexMetricsComputer.getInstance();
|
||||
|
||||
+6
-6
@@ -18,12 +18,7 @@ public class ApexMetricsProvider extends AbstractLanguageMetricsProvider<ASTUser
|
||||
@SuppressWarnings("unchecked")
|
||||
public ApexMetricsProvider() {
|
||||
// a wild double cast
|
||||
super((Class<ASTUserClassOrInterface<?>>) (Object) ASTUserClassOrInterface.class, ASTMethod.class, ApexMetricsComputer.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
ApexMetrics.reset();
|
||||
super((Class<ASTUserClassOrInterface<?>>) (Object) ASTUserClassOrInterface.class, ASTMethod.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,6 +27,11 @@ public class ApexMetricsProvider extends AbstractLanguageMetricsProvider<ASTUser
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<ASTMethod> findOps(ASTUserClassOrInterface<?> astUserClassOrInterface) {
|
||||
return ApexMetrics.findOps(astUserClassOrInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApexOperationMetricKey> getAvailableOperationMetrics() {
|
||||
return Arrays.asList(ApexOperationMetricKey.values());
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey;
|
||||
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricsUtil;
|
||||
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
@@ -23,7 +24,7 @@ import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
|
||||
/**
|
||||
* Cyclomatic complexity rule using metrics. Uses Wmc to report classes.
|
||||
*
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class CyclomaticComplexityRule extends AbstractApexRule {
|
||||
@@ -69,7 +70,7 @@ public class CyclomaticComplexityRule extends AbstractApexRule {
|
||||
classNames.pop();
|
||||
|
||||
if (ApexClassMetricKey.WMC.supports(node)) {
|
||||
int classWmc = (int) ApexMetrics.get(ApexClassMetricKey.WMC, node);
|
||||
int classWmc = (int) MetricsUtil.computeMetric(ApexClassMetricKey.WMC, node);
|
||||
|
||||
if (classWmc >= getProperty(CLASS_LEVEL_DESCRIPTOR)) {
|
||||
int classHighest = (int) ApexMetrics.get(ApexOperationMetricKey.CYCLO, node, ResultOption.HIGHEST);
|
||||
@@ -89,7 +90,7 @@ public class CyclomaticComplexityRule extends AbstractApexRule {
|
||||
@Override
|
||||
public final Object visit(ASTMethod node, Object data) {
|
||||
|
||||
int cyclo = (int) ApexMetrics.get(ApexOperationMetricKey.CYCLO, node);
|
||||
int cyclo = (int) MetricsUtil.computeMetric(ApexOperationMetricKey.CYCLO, node);
|
||||
if (cyclo >= getProperty(METHOD_LEVEL_DESCRIPTOR)) {
|
||||
String opType = inTrigger ? "trigger"
|
||||
: node.getImage().equals(classNames.peek()) ? "constructor"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.metrics;
|
||||
|
||||
|
||||
/**
|
||||
* Provides a hook into package-private methods of {@code apex.metrics}.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class ApexMetricsHook {
|
||||
|
||||
private ApexMetricsHook() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void reset() {
|
||||
ApexMetrics.reset();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+3
-9
@@ -24,8 +24,8 @@ import net.sourceforge.pmd.lang.apex.metrics.impl.AbstractApexClassMetric;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.impl.AbstractApexOperationMetric;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricKey;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricKeyUtil;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricMemoizer;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricOptions;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricsUtil;
|
||||
|
||||
import apex.jorje.semantic.ast.compilation.Compilation;
|
||||
|
||||
@@ -71,25 +71,19 @@ public class ApexProjectMirrorTest extends ApexParserTestBase {
|
||||
|
||||
|
||||
private List<Integer> visitWith(ApexNode<Compilation> acu, final boolean force) {
|
||||
final ApexProjectMemoizer toplevel = ApexMetrics.getFacade().getLanguageSpecificProjectMemoizer();
|
||||
|
||||
final List<Integer> result = new ArrayList<>();
|
||||
|
||||
acu.jjtAccept(new ApexParserVisitorAdapter() {
|
||||
@Override
|
||||
public Object visit(ASTMethod node, Object data) {
|
||||
MetricMemoizer<ASTMethod> op = toplevel.getOperationMemoizer(node.getQualifiedName());
|
||||
result.add((int) ApexMetricsComputer.getInstance().computeForOperation(opMetricKey, node, force,
|
||||
MetricOptions.emptyOptions(), op));
|
||||
result.add((int) MetricsUtil.computeMetric(opMetricKey, node, MetricOptions.emptyOptions(), force));
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserClass node, Object data) {
|
||||
MetricMemoizer<ASTUserClassOrInterface<?>> clazz = toplevel.getClassMemoizer(node.getQualifiedName());
|
||||
result.add((int) ApexMetricsComputer.getInstance().computeForType(classMetricKey, node, force,
|
||||
MetricOptions.emptyOptions(), clazz));
|
||||
result.add((int) MetricsUtil.computeMetric(classMetricKey, node, MetricOptions.emptyOptions(), force));
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}, null);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.metrics.impl;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsHook;
|
||||
import net.sourceforge.pmd.testframework.SimpleAggregatorTst;
|
||||
|
||||
/**
|
||||
@@ -18,14 +16,6 @@ public class AllMetricsTest extends SimpleAggregatorTst {
|
||||
|
||||
private static final String RULESET = "rulesets/apex/metrics_test.xml";
|
||||
|
||||
|
||||
@Override
|
||||
protected Rule reinitializeRule(Rule rule) {
|
||||
ApexMetricsHook.reset();
|
||||
return rule;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
addRule(RULESET, "CycloTest");
|
||||
|
||||
-7
@@ -4,14 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule.design;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsHook;
|
||||
import net.sourceforge.pmd.testframework.PmdRuleTst;
|
||||
|
||||
public class CyclomaticComplexityTest extends PmdRuleTst {
|
||||
@Override
|
||||
protected Rule reinitializeRule(Rule rule) {
|
||||
ApexMetricsHook.reset();
|
||||
return super.reinitializeRule(rule);
|
||||
}
|
||||
}
|
||||
@@ -373,6 +373,7 @@ public interface Node {
|
||||
* unless it has been set via {@link #setUserData(Object)}.
|
||||
*
|
||||
* @return The user data set on this node.
|
||||
* @deprecated Use {@link #getUserMap()}
|
||||
*/
|
||||
Object getUserData();
|
||||
|
||||
@@ -389,6 +390,7 @@ public interface Node {
|
||||
*
|
||||
* @param userData
|
||||
* The data to set on this node.
|
||||
* @deprecated Use {@link #getUserMap()}
|
||||
*/
|
||||
void setUserData(Object userData);
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ package net.sourceforge.pmd.lang.ast;
|
||||
* Nodes that can be described with a qualified name.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*
|
||||
* @deprecated Not useful anymore
|
||||
*/
|
||||
@Deprecated
|
||||
public interface QualifiableNode extends Node {
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,9 @@ package net.sourceforge.pmd.lang.ast;
|
||||
* from QualifiedName to e.g. JavaQualifiedName.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @deprecated Not useful anymore
|
||||
*/
|
||||
@Deprecated
|
||||
public interface QualifiedName {
|
||||
|
||||
@Override
|
||||
|
||||
+5
-72
@@ -4,7 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
@@ -17,25 +16,16 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractMetricsComputer<T extends QualifiableNode, O extends QualifiableNode>
|
||||
implements MetricsComputer<T, O> {
|
||||
|
||||
@Override
|
||||
public double computeForType(MetricKey<T> key, T node, boolean force,
|
||||
MetricOptions options, MetricMemoizer<T> memoizer) {
|
||||
|
||||
ParameterizedMetricKey<T> paramKey = ParameterizedMetricKey.getInstance(key, options);
|
||||
// if memo.get(key) == null then the metric has never been computed. NaN is a valid value.
|
||||
Double prev = memoizer.getMemo(paramKey);
|
||||
if (!force && prev != null) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
double val = key.getCalculator().computeFor(node, options);
|
||||
memoizer.memoize(paramKey, val);
|
||||
|
||||
return val;
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,46 +33,14 @@ public abstract class AbstractMetricsComputer<T extends QualifiableNode, O exten
|
||||
public double computeForOperation(MetricKey<O> key, O node, boolean force,
|
||||
MetricOptions options, MetricMemoizer<O> memoizer) {
|
||||
|
||||
ParameterizedMetricKey<O> paramKey = ParameterizedMetricKey.getInstance(key, options);
|
||||
Double prev = memoizer.getMemo(paramKey);
|
||||
if (!force && prev != null) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
double val = key.getCalculator().computeFor(node, options);
|
||||
memoizer.memoize(paramKey, val);
|
||||
return val;
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWithResultOption(MetricKey<O> key, T node, boolean force, MetricOptions options,
|
||||
ResultOption option, ProjectMemoizer<T, O> stats) {
|
||||
|
||||
List<O> ops = findOperations(node);
|
||||
|
||||
List<Double> values = new ArrayList<>();
|
||||
for (O op : ops) {
|
||||
if (key.supports(op)) {
|
||||
MetricMemoizer<O> opStats = stats.getOperationMemoizer(op.getQualifiedName());
|
||||
double val = this.computeForOperation(key, op, force, options, opStats);
|
||||
if (val != Double.NaN) {
|
||||
values.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUTURE use streams to do that when we upgrade the compiler to 1.8
|
||||
switch (option) {
|
||||
case SUM:
|
||||
return sum(values);
|
||||
case HIGHEST:
|
||||
return highest(values);
|
||||
case AVERAGE:
|
||||
return average(values);
|
||||
default:
|
||||
return Double.NaN;
|
||||
}
|
||||
return MetricsUtil.computeAggregate(key, findOperations(node), options, option);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,29 +55,4 @@ public abstract class AbstractMetricsComputer<T extends QualifiableNode, O exten
|
||||
protected abstract List<O> findOperations(T node); // TODO:cf this one is computed every time
|
||||
|
||||
|
||||
private static double sum(List<Double> values) {
|
||||
double sum = 0;
|
||||
for (double val : values) {
|
||||
sum += val;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
private static double highest(List<Double> values) {
|
||||
double highest = Double.NEGATIVE_INFINITY;
|
||||
for (double val : values) {
|
||||
if (val > highest) {
|
||||
highest = val;
|
||||
}
|
||||
}
|
||||
return highest == Double.NEGATIVE_INFINITY ? 0 : highest;
|
||||
}
|
||||
|
||||
|
||||
private static double average(List<Double> values) {
|
||||
return sum(values) / values.size();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.metrics;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
|
||||
/**
|
||||
@@ -17,19 +15,18 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractMetricsFacade<T extends QualifiableNode, O extends QualifiableNode> {
|
||||
|
||||
private static final String NULL_KEY_MESSAGE = "The metric key must not be null";
|
||||
private static final String NULL_OPTIONS_MESSAGE = "The metric options must not be null";
|
||||
private static final String NULL_NODE_MESSAGE = "The node must not be null";
|
||||
|
||||
|
||||
/**
|
||||
* Gets the language specific metrics computer.
|
||||
*
|
||||
* @return The metrics computer
|
||||
*/
|
||||
@Deprecated
|
||||
protected abstract MetricsComputer<T, O> getLanguageSpecificComputer();
|
||||
|
||||
|
||||
@@ -38,6 +35,7 @@ public abstract class AbstractMetricsFacade<T extends QualifiableNode, O extends
|
||||
*
|
||||
* @return The project memoizer
|
||||
*/
|
||||
@Deprecated
|
||||
protected abstract ProjectMemoizer<T, O> getLanguageSpecificProjectMemoizer();
|
||||
|
||||
|
||||
@@ -52,20 +50,7 @@ public abstract class AbstractMetricsFacade<T extends QualifiableNode, O extends
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public double computeForType(MetricKey<T> key, T node, MetricOptions options) {
|
||||
|
||||
Objects.requireNonNull(key, NULL_KEY_MESSAGE);
|
||||
Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE);
|
||||
Objects.requireNonNull(node, NULL_NODE_MESSAGE);
|
||||
|
||||
if (!key.supports(node)) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
MetricMemoizer<T> memoizer = getLanguageSpecificProjectMemoizer().getClassMemoizer(node.getQualifiedName());
|
||||
|
||||
return memoizer == null ? Double.NaN
|
||||
: getLanguageSpecificComputer().computeForType(key, node, false,
|
||||
options, memoizer);
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,22 +64,7 @@ public abstract class AbstractMetricsFacade<T extends QualifiableNode, O extends
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public double computeForOperation(MetricKey<O> key, O node, MetricOptions options) {
|
||||
|
||||
Objects.requireNonNull(key, NULL_KEY_MESSAGE);
|
||||
Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE);
|
||||
Objects.requireNonNull(node, NULL_NODE_MESSAGE);
|
||||
|
||||
|
||||
if (!key.supports(node)) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
MetricMemoizer<O> memoizer = getLanguageSpecificProjectMemoizer().getOperationMemoizer(node.getQualifiedName());
|
||||
|
||||
return memoizer == null ? Double.NaN
|
||||
: getLanguageSpecificComputer().computeForOperation(key, node, false,
|
||||
options, memoizer);
|
||||
|
||||
return MetricsUtil.computeMetric(key, node, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,11 +83,6 @@ public abstract class AbstractMetricsFacade<T extends QualifiableNode, O extends
|
||||
public double computeWithResultOption(MetricKey<O> key, T node,
|
||||
MetricOptions options, ResultOption resultOption) {
|
||||
|
||||
Objects.requireNonNull(key, NULL_KEY_MESSAGE);
|
||||
Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE);
|
||||
Objects.requireNonNull(node, NULL_NODE_MESSAGE);
|
||||
Objects.requireNonNull(resultOption, "The result option must not be null");
|
||||
|
||||
return getLanguageSpecificComputer().computeWithResultOption(key, node, false, options,
|
||||
resultOption, getLanguageSpecificProjectMemoizer());
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public class BasicMetricMemoizer<N extends Node> implements MetricMemoizer<N> {
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ import net.sourceforge.pmd.lang.ast.QualifiedName;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
*
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class BasicProjectMemoizer<T extends QualifiableNode, O extends QualifiableNode>
|
||||
implements ProjectMemoizer<T, O> {
|
||||
|
||||
|
||||
@@ -31,12 +31,6 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
@Experimental
|
||||
public interface LanguageMetricsProvider<T extends QualifiableNode, O extends QualifiableNode> {
|
||||
|
||||
/**
|
||||
* Provides a hook to do any initializing before the first file is processed by PMD.
|
||||
* This can be used by the metrics implementations to reset the cache.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Returns a list of all supported type metric keys
|
||||
* for the language.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package net.sourceforge.pmd.lang.metrics;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.util.DataMap.DataKey;
|
||||
|
||||
/**
|
||||
* Key identifying a metric. Such keys <i>must</i> implement the hashCode method. Enums are well fitted to serve as
|
||||
@@ -14,7 +15,7 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
* @author Clément Fournier
|
||||
* @since 5.8.0
|
||||
*/
|
||||
public interface MetricKey<N extends Node> {
|
||||
public interface MetricKey<N extends Node> extends DataKey<MetricKey<N>, Double> {
|
||||
|
||||
/**
|
||||
* Returns the name of the metric.
|
||||
|
||||
@@ -14,7 +14,9 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public interface MetricMemoizer<N extends Node> {
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public interface MetricsComputer<T extends QualifiableNode, O extends QualifiableNode> {
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
|
||||
/**
|
||||
* Utilities to use {@link Metric} instances.
|
||||
*/
|
||||
public final class MetricsUtil {
|
||||
|
||||
static final String NULL_KEY_MESSAGE = "The metric key must not be null";
|
||||
static final String NULL_OPTIONS_MESSAGE = "The metric options must not be null";
|
||||
static final String NULL_NODE_MESSAGE = "The node must not be null";
|
||||
|
||||
private MetricsUtil() {
|
||||
// util class
|
||||
}
|
||||
|
||||
public static <O extends Node> double computeAggregate(MetricKey<? super O> key, Iterable<? extends O> ops, ResultOption resultOption) {
|
||||
return computeAggregate(key, ops, MetricOptions.emptyOptions(), resultOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes an aggregate result for a metric, identified with a {@link ResultOption}.
|
||||
*
|
||||
* @param key The metric to compute
|
||||
* @param ops List of nodes for which to aggregate the metric
|
||||
* @param options The options of the metric
|
||||
* @param resultOption The type of aggregation to perform
|
||||
*
|
||||
* @return The result of the computation, or {@code Double.NaN} if it couldn't be performed
|
||||
*/
|
||||
public static <O extends Node> double computeAggregate(MetricKey<? super O> key, Iterable<? extends O> ops, MetricOptions options, ResultOption resultOption) {
|
||||
|
||||
|
||||
Objects.requireNonNull(key, NULL_KEY_MESSAGE);
|
||||
Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE);
|
||||
Objects.requireNonNull(ops, NULL_NODE_MESSAGE);
|
||||
Objects.requireNonNull(resultOption, "The result option must not be null");
|
||||
|
||||
|
||||
List<Double> values = new ArrayList<>();
|
||||
for (O op : ops) {
|
||||
if (key.supports(op)) {
|
||||
double val = computeMetric(key, op, options);
|
||||
if (!Double.isNaN(val)) {
|
||||
values.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUTURE use streams to do that when we upgrade the compiler to 1.8
|
||||
switch (resultOption) {
|
||||
case SUM:
|
||||
return sum(values);
|
||||
case HIGHEST:
|
||||
return highest(values);
|
||||
case AVERAGE:
|
||||
return average(values);
|
||||
default:
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on a node, with the default options.
|
||||
*
|
||||
* @param key The key identifying the metric to be computed
|
||||
* @param node The node on which to compute the metric
|
||||
*
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static <N extends Node> double computeMetric(MetricKey<? super N> key, N node) {
|
||||
return computeMetric(key, node, MetricOptions.emptyOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on a node, possibly
|
||||
* selecting a variant with the {@code options} parameter.
|
||||
*
|
||||
* @param key The key identifying the metric to be computed
|
||||
* @param node The node on which to compute the metric
|
||||
* @param options The options of the metric
|
||||
*
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static <N extends Node> double computeMetric(MetricKey<? super N> key, N node, MetricOptions options) {
|
||||
return computeMetric(key, node, options, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on a node, possibly
|
||||
* selecting a variant with the {@code options} parameter.
|
||||
*
|
||||
* @param key The key identifying the metric to be computed
|
||||
* @param node The node on which to compute the metric
|
||||
* @param options The options of the metric
|
||||
* @param forceRecompute Force recomputation of the result
|
||||
*
|
||||
* @return The value of the metric, or {@code Double.NaN} if the value couldn't be computed
|
||||
*/
|
||||
public static <N extends Node> double computeMetric(MetricKey<? super N> key, N node, MetricOptions options, boolean forceRecompute) {
|
||||
Objects.requireNonNull(key, NULL_KEY_MESSAGE);
|
||||
Objects.requireNonNull(options, NULL_OPTIONS_MESSAGE);
|
||||
Objects.requireNonNull(node, NULL_NODE_MESSAGE);
|
||||
|
||||
|
||||
if (!key.supports(node)) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
ParameterizedMetricKey<? super N> paramKey = ParameterizedMetricKey.getInstance(key, options);
|
||||
Double prev = node.getUserMap().get(paramKey);
|
||||
if (!forceRecompute && prev != null) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
double val = key.getCalculator().computeFor(node, options);
|
||||
node.getUserMap().set(paramKey, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
private static double sum(List<Double> values) {
|
||||
double sum = 0;
|
||||
for (double val : values) {
|
||||
sum += val;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
private static double highest(List<Double> values) {
|
||||
double highest = Double.NEGATIVE_INFINITY;
|
||||
for (double val : values) {
|
||||
if (val > highest) {
|
||||
highest = val;
|
||||
}
|
||||
}
|
||||
return highest == Double.NEGATIVE_INFINITY ? 0 : highest;
|
||||
}
|
||||
|
||||
|
||||
private static double average(List<Double> values) {
|
||||
return sum(values) / values.size();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -7,7 +7,9 @@ package net.sourceforge.pmd.lang.metrics;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.util.DataMap.DataKey;
|
||||
|
||||
/**
|
||||
* Represents a key parameterized with its options. Used to index memoization maps.
|
||||
@@ -16,8 +18,11 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 5.8.0
|
||||
* @deprecated Is internal API
|
||||
*/
|
||||
public final class ParameterizedMetricKey<N extends Node> {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public final class ParameterizedMetricKey<N extends Node> implements DataKey<ParameterizedMetricKey<N>, Double> {
|
||||
|
||||
private static final Map<ParameterizedMetricKey<?>, ParameterizedMetricKey<?>> POOL = new HashMap<>();
|
||||
|
||||
@@ -65,6 +70,7 @@ public final class ParameterizedMetricKey<N extends Node> {
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingletonClassReturningNewInstance")
|
||||
public static <N extends Node> ParameterizedMetricKey<N> getInstance(MetricKey<N> key, MetricOptions options) {
|
||||
// sharing instances allows using DataMap, which uses reference identity
|
||||
ParameterizedMetricKey<N> tmp = new ParameterizedMetricKey<>(key, options);
|
||||
if (!POOL.containsKey(tmp)) {
|
||||
POOL.put(tmp, tmp);
|
||||
|
||||
@@ -19,7 +19,9 @@ import net.sourceforge.pmd.lang.ast.QualifiedName;
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
* @deprecated See package description
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ProjectMemoizer<T extends QualifiableNode, O extends QualifiableNode> {
|
||||
|
||||
/**
|
||||
|
||||
+9
-9
@@ -5,6 +5,7 @@
|
||||
package net.sourceforge.pmd.lang.metrics.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
@@ -12,7 +13,7 @@ import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricKey;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricOptions;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricsComputer;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricsUtil;
|
||||
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||
|
||||
|
||||
@@ -26,15 +27,12 @@ public abstract class AbstractLanguageMetricsProvider<T extends QualifiableNode,
|
||||
|
||||
private final Class<T> tClass;
|
||||
private final Class<O> oClass;
|
||||
private final MetricsComputer<T, O> myComputer;
|
||||
|
||||
|
||||
protected AbstractLanguageMetricsProvider(Class<T> tClass,
|
||||
Class<O> oClass,
|
||||
MetricsComputer<T, O> computer) {
|
||||
Class<O> oClass) {
|
||||
this.tClass = tClass;
|
||||
this.oClass = oClass;
|
||||
this.myComputer = computer;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,21 +50,23 @@ public abstract class AbstractLanguageMetricsProvider<T extends QualifiableNode,
|
||||
|
||||
@Override
|
||||
public double computeForType(MetricKey<T> key, T node, MetricOptions options) {
|
||||
return myComputer.computeForType(key, node, true, options, DummyMetricMemoizer.<T>getInstance());
|
||||
return MetricsUtil.computeMetric(key, node, options, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double computeForOperation(MetricKey<O> key, O node, MetricOptions options) {
|
||||
return myComputer.computeForOperation(key, node, true, options, DummyMetricMemoizer.<O>getInstance());
|
||||
return MetricsUtil.computeMetric(key, node, options, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWithResultOption(MetricKey<O> key, T node, MetricOptions options, ResultOption option) {
|
||||
return myComputer.computeWithResultOption(key, node, true, options, option, DummyProjectMemoizer.<T, O>getInstance());
|
||||
public double computeWithResultOption(MetricKey<O> key, T node, MetricOptions options, ResultOption resultOption) {
|
||||
return MetricsUtil.computeAggregate(key, findOps(node), options, resultOption);
|
||||
}
|
||||
|
||||
protected abstract List<O> findOps(T t);
|
||||
|
||||
|
||||
@Override
|
||||
public Map<MetricKey<?>, Double> computeAllMetricsFor(Node node) {
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.metrics.internal;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricMemoizer;
|
||||
import net.sourceforge.pmd.lang.metrics.ParameterizedMetricKey;
|
||||
|
||||
|
||||
/**
|
||||
* Memoizes nothing.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.11.0
|
||||
*/
|
||||
public final class DummyMetricMemoizer<N extends Node> implements MetricMemoizer<N> {
|
||||
|
||||
private static final DummyMetricMemoizer<Node> INSTANCE = new DummyMetricMemoizer<>();
|
||||
|
||||
|
||||
private DummyMetricMemoizer() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Double getMemo(ParameterizedMetricKey<N> key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void memoize(ParameterizedMetricKey<N> key, double value) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <N extends Node> DummyMetricMemoizer<N> getInstance() {
|
||||
return (DummyMetricMemoizer<N>) INSTANCE;
|
||||
}
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.metrics.internal;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||
import net.sourceforge.pmd.lang.ast.QualifiedName;
|
||||
import net.sourceforge.pmd.lang.metrics.MetricMemoizer;
|
||||
import net.sourceforge.pmd.lang.metrics.ProjectMemoizer;
|
||||
|
||||
|
||||
/**
|
||||
* Memoizes nothing.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.11.0
|
||||
*/
|
||||
public final class DummyProjectMemoizer<T extends QualifiableNode, O extends QualifiableNode> implements ProjectMemoizer<T, O> {
|
||||
|
||||
private static final DummyProjectMemoizer<? extends QualifiableNode, ? extends QualifiableNode> INSTANCE = new DummyProjectMemoizer<>();
|
||||
|
||||
|
||||
private DummyProjectMemoizer() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MetricMemoizer<O> getOperationMemoizer(QualifiedName qname) {
|
||||
return DummyMetricMemoizer.getInstance();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MetricMemoizer<T> getClassMemoizer(QualifiedName qname) {
|
||||
return DummyMetricMemoizer.getInstance();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends QualifiableNode, O extends QualifiableNode> DummyProjectMemoizer<T, O> getInstance() {
|
||||
return (DummyProjectMemoizer<T, O>) INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Language-independent framework to represent code metrics. If you want
|
||||
* to compute code metrics in your rules, then you should find the language-specific
|
||||
* enums containing {@link net.sourceforge.pmd.lang.metrics.MetricKey}s
|
||||
* in the relevant language modules.
|
||||
*
|
||||
* <p>Metrics are cached by default on the nodes they're computed on.
|
||||
* Many APIs here are deprecated, this is because metrics were previously
|
||||
* cached in big static maps, which is replaced by caching on nodes.
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.metrics;
|
||||
@@ -24,9 +24,6 @@ import net.sourceforge.pmd.SourceCodeProcessor;
|
||||
import net.sourceforge.pmd.benchmark.TimeTracker;
|
||||
import net.sourceforge.pmd.benchmark.TimedOperation;
|
||||
import net.sourceforge.pmd.benchmark.TimedOperationCategory;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
|
||||
@@ -37,7 +34,7 @@ import net.sourceforge.pmd.util.datasource.DataSource;
|
||||
public abstract class AbstractPMDProcessor {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(AbstractPMDProcessor.class.getName());
|
||||
|
||||
|
||||
protected final PMDConfiguration configuration;
|
||||
|
||||
public AbstractPMDProcessor(PMDConfiguration configuration) {
|
||||
@@ -56,7 +53,7 @@ public abstract class AbstractPMDProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @deprecated this method will be removed. It was once used to determine a short filename
|
||||
* for the file being analyzed, so that shortnames can be reported. But the logic has
|
||||
* been moved to the renderers.
|
||||
@@ -78,15 +75,15 @@ public abstract class AbstractPMDProcessor {
|
||||
*/
|
||||
protected RuleSets createRuleSets(RuleSetFactory factory, Report report) {
|
||||
final RuleSets rs = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), factory);
|
||||
|
||||
|
||||
final Set<Rule> brokenRules = removeBrokenRules(rs);
|
||||
for (final Rule rule : brokenRules) {
|
||||
report.addConfigError(new Report.ConfigurationError(rule, rule.dysfunctionReason()));
|
||||
}
|
||||
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove and return the misconfigured rules from the rulesets and log them
|
||||
* for good measure.
|
||||
@@ -117,8 +114,6 @@ public abstract class AbstractPMDProcessor {
|
||||
configuration.getAnalysisCache().checkValidity(rs, configuration.getClassLoader());
|
||||
final SourceCodeProcessor processor = new SourceCodeProcessor(configuration);
|
||||
|
||||
resetMetrics();
|
||||
|
||||
for (final DataSource dataSource : files) {
|
||||
// this is the real, canonical and absolute filename (not shortened)
|
||||
String realFileName = dataSource.getNiceFileName(false, null);
|
||||
@@ -128,7 +123,7 @@ public abstract class AbstractPMDProcessor {
|
||||
|
||||
// render base report first - general errors
|
||||
renderReports(renderers, ctx.getReport());
|
||||
|
||||
|
||||
// then add analysis results per file
|
||||
collectReports(renderers);
|
||||
|
||||
@@ -139,15 +134,6 @@ public abstract class AbstractPMDProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private void resetMetrics() {
|
||||
for (Language language : LanguageRegistry.getLanguages()) {
|
||||
LanguageMetricsProvider<?, ?> languageMetricsProvider = language.getDefaultVersion().getLanguageVersionHandler().getLanguageMetricsProvider();
|
||||
if (languageMetricsProvider != null) {
|
||||
languageMetricsProvider.initialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void runAnalysis(PmdRunnable runnable);
|
||||
|
||||
protected abstract void collectReports(List<Renderer> renderers);
|
||||
|
||||
@@ -8,11 +8,14 @@ import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An opaque, strongly typed heterogeneous data container.
|
||||
* An opaque, strongly typed heterogeneous data container. Data maps can
|
||||
* be set to accept only a certain type of key, with the type parameter.
|
||||
* The key can itself constrain the type of values, using its own type
|
||||
* parameter {@code T}.
|
||||
*
|
||||
* @param <K> Type of keys in this map
|
||||
* @param <K> Type of keys in this map.
|
||||
*/
|
||||
public class DataMap<K> {
|
||||
public final class DataMap<K> {
|
||||
|
||||
private final Map<DataKey<? extends K, ?>, Object> map = new IdentityHashMap<>();
|
||||
|
||||
|
||||
Loaded 30 of 49 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user