Documentation
This commit is contained in:
@ -1,15 +1,16 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base class for metrics. Metric objects encapsulate the computational logic required to compute a metric from a PackageStats.
|
||||
*
|
||||
@ -25,7 +26,13 @@ public abstract class AbstractMetric {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isNotSupported(ASTMethodOrConstructorDeclaration node) {
|
||||
/**
|
||||
* Checks if the metric can be computed on that node.
|
||||
*
|
||||
* @param node The node to check for
|
||||
* @return True if the metric can be computed, false otherwise.
|
||||
*/
|
||||
protected boolean isSupported(ASTMethodOrConstructorDeclaration node) {
|
||||
if (node instanceof ASTMethodDeclaration) {
|
||||
return ((ASTMethodDeclaration) node).isAbstract();
|
||||
} else {
|
||||
|
@ -4,34 +4,34 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.metrics.OperationSignature.Role;
|
||||
import net.sourceforge.pmd.lang.java.metrics.Signature.Visibility;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Access to Foreign Data. Quantifies the number of foreign fields accessed directly or via accessors.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class AtfdMetric extends AbstractMetric implements ClassMetric, OperationMetric {
|
||||
|
||||
public AtfdMetric(){
|
||||
|
||||
public AtfdMetric() {
|
||||
isAbstractHandler = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double computeFor(ASTMethodOrConstructorDeclaration node, PackageStats holder) {
|
||||
if (isNotSupported(node)) {
|
||||
if (!isSupported(node)) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
OperationSigMask targetOps = new OperationSigMask();
|
||||
targetOps.setVisibilityMask(Visibility.PUBLIC);
|
||||
targetOps.setRoleMask(Role.GETTER_OR_SETTER);
|
||||
|
||||
|
||||
List<String> callQNames = findAllCalls(node);
|
||||
int foreignCalls = 0;
|
||||
for (String name : callQNames) {
|
||||
@ -42,7 +42,7 @@ public class AtfdMetric extends AbstractMetric implements ClassMetric, Operation
|
||||
|
||||
return foreignCalls / callQNames.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder) {
|
||||
// TODO
|
||||
|
@ -6,8 +6,9 @@ package net.sourceforge.pmd.lang.java.metrics;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Metric that can be computed on a class node.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public interface ClassMetric extends Metric {
|
||||
double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder);
|
||||
|
@ -8,8 +8,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Statistics about a class. Gathers information about the contained members and their signatures, subclasses and
|
||||
* superclasses.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class ClassStats {
|
||||
private Map<OperationSignature, List<String>> operations = new HashMap<>();
|
||||
|
@ -4,8 +4,9 @@
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Signature mask for a field
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class FieldSigMask extends SigMask<FieldSignature> {
|
||||
|
||||
|
@ -29,7 +29,7 @@ public class FieldSignature extends Signature {
|
||||
}
|
||||
|
||||
public FieldSignature buildFor(ASTFieldDeclaration node) {
|
||||
return new FieldSignature(getVisibility(node), node.isStatic(), node.isFinal());
|
||||
return new FieldSignature(Visibility.get(node), node.isStatic(), node.isFinal());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,9 @@
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Umbrella marker interface.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public interface Metric {
|
||||
|
||||
|
@ -4,28 +4,51 @@
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Façade of the Metrics Framework.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class Metrics {
|
||||
|
||||
/* Holds sufficient statistics gathered by the visitor */
|
||||
private static PackageStats m_holder;
|
||||
/**
|
||||
* Holds sufficient statistics gathered by the visitor
|
||||
*/
|
||||
private static PackageStats topPackageStats; // TODO
|
||||
|
||||
/* References all available class metrics */
|
||||
public static enum ClassMetricKey {
|
||||
private Metrics() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on the class AST node being
|
||||
* passed.
|
||||
*/
|
||||
public static double get(ClassMetricKey key, ASTClassOrInterfaceDeclaration node) {
|
||||
return key.getCalculator().computeFor(node, topPackageStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on the operation AST node being
|
||||
* passed.
|
||||
*/
|
||||
public static double get(OperationMetricKey key, ASTMethodOrConstructorDeclaration node) {
|
||||
return key.getCalculator().computeFor(node, topPackageStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keys for class metrics
|
||||
*/
|
||||
public enum ClassMetricKey {
|
||||
ATFD(new AtfdMetric()),
|
||||
// ...
|
||||
WMC(new WmcMetric());
|
||||
|
||||
|
||||
/* The object used to calculate the metric */
|
||||
private final ClassMetric calculator;
|
||||
|
||||
|
||||
ClassMetricKey(ClassMetric m) {
|
||||
calculator = m;
|
||||
}
|
||||
@ -34,16 +57,19 @@ public class Metrics {
|
||||
return calculator;
|
||||
}
|
||||
}
|
||||
|
||||
/* References all available method metrics */
|
||||
public static enum OperationMetricKey {
|
||||
|
||||
/**
|
||||
* Keys for operation metrics
|
||||
*/
|
||||
public enum OperationMetricKey {
|
||||
|
||||
ATFD(new AtfdMetric()),
|
||||
// ...
|
||||
;
|
||||
|
||||
|
||||
/* The object used to calculate the metric */
|
||||
private final OperationMetric calculator;
|
||||
|
||||
|
||||
OperationMetricKey(OperationMetric m) {
|
||||
calculator = m;
|
||||
}
|
||||
@ -53,20 +79,4 @@ public class Metrics {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on the class AST node being
|
||||
* passed.
|
||||
*/
|
||||
public static double get(ClassMetricKey key, ASTClassOrInterfaceDeclaration node) {
|
||||
return key.getCalculator().computeFor(node, m_holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a metric identified by its code on the operation AST node being
|
||||
* passed.
|
||||
*/
|
||||
public static double get(OperationMetricKey key, ASTMethodOrConstructorDeclaration node) {
|
||||
return key.getCalculator().computeFor(node, m_holder);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,16 +3,15 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Metric that can be computed on an operation.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public interface OperationMetric extends Metric {
|
||||
|
||||
double computeFor(ASTMethodOrConstructorDeclaration node, PackageStats holder);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,34 +4,35 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.metrics.OperationSignature.Role;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.metrics.OperationSignature.Role;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Signature mask for an operation.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class OperationSigMask extends SigMask<OperationSignature> {
|
||||
|
||||
private Set<Role> roleMask = new HashSet<>();
|
||||
private boolean isAbstractIncluded = false;
|
||||
|
||||
private Set<Role> roleMask = new HashSet<>();
|
||||
private boolean isAbstractIncluded = false;
|
||||
|
||||
public void setRoleMask(Role... roles) {
|
||||
roleMask.clear();
|
||||
roleMask.addAll(Arrays.asList(roles));
|
||||
}
|
||||
|
||||
|
||||
public void setAbstractIncluded(boolean isAbstractIncluded) {
|
||||
this.isAbstractIncluded = isAbstractIncluded;
|
||||
}
|
||||
|
||||
|
||||
public void setAllRoles() {
|
||||
roleMask.addAll(Arrays.asList(Role.ALL));
|
||||
}
|
||||
|
||||
|
||||
public void remove(Role... roles) {
|
||||
roleMask.removeAll(Arrays.asList(roles));
|
||||
}
|
||||
|
@ -1,32 +1,53 @@
|
||||
/**
|
||||
* 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.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Signature for an operation.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class OperationSignature extends Signature {
|
||||
|
||||
public final Role role;
|
||||
public final boolean isAbstract;
|
||||
|
||||
public static enum Role {
|
||||
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC;
|
||||
public final Role role;
|
||||
|
||||
public final boolean isAbstract;
|
||||
|
||||
public static final Role[] ALL = new Role[] { GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC };
|
||||
}
|
||||
|
||||
public OperationSignature(Visibility visibility, Role role, boolean isAbstract) {
|
||||
super(visibility);
|
||||
this.role = role;
|
||||
this.isAbstract = isAbstract;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an operation signature from a method declaration.
|
||||
*
|
||||
* @param node The method declaration
|
||||
* @return The signature of the parameter
|
||||
*/
|
||||
public static OperationSignature buildFor(ASTMethodDeclaration node) {
|
||||
// TODO better getter or setter detection
|
||||
boolean isGetterOrSetter = node.getName().startsWith("get") || node.getName().startsWith("set");
|
||||
Role role = isGetterOrSetter ? Role.GETTER_OR_SETTER : node.isStatic() ? Role.STATIC : Role.METHOD;
|
||||
|
||||
return new OperationSignature(Visibility.get(node), role, node.isAbstract());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an operation signature from a constructor declaration.
|
||||
*
|
||||
* @param node The constructor declaration
|
||||
* @return The signature of the parameter
|
||||
*/
|
||||
public static OperationSignature buildFor(ASTConstructorDeclaration node) {
|
||||
return new OperationSignature(Visibility.get(node), Role.CONSTRUCTOR, node.isAbstract());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof OperationSignature) {
|
||||
@ -35,17 +56,19 @@ public class OperationSignature extends Signature {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static OperationSignature buildFor(ASTMethodDeclaration node) {
|
||||
// TODO better getter or setter detection
|
||||
boolean isGetterOrSetter = node.getName().startsWith("get") || node.getName().startsWith("set");
|
||||
Role role = isGetterOrSetter ? Role.GETTER_OR_SETTER : node.isStatic() ? Role.STATIC : Role.METHOD;
|
||||
|
||||
return new OperationSignature(getVisibility(node), role, node.isAbstract());
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return role.hashCode() * 2 + visibility.hashCode() * 4 + (isAbstract ? 1 : 0);
|
||||
}
|
||||
|
||||
public static OperationSignature buildFor(ASTConstructorDeclaration node) {
|
||||
return new OperationSignature(getVisibility(node), Role.CONSTRUCTOR, node.isAbstract());
|
||||
|
||||
/**
|
||||
* Role of an operation.
|
||||
*/
|
||||
public enum Role {
|
||||
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC;
|
||||
|
||||
public static final Role[] ALL = new Role[]{GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,8 +8,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Package statistics. This recursive data structure mirrors the package structure of the analysed project and stores
|
||||
* information about the classes and subpackages it contains.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @see ClassStats
|
||||
*/
|
||||
public class PackageStats {
|
||||
|
||||
@ -21,11 +24,11 @@ public class PackageStats {
|
||||
// recursive navigation method
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public ClassStats getClassStats(String name) {
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasMatchingSig(String qname, OperationSigMask sigMask) {
|
||||
// navigate to the class in the tree
|
||||
// return true if the signature of the qualified name is covered by the
|
||||
|
@ -1,6 +1,7 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.java.metrics;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -10,27 +11,50 @@ import java.util.Set;
|
||||
import net.sourceforge.pmd.lang.java.metrics.Signature.Visibility;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Generic signature mask.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public abstract class SigMask<T extends Signature> {
|
||||
/**
|
||||
* Visibility mask
|
||||
*/
|
||||
protected Set<Visibility> visMask = new HashSet<>();
|
||||
|
||||
|
||||
/**
|
||||
* Clears the visibility mask and adds all parameters.
|
||||
*
|
||||
* @param visibilities The visibilities to add
|
||||
*/
|
||||
public void setVisibilityMask(Visibility... visibilities) {
|
||||
visMask.clear();
|
||||
visMask.addAll(Arrays.asList(visibilities));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the mask to cover all visibilities.
|
||||
*/
|
||||
public void setAllVisibility() {
|
||||
visMask.addAll(Arrays.asList(Visibility.ALL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes all mentioned visibilities from the mask.
|
||||
*
|
||||
* @param visibilities The visibilities to remove
|
||||
*/
|
||||
public void remove(Visibility... visibilities) {
|
||||
visMask.removeAll(Arrays.asList(visibilities));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the parameter is covered by this mask.
|
||||
*
|
||||
* @param sig The signature to test
|
||||
* @return True if the parameter is covered by this mask
|
||||
*/
|
||||
public boolean covers(T sig) {
|
||||
return visMask.contains(sig.visibility);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,34 +1,44 @@
|
||||
/**
|
||||
* 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.AbstractJavaAccessNode;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
* Generic signature. This class is extended by classes specific to operations and fields.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public class Signature {
|
||||
public abstract class Signature {
|
||||
|
||||
public final Visibility visibility;
|
||||
|
||||
public static enum Visibility {
|
||||
PUBLIC, PACKAGE, PROTECTED, PRIVATE, UNDEF;
|
||||
|
||||
public static final Visibility[] ALL = new Visibility[] { PUBLIC, PACKAGE, PROTECTED, PRIVATE };
|
||||
|
||||
}
|
||||
|
||||
public Signature(Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public static Visibility getVisibility(AbstractJavaAccessNode node) {
|
||||
return node.isPublic() ? Visibility.PUBLIC
|
||||
: node.isPackagePrivate() ? Visibility.PACKAGE
|
||||
: node.isProtected() ? Visibility.PROTECTED
|
||||
: node.isPrivate() ? Visibility.PRIVATE : Visibility.UNDEF;
|
||||
/**
|
||||
* The visibility of a node.
|
||||
*/
|
||||
public enum Visibility {
|
||||
PUBLIC, PACKAGE, PROTECTED, PRIVATE, UNDEF;
|
||||
|
||||
public static final Visibility[] ALL = new Visibility[]{PUBLIC, PACKAGE, PROTECTED, PRIVATE};
|
||||
|
||||
/**
|
||||
* Returns the Visibility enum key for a node
|
||||
*
|
||||
* @param node A node
|
||||
* @return The visibility enum key for a node
|
||||
*/
|
||||
public static Visibility get(AbstractJavaAccessNode node) {
|
||||
return node.isPublic() ? PUBLIC
|
||||
: node.isPackagePrivate() ? PACKAGE
|
||||
: node.isProtected() ? PROTECTED
|
||||
: node.isPrivate() ? PRIVATE : UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/**
|
||||
*
|
||||
* 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.ASTClassOrInterfaceDeclaration;
|
||||
|
Reference in New Issue
Block a user