Extracted the facade and stripped responsibilities of packageStats

This commit is contained in:
oowekyala
2017-07-27 21:53:32 +02:00
parent edc8d980bb
commit 05f2ffce4c
12 changed files with 165 additions and 143 deletions

View File

@ -19,12 +19,10 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
super(id);
}
public ASTMethodDeclaration(JavaParser p, int id) {
super(p, id);
}
/**
* Accept the visitor. *
*/
@ -33,7 +31,6 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
return visitor.visit(this, data);
}
/**
* Gets the name of the method.
*
@ -47,22 +44,18 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
return null;
}
public String getName() {
return getMethodName();
}
public boolean isSyntacticallyPublic() {
return super.isPublic();
}
public boolean isSyntacticallyAbstract() {
return super.isAbstract();
}
@Override
public boolean isPublic() {
if (isInterfaceMember()) {
@ -71,7 +64,6 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
return super.isPublic();
}
@Override
public boolean isAbstract() {
if (isInterfaceMember()) {
@ -86,17 +78,14 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
return clz != null && clz.isInterface();
}
public boolean isVoid() {
return getResultType().isVoid();
}
public ASTResultType getResultType() {
return getFirstChildOfType(ASTResultType.class);
}
public ASTBlock getBlock() {
for (int i = 0; i < jjtGetNumChildren(); i++) {
Node n = jjtGetChild(i);
@ -107,7 +96,6 @@ public class ASTMethodDeclaration extends AbstractJavaAccessNode implements DFAG
return null;
}
public ASTNameList getThrows() {
int declaratorIndex = -1;
for (int i = 0; i < jjtGetNumChildren(); i++) {

View File

@ -33,9 +33,9 @@ public abstract class AbstractJavaMetric<N extends Node> implements Metric<N> {
/**
* Gives access to the toplevel package stats to metrics without having to pass them as a parameter to metrics.
* Gives access to the toplevel package stats to metrics.
*
* @return The toplevel package stats (singleton contained within {@link JavaMetrics}).
* @return The toplevel package stats (singleton contained within {@link JavaMetricsFacade}).
*/
protected static PackageStats getTopLevelPackageStats() {
return JavaMetrics.getTopLevelPackageStats();

View File

@ -21,8 +21,7 @@ import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
*
* <p>This class does not provide methods to operate directly on its nested classes, but only on itself. To operate on a
* nested class, retrieve the correct ClassStats with {@link PackageStats#getClassStats(JavaQualifiedName, boolean)}
* then
* use the methods of ClassStats. Note that at this level, entities of the data structure do not manipulate
* then use the methods of ClassStats. Note that at this level, entities of the data structure do not manipulate
* QualifiedNames anymore, only Strings.
*
* @author Clément Fournier

View File

@ -20,7 +20,7 @@ import net.sourceforge.pmd.lang.metrics.api.ResultOption;
*/
public final class JavaMetrics {
private static final PackageStats TOP_LEVEL_PACKAGE = new PackageStats();
private static final JavaMetricsFacade FACADE = new JavaMetricsFacade();
private JavaMetrics() { // Cannot be instantiated
@ -33,14 +33,14 @@ public final class JavaMetrics {
*
* @return The top level package stats
*/
/* default */ static PackageStats getTopLevelPackageStats() {
return TOP_LEVEL_PACKAGE;
static PackageStats getTopLevelPackageStats() {
return FACADE.getTopLevelPackageStats();
}
/** Sets whether computations are forced or not. Used for tests. */
/* default */ static void reset() {
TOP_LEVEL_PACKAGE.reset();
/** Resets the entire data structure. Used for tests. */
static void reset() {
FACADE.reset();
}
@ -53,7 +53,7 @@ public final class JavaMetrics {
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public static double get(MetricKey<ASTAnyTypeDeclaration> key, ASTAnyTypeDeclaration node) {
return get(key, node, Version.STANDARD);
return FACADE.computeForType(key, node, Version.STANDARD);
}
@ -68,14 +68,7 @@ public final class JavaMetrics {
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public static double get(MetricKey<ASTAnyTypeDeclaration> key, ASTAnyTypeDeclaration node, MetricVersion version) {
if (!key.supports(node)) {
return Double.NaN;
}
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
return TOP_LEVEL_PACKAGE.compute(key, node, false, safeVersion);
return FACADE.computeForType(key, node, version);
}
@ -88,7 +81,7 @@ public final class JavaMetrics {
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public static double get(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTMethodOrConstructorDeclaration node) {
return get(key, node, Version.STANDARD);
return FACADE.computeForOperation(key, node, Version.STANDARD);
}
@ -102,14 +95,7 @@ public final class JavaMetrics {
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public static double get(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTMethodOrConstructorDeclaration node, MetricVersion version) {
if (!key.supports(node)) {
return Double.NaN;
}
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
return TOP_LEVEL_PACKAGE.compute(key, node, false, safeVersion);
return FACADE.computeForOperation(key, node, version);
}
@ -125,13 +111,13 @@ public final class JavaMetrics {
* {@code null}
*/
public static double get(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTAnyTypeDeclaration node, ResultOption option) {
return get(key, node, Version.STANDARD, option);
return FACADE.computeWithResultOption(key, node, Version.STANDARD, option);
}
/**
* Compute the sum, average, or highest value of the operation metric on all operations of the class node. The
* type of operation is specified by the {@link ResultOption} parameter.
* Compute the sum, average, or highest value of the operation metric on all operations of the class node. The type
* of operation is specified by the {@link ResultOption} parameter.
*
* @param key The key identifying the metric to be computed
* @param node The node on which to compute the metric
@ -143,10 +129,7 @@ public final class JavaMetrics {
*/
public static double get(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTAnyTypeDeclaration node, MetricVersion version,
ResultOption option) {
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
return option == null ? Double.NaN
: TOP_LEVEL_PACKAGE.computeWithResultOption(key, node, false, safeVersion, option);
return FACADE.computeWithResultOption(key, node, version, option);
}
}

View File

@ -10,7 +10,6 @@ import java.util.List;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.metrics.ParameterizedMetricKey;
import net.sourceforge.pmd.lang.metrics.api.MetricKey;
import net.sourceforge.pmd.lang.metrics.api.MetricVersion;
@ -21,11 +20,11 @@ import net.sourceforge.pmd.lang.metrics.api.ResultOption;
*
* @author Clément Fournier
*/
public class MetricsComputer {
public class JavaMetricsComputer {
static final MetricsComputer INSTANCE = new MetricsComputer();
static final JavaMetricsComputer INSTANCE = new JavaMetricsComputer();
private MetricsComputer() {
private JavaMetricsComputer() {
}

View File

@ -0,0 +1,120 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.metrics;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.JavaQualifiedName;
import net.sourceforge.pmd.lang.metrics.api.Metric.Version;
import net.sourceforge.pmd.lang.metrics.api.MetricKey;
import net.sourceforge.pmd.lang.metrics.api.MetricVersion;
import net.sourceforge.pmd.lang.metrics.api.ResultOption;
/**
* Facade of the Java metrics framework.
*
* @author Clément Fournier
*/
class JavaMetricsFacade {
private final PackageStats topLevelPackageStats = new PackageStats();
/**
* Returns the top level package statistics.
*
* @return The top level package stats
*/
PackageStats getTopLevelPackageStats() {
return topLevelPackageStats;
}
/** Resets the entire data structure. Used for tests. */
void reset() {
topLevelPackageStats.reset();
}
/**
* Computes a metric identified by its code on a class AST node, possibly selecting a variant with the {@code
* MetricVersion} parameter.
*
* @param key The key identifying the metric to be computed
* @param node The node on which to compute the metric
* @param version The version of the metric
*
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public double computeForType(MetricKey<ASTAnyTypeDeclaration> key, ASTAnyTypeDeclaration node, MetricVersion version) {
if (!key.supports(node)) {
return Double.NaN;
}
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
ClassStats memoizer = topLevelPackageStats.getClassStats(node.getQualifiedName(), false);
return memoizer == null ? Double.NaN
: JavaMetricsComputer.INSTANCE.compute(key, node, false, safeVersion, memoizer);
}
/**
* Computes a metric identified by its key on a operation AST node.
*
* @param key The key identifying the metric to be computed
* @param node The node on which to compute the metric
* @param version The version of the metric
*
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed
*/
public double computeForOperation(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTMethodOrConstructorDeclaration node,
MetricVersion version) {
if (!key.supports(node)) {
return Double.NaN;
}
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
JavaQualifiedName qname = node.getQualifiedName();
ClassStats container = topLevelPackageStats.getClassStats(qname, false);
OperationStats memoizer = container == null ? null
: container.getOperationStats(qname.getOperation(), node.getSignature());
return memoizer == null ? Double.NaN
: JavaMetricsComputer.INSTANCE.compute(key, node, false, safeVersion, memoizer);
}
/**
* Compute the sum, average, or highest value of the operation metric on all operations of the class node. The type
* of operation is specified by the {@link ResultOption} parameter.
*
* @param key The key identifying the metric to be computed
* @param node The node on which to compute the metric
* @param version The version of the metric
* @param option The result option to use
*
* @return The value of the metric, or {@code Double.NaN} if the value couln't be computed or {@code option} is
* {@code null}
*/
public double computeWithResultOption(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTAnyTypeDeclaration node,
MetricVersion version, ResultOption option) {
if (option == null) {
throw new IllegalArgumentException("The result option may not be null");
}
MetricVersion safeVersion = (version == null) ? Version.STANDARD : version;
ClassStats memoizer = topLevelPackageStats.getClassStats(node.getQualifiedName(), false);
return memoizer == null ? Double.NaN
: JavaMetricsComputer.INSTANCE.computeWithResultOption(key, node, false, safeVersion,
option, memoizer);
}
}

View File

@ -7,15 +7,10 @@ package net.sourceforge.pmd.lang.java.metrics;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.JavaQualifiedName;
import net.sourceforge.pmd.lang.java.metrics.signature.FieldSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.metrics.api.MetricKey;
import net.sourceforge.pmd.lang.metrics.api.MetricVersion;
import net.sourceforge.pmd.lang.metrics.api.ResultOption;
/**
@ -48,21 +43,6 @@ public final class PackageStats {
}
/**
* Returns true if the signature of the operation designated by the qualified name is covered by the mask.
*
* @param qname The operation to test
* @param sigMask The signature mask to use
*
* @return True if the signature of the operation designated by the qualified name is covered by the mask
*/
public boolean hasMatchingSig(JavaQualifiedName qname, OperationSigMask sigMask) {
ClassStats clazz = getClassStats(qname, false);
return clazz != null && clazz.hasMatchingSig(qname.getOperation(), sigMask);
}
/**
* Gets the OperationStats corresponding to the qualified name.
*
@ -158,6 +138,19 @@ public final class PackageStats {
return next;
}
/**
* Returns true if the signature of the operation designated by the qualified name is covered by the mask.
*
* @param qname The operation to test
* @param sigMask The signature mask to use
*
* @return True if the signature of the operation designated by the qualified name is covered by the mask
*/
public boolean hasMatchingSig(JavaQualifiedName qname, OperationSigMask sigMask) {
ClassStats clazz = getClassStats(qname, false);
return clazz != null && clazz.hasMatchingSig(qname.getOperation(), sigMask);
}
/**
* Returns true if the signature of the field designated by its name and the qualified name of its class is covered
@ -174,66 +167,4 @@ public final class PackageStats {
return clazz != null && clazz.hasMatchingSig(fieldName, sigMask);
}
/**
* Computes the value of a metric on a class.
*
* @param key The class metric to compute
* @param node The AST node of the class
* @param force Force the recomputation; if unset, we'll first check for a memoized result
* @param version The version of the metric
*
* @return The result of the computation, or {@code Double.NaN} if it couldn't be performed
*/
/* default */ double compute(MetricKey<ASTAnyTypeDeclaration> key, ASTAnyTypeDeclaration node, boolean force,
MetricVersion version) {
ClassStats container = getClassStats(node.getQualifiedName(), false);
return container == null ? Double.NaN
: MetricsComputer.INSTANCE.compute(key, node, force, version, container);
}
/**
* Computes the value of a metric for an operation.
*
* @param key The operation metric for which to find a memoized result
* @param node The AST node of the operation
* @param force Force the recomputation; if unset, we'll first check for a memoized result
* @param version The version of the metric
*
* @return The result of the computation, or {@code Double.NaN} if it couldn't be performed
*/
/* default */ double compute(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTMethodOrConstructorDeclaration node,
boolean force, MetricVersion version) {
JavaQualifiedName qname = node.getQualifiedName();
ClassStats container = getClassStats(qname, false);
OperationStats memoizer = container == null ? null : container.getOperationStats(qname.getOperation(),
node.getSignature());
return memoizer == null ? Double.NaN
: MetricsComputer.INSTANCE.compute(key, node, force, version, memoizer);
}
/**
* Computes an aggregate result using a ResultOption.
*
* @param key The class metric to compute
* @param node The AST node of the class
* @param force Force the recomputation; if unset, we'll first check for a memoized result
* @param version The version of the metric
* @param option The type of result to compute
*
* @return The result of the computation, or {@code Double.NaN} if it couldn't be performed
*/
/* default */ double computeWithResultOption(MetricKey<ASTMethodOrConstructorDeclaration> key, ASTAnyTypeDeclaration node,
boolean force, MetricVersion version, ResultOption option) {
ClassStats container = getClassStats(node.getQualifiedName(), false);
return container == null ? Double.NaN
: MetricsComputer.INSTANCE.computeWithResultOption(key, node, force, version,
option, container);
}
}

View File

@ -9,9 +9,9 @@ import java.util.List;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.JavaQualifiedName;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature.Visibility;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.metrics.api.MetricVersion;
/**

View File

@ -33,8 +33,8 @@ import net.sourceforge.pmd.lang.java.metrics.impl.AbstractJavaClassMetric;
import net.sourceforge.pmd.lang.java.metrics.impl.AbstractJavaOperationMetric;
import net.sourceforge.pmd.lang.java.metrics.signature.FieldSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaFieldSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.testdata.MetricsVisitorTestData;
import net.sourceforge.pmd.lang.metrics.api.Metric.Version;
import net.sourceforge.pmd.lang.metrics.api.MetricKey;
@ -48,8 +48,8 @@ import net.sourceforge.pmd.lang.metrics.api.MetricVersion;
*/
public class DataStructureTest extends ParserTst {
MetricKey<ASTAnyTypeDeclaration> classMetricKey = JavaClassMetricKey.of(new RandomClassMetric(), null);
MetricKey<ASTMethodOrConstructorDeclaration> opMetricKey = JavaOperationMetricKey.of(new RandomOperationMetric(), null);
private MetricKey<ASTAnyTypeDeclaration> classMetricKey = JavaClassMetricKey.of(new RandomClassMetric(), null);
private MetricKey<ASTMethodOrConstructorDeclaration> opMetricKey = JavaOperationMetricKey.of(new RandomOperationMetric(), null);
private PackageStats pack;
@ -142,14 +142,16 @@ public class DataStructureTest extends ParserTst {
acu.jjtAccept(new JavaParserVisitorReducedAdapter() {
@Override
public Object visit(ASTMethodOrConstructorDeclaration node, Object data) {
result.add((int) toplevel.compute(opMetricKey, node, force, Version.STANDARD));
OperationStats op = toplevel.getOperationStats(node.getQualifiedName(), node.getSignature(), false);
result.add((int) JavaMetricsComputer.INSTANCE.compute(opMetricKey, node, force, Version.STANDARD, op));
return super.visit(node, data);
}
@Override
public Object visit(ASTAnyTypeDeclaration node, Object data) {
result.add((int) toplevel.compute(classMetricKey, node, force, Version.STANDARD));
ClassStats clazz = toplevel.getClassStats(node.getQualifiedName(), false);
result.add((int) JavaMetricsComputer.INSTANCE.compute(classMetricKey, node, force, Version.STANDARD, clazz));
return super.visit(node, data);
}
}, null);

View File

@ -23,9 +23,9 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
import net.sourceforge.pmd.lang.java.ast.JavaQualifiedName;
import net.sourceforge.pmd.lang.java.metrics.signature.FieldSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature.Visibility;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.testdata.MetricsVisitorTestData;
import net.sourceforge.pmd.typeresolution.ClassTypeResolverTest;

View File

@ -19,10 +19,10 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.metrics.signature.FieldSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaFieldSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.signature.SigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature.Visibility;
import net.sourceforge.pmd.lang.java.metrics.signature.OperationSigMask;
import net.sourceforge.pmd.lang.java.metrics.signature.SigMask;
/**
* @author Clément Fournier

View File

@ -24,8 +24,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaFieldSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaOperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature;
import net.sourceforge.pmd.lang.java.metrics.signature.JavaSignature.Visibility;
import net.sourceforge.pmd.lang.java.metrics.testdata.GetterDetection;
import net.sourceforge.pmd.lang.java.metrics.testdata.SetterDetection;