Documentation

This commit is contained in:
Oowekyala
2017-05-06 16:29:44 +02:00
parent a8ff116fb3
commit cb0a30b2e1
15 changed files with 189 additions and 106 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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<>();

View File

@ -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> {

View File

@ -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());
}
}

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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};
}
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;