diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractMetric.java index 052dff26c4..b69ba02d3f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AbstractMetric.java @@ -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 { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AtfdMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AtfdMetric.java index 70cd7ace4d..e24466f1e4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AtfdMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/AtfdMetric.java @@ -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 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 diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassMetric.java index 4e3c7621f2..e331513a46 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassMetric.java @@ -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); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassStats.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassStats.java index 9d29dec4f4..3b49d384c7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassStats.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/ClassStats.java @@ -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> operations = new HashMap<>(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSigMask.java index 6bb1d90d6a..5c38368fa2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSigMask.java @@ -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 { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSignature.java index 95959c8847..e6db103ae8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/FieldSignature.java @@ -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()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metric.java index ca673ea3d1..b4121f8a71 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metric.java @@ -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 { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metrics.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metrics.java index 92aecd5aa8..bfb1b444fb 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metrics.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Metrics.java @@ -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); - } - } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationMetric.java index 2a23851441..f716aaa57c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationMetric.java @@ -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); - } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSigMask.java index b9d3d15456..d6fb4de1ba 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSigMask.java @@ -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 { - private Set roleMask = new HashSet<>(); - private boolean isAbstractIncluded = false; - + private Set 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)); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSignature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSignature.java index f89f583dde..6359458d3d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSignature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/OperationSignature.java @@ -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}; } - -} \ No newline at end of file + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/PackageStats.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/PackageStats.java index 2a6a81031b..c1757117e7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/PackageStats.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/PackageStats.java @@ -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 diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/SigMask.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/SigMask.java index 6ad5cbe40e..72442865fd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/SigMask.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/SigMask.java @@ -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 { + /** + * Visibility mask + */ protected Set 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); } - + } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Signature.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Signature.java index 7a7591530e..d6a70a6208 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Signature.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/Signature.java @@ -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; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/WmcMetric.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/WmcMetric.java index 68168c0f5d..7143ba455c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/WmcMetric.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/WmcMetric.java @@ -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;