Abstracted signatures

This commit is contained in:
Clément Fournier
2017-03-27 20:22:41 +02:00
committed by Clément Fournier
parent 7a5894c856
commit 4b671f5d12
12 changed files with 141 additions and 84 deletions

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.List;
@@ -8,42 +9,42 @@ 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.metrics.OperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.OperationSignature.Visibility;
import net.sourceforge.pmd.lang.java.metrics.Signature.Visibility;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public class AtfdMetric extends AbstractMetric implements ClassMetric, MethodMetric {
public class AtfdMetric extends AbstractMetric implements ClassMetric, OperationMetric {
static {
operationMask = new OperationSigMask();
operationMask.setAllVisibility();
operationMask.setAllRoles();
operationMask.remove(Role.CONSTRUCTOR);
}
@Override
public double computeFor(ASTMethodDeclaration node, PackageStats holder) {
if (!checkMaskIsMatching(node)) {
return Double.NaN;
}
OperationSigMask targetOps = new OperationSigMask();
targetOps.setVisibilityMask(Visibility.PUBLIC);
targetOps.setRoleMask(Role.GETTERORSETTER);
targetOps.setRoleMask(Role.GETTER_OR_SETTER);
List<String> callQNames = findAllCalls(node);
int atfd = 0;
int foreignCalls = 0;
for (String name : callQNames) {
if (holder.hasMatchingSig(name, targetOps)) {
atfd++;
foreignCalls++;
}
}
return atfd;
}
return foreignCalls / callQNames.size();
}
@Override
public double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder) {
// TODO

View File

@@ -10,5 +10,5 @@ import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
*
*/
public interface ClassMetric extends Metric {
public double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder);
double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder);
}

View File

@@ -0,0 +1,12 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.metrics;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public class FieldSigMask extends SigMask<FieldSignature> {
}

View File

@@ -3,20 +3,34 @@
*/
package net.sourceforge.pmd.lang.java.metrics;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public class FieldSignature extends Signature {
public final Visibility visibility;
public final boolean isStatic;
public final boolean isFinal;
public final boolean isStatic;
public final boolean isFinal;
public FieldSignature(Visibility visibility, boolean isStatic, boolean isFinal) {
this.visibility = visibility;
super(visibility);
this.isStatic = isStatic;
this.isFinal = isFinal;
}
@Override
public boolean equals(Object o) {
if (o instanceof FieldSignature) {
// TODO
return true;
}
return false;
}
public FieldSignature buildFor(ASTFieldDeclaration node) {
return new FieldSignature(getVisibility(node), node.isStatic(), node.isFinal());
}
}

View File

@@ -1,14 +0,0 @@
/**
*
*/
package net.sourceforge.pmd.lang.java.metrics;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public interface MethodMetric extends Metric {
public double computeFor(ASTMethodDeclaration node, PackageStats holder);
}

View File

@@ -34,19 +34,19 @@ public class Metrics {
}
/* References all available method metrics */
public static enum MethodMetricKey {
public static enum OperationMetricKey {
ATFD(new AtfdMetric()),
// ...
;
/* The object used to calculate the metric */
private final MethodMetric calculator;
private final OperationMetric calculator;
MethodMetricKey(MethodMetric m) {
OperationMetricKey(OperationMetric m) {
calculator = m;
}
MethodMetric getCalculator() {
OperationMetric getCalculator() {
return calculator;
}
}
@@ -63,7 +63,7 @@ public class Metrics {
* Computes a metric identified by its code on the method AST node being
* passed.
*/
public static double get(MethodMetricKey key, ASTMethodDeclaration node) {
public static double get(OperationMetricKey key, ASTMethodDeclaration node) {
return key.getCalculator().computeFor(node, m_holder);
}

View File

@@ -0,0 +1,17 @@
/**
*
*/
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 (clement.fournier@insa-rennes.fr)
*
*/
public interface OperationMetric extends Metric {
double computeFor(ASTMethodDeclaration node, PackageStats holder);
double computeFor(ASTConstructorDeclaration node, PackageStats holder);
}

View File

@@ -9,22 +9,15 @@ import java.util.HashSet;
import java.util.Set;
import net.sourceforge.pmd.lang.java.metrics.OperationSignature.Role;
import net.sourceforge.pmd.lang.java.metrics.Signature.Visibility;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public class OperationSigMask {
public class OperationSigMask extends SigMask<OperationSignature> {
private Set<Visibility> visMask = new HashSet<>();
private Set<Role> roleMask = new HashSet<>();
private boolean isAbstractIncluded = false;
public void setVisibilityMask(Visibility... visibilities) {
visMask.clear();
visMask.addAll(Arrays.asList(visibilities));
}
private Set<Role> roleMask = new HashSet<>();
private boolean isAbstractIncluded = false;
public void setRoleMask(Role... roles) {
roleMask.clear();
@@ -35,25 +28,17 @@ public class OperationSigMask {
this.isAbstractIncluded = isAbstractIncluded;
}
public void setAllVisibility() {
visMask.addAll(Arrays.asList(Visibility.ALL));
}
public void setAllRoles() {
roleMask.addAll(Arrays.asList(Role.ALL));
}
public void remove(Visibility... visibilities) {
visMask.removeAll(Arrays.asList(visibilities));
}
public void remove(Role... roles) {
roleMask.removeAll(Arrays.asList(roles));
}
@Override
public boolean covers(OperationSignature sig) {
return visMask.contains(sig.visibility) && roleMask.contains(sig.role)
&& (isAbstractIncluded || !sig.isAbstract);
return super.covers(sig) && roleMask.contains(sig.role) && (isAbstractIncluded || !sig.isAbstract);
}
}

View File

@@ -10,24 +10,23 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public class OperationSignature extends Signature { // TODO use enums
public class OperationSignature extends Signature {
public final Role role;
public final boolean isAbstract;
public static enum Role {
GETTERORSETTER, CONSTRUCTOR, METHOD, STATIC;
public static final Role[] ALL = new Role[] { GETTERORSETTER, CONSTRUCTOR, METHOD, STATIC };
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC;
public static final Role[] ALL = new Role[] { GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC };
}
public final Visibility visibility;
public final Role role;
public final boolean isAbstract;
public OperationSignature(Visibility visibility, Role role, boolean isAbstract) {
this.visibility = visibility;
super(visibility);
this.role = role;
this.isAbstract = isAbstract;
}
@Override
public boolean equals(Object o) {
if (o instanceof OperationSignature) {
@@ -36,17 +35,17 @@ public class OperationSignature extends Signature { // TODO use enums
}
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.GETTERORSETTER : node.isStatic() ? Role.STATIC : Role.METHOD;
Role role = isGetterOrSetter ? Role.GETTER_OR_SETTER : node.isStatic() ? Role.STATIC : Role.METHOD;
return new OperationSignature(getVisibility(node), role, node.isAbstract());
}
public static OperationSignature buildFor(ASTConstructorDeclaration node) {
return new OperationSignature(getVisibility(node), Role.CONSTRUCTOR, node.isAbstract());
}
}

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.HashMap;
@@ -11,20 +12,20 @@ import java.util.Map;
*
*/
public class PackageStats {
private Map<String, PackageStats> m_subPackages = new HashMap<>();
private Map<String, ClassStats> m_classes = new HashMap<>();
public PackageStats getSubPackage(String[] qname, int index) {
// ...
// recursive navigation method
return null;
}
public ClassStats getClassStats(String name) {
return m_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

@@ -0,0 +1,36 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.metrics;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import net.sourceforge.pmd.lang.java.metrics.Signature.Visibility;
/**
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
*
*/
public abstract class SigMask<T extends Signature> {
protected Set<Visibility> visMask = new HashSet<>();
public void setVisibilityMask(Visibility... visibilities) {
visMask.clear();
visMask.addAll(Arrays.asList(visibilities));
}
public void setAllVisibility() {
visMask.addAll(Arrays.asList(Visibility.ALL));
}
public void remove(Visibility... visibilities) {
visMask.removeAll(Arrays.asList(visibilities));
}
public boolean covers(T sig) {
return visMask.contains(sig.visibility);
}
}

View File

@@ -10,19 +10,25 @@ import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode;
*
*/
public 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 static final Visibility[] ALL = new Visibility[] { PUBLIC, PACKAGE, PROTECTED, PRIVATE };
}
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;
}
public Signature(Visibility visibility) {
this.visibility = visibility;
}
}