Documentation

This commit is contained in:
oowekyala
2017-06-09 18:40:00 +02:00
parent 0b84366a30
commit 57c6aadd88
6 changed files with 89 additions and 63 deletions

View File

@ -9,12 +9,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents Qualified Names for use within PackageStats
* Represents Qualified Names for use within PackageStats.
* TODO make unit tests once the visitor is working to ensure new implementations won't break it
*/
public class QualifiedName {
/** {@link QualifiedName#parseName(String)} */
/** See {@link QualifiedName#parseName(String)}. */
public static final Pattern FORMAT = Pattern.compile("((\\w+\\.)+|\\.)((\\w+)(\\$\\w+)*)(#(\\w+)\\(((\\w+)(, \\w+)*)?\\))?");
private String[] packages = null; // unnamed package
@ -26,7 +26,7 @@ public class QualifiedName {
}
/**
* Builds the qualified name of a method declaration
* Builds the qualified name of a method declaration.
*
* @param node The method declaration node
*
@ -44,7 +44,7 @@ public class QualifiedName {
}
/**
* Builds the qualified name of a constructor declaration
* Builds the qualified name of a constructor declaration.
*
* @param node The constructor declaration node
*
@ -64,7 +64,7 @@ public class QualifiedName {
/**
* Builds a nested class QName using the QName of its immediate parent
* Builds the qualified name of a nested class using the qualified name of its immediate parent.
*
* @param parent The qname of the immediate parent
* @param className The name of the class
@ -85,7 +85,7 @@ public class QualifiedName {
}
/**
* Builds the QName of an outer (not nested) class.
* Builds the qualified name of an outer (not nested) class.
*
* @param node The class node
*
@ -109,24 +109,24 @@ public class QualifiedName {
}
/**
* Parses a qualified name given in the format defined for this implementation.
* The pattern is available as a static class member.The format
* Parses a qualified name given in the format defined for this implementation. The format
* is described as the following regex pattern :
* <p>
* {@code ((\w+\.)+|\.)(\w+)(\$\w+)*(#(\w+)\(((\w+)(,\w+)*)?\))?}
* <p>
* Notes:
*
* <p>{@code ((\w+\.)+|\.)((\w+)(\$\w+)*)(#(\w+)\(((\w+)(, \w+)*)?\))?}
*
* <p>Notes:
* <ul>
* <li> Group 1 : dot separated packages, or just dot if unnamed package;
* <li> Group 5 : nested classes are separated by a dollar symbol;
* <li> Group 6 : the optional method suffix is separated from the class with a hashtag;
* <li> Group 8 : method arguments. Note the absence of whitespace after commas.
* <li> Group 8 : method arguments. Note the presence of a single space after commas.
* </ul>
* <p>
*
* @param name
* <p>The pattern is available as a static class member.
*
* @return
* @param name The name to parse.
*
* @return A qualified name instance corresponding to the parsed string.
*/
public static QualifiedName parseName(String name) {
QualifiedName qname = new QualifiedName();
@ -137,24 +137,14 @@ public class QualifiedName {
return null;
}
if (".".equals(matcher.group(1))) {
qname.packages = null;
} else {
qname.packages = matcher.group(1).split("\\.");
}
qname.packages = ".".equals(matcher.group(1)) ? null : matcher.group(1).split("\\.");
qname.classes = matcher.group(3).split("\\$");
String op = matcher.group(6);
if (op != null) {
qname.operation = op.substring(1);
}
qname.operation = matcher.group(6) == null ? null : matcher.group(6).substring(1);
return qname;
}
/** Returns a normalized method name (not Java-canonical!) */
/** Returns a normalized method name (not Java-canonical!). */
private static String getOperationName(String methodName, ASTFormalParameters params) {
StringBuilder sb = new StringBuilder();
@ -200,10 +190,12 @@ public class QualifiedName {
return packages;
}
/** Returns the classes. @return The classes. */
public String[] getClasses() {
return classes;
}
/** Returns the operation string. @return The operation string. */
public String getOperation() {
return operation;
}
@ -268,6 +260,4 @@ public class QualifiedName {
return sb.toString();
}
}

View File

@ -30,8 +30,8 @@ public class AtfdMetric extends AbstractMetric implements ClassMetric, Operation
}
OperationSigMask targetOps = new OperationSigMask();
targetOps.setVisibilityMask(Visibility.PUBLIC);
targetOps.setRoleMask(Role.GETTER_OR_SETTER);
targetOps.restrictVisibilitiesTo(Visibility.PUBLIC);
targetOps.restrictRolesTo(Role.GETTER_OR_SETTER);
List<QualifiedName> callQNames = findAllCalls(node);
int foreignCalls = 0;

View File

@ -10,5 +10,21 @@ package net.sourceforge.pmd.lang.java.oom.visitor;
* @author Clément Fournier
*/
public class FieldSigMask extends SigMask<FieldSignature> {
//TODO
private boolean coverFinal = true;
private boolean coverStatic = true;
public FieldSigMask() {
super();
}
/** Include final fields? */
public void coverFinal(boolean coverFinal) {
this.coverFinal = coverFinal;
}
/** Include static fields? */
public void coverStatic(boolean coverStatic) {
this.coverStatic = coverStatic;
}
}

View File

@ -16,29 +16,51 @@ import java.util.Set;
public class OperationSigMask extends SigMask<OperationSignature> {
private Set<OperationSignature.Role> roleMask = new HashSet<>();
private boolean isAbstractIncluded = false;
private boolean coverAbstract = false;
public void setRoleMask(OperationSignature.Role... roles) {
public OperationSigMask() {
super();
coverAllRoles();
}
/**
* Restricts the roles covered by the mask to the parameters.
*
* @param roles The roles to cover.
*/
public void restrictRolesTo(OperationSignature.Role... roles) {
roleMask.clear();
roleMask.addAll(Arrays.asList(roles));
}
public void setAbstractIncluded(boolean isAbstractIncluded) {
this.isAbstractIncluded = isAbstractIncluded;
}
public void setAllRoles() {
/**
* Sets the mask to cover all roles.
*/
public void coverAllRoles() {
roleMask.addAll(Arrays.asList(OperationSignature.Role.values()));
}
public void remove(OperationSignature.Role... roles) {
/**
* Forbid all mentioned roles.
*
* @param roles The roles to forbid.
*/
public void forbid(OperationSignature.Role... roles) {
roleMask.removeAll(Arrays.asList(roles));
}
/**
* Forbid all mentioned visibilities.
*
* @param coverAbstract The visibilities to forbid.
*/
public void coverAbstract(boolean coverAbstract) {
this.coverAbstract = coverAbstract;
}
@Override
public boolean covers(OperationSignature sig) {
return super.covers(sig) && roleMask.contains(sig.role) && (isAbstractIncluded
return super.covers(sig) && roleMask.contains(sig.role) && (coverAbstract
|| !sig.isAbstract);
}
}

View File

@ -9,7 +9,7 @@ import java.util.HashSet;
import java.util.Set;
/**
* Generic signature mask. Masks are initially created empty and cover nothing.
* Generic signature mask. Newly created masks cover everything.
*
* @param <T> The type of Signature to handle.
*
@ -20,12 +20,16 @@ public abstract class SigMask<T extends Signature> {
/** Visibility mask. */
protected Set<Signature.Visibility> visMask = new HashSet<>();
public SigMask(){
coverAllVisibilities();
}
/**
* Clears the visibility mask and adds all parameters.
* Restricts the visibilities covered by the mask to the parameters.
*
* @param visibilities The visibilities to add
* @param visibilities The visibilities to cover.
*/
public void setVisibilityMask(Signature.Visibility... visibilities) {
public void restrictVisibilitiesTo(Signature.Visibility... visibilities) {
visMask.clear();
visMask.addAll(Arrays.asList(visibilities));
}
@ -33,28 +37,27 @@ public abstract class SigMask<T extends Signature> {
/**
* Sets the mask to cover all visibilities.
*/
public void setAllVisibilities() {
public void coverAllVisibilities() {
visMask.addAll(Arrays.asList(Signature.Visibility.values()));
}
/**
* Removes all mentioned visibilities from the mask.
* Forbid all mentioned visibilities.
*
* @param visibilities The visibilities to remove
* @param visibilities The visibilities to forbid.
*/
public void remove(Signature.Visibility... visibilities) {
public void forbid(Signature.Visibility... visibilities) {
visMask.removeAll(Arrays.asList(visibilities));
}
/**
* Returns true if the parameter is covered by this mask.
*
* @param sig The signature to test
* @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

@ -4,10 +4,8 @@
package net.sourceforge.pmd.lang.java.oom;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
@ -15,7 +13,6 @@ import org.junit.Test;
import net.sourceforge.pmd.lang.java.ParserTst;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.oom.visitor.FieldSigMask;
import net.sourceforge.pmd.lang.java.oom.visitor.FieldSignature;
import net.sourceforge.pmd.lang.java.oom.visitor.OperationSigMask;
@ -28,7 +25,7 @@ import net.sourceforge.pmd.lang.java.oom.visitor.SigMask;
public class SigMaskTest extends ParserTst {
/**
* Ensure nothing is covered by an empty mask
* Ensure any method is covered by an empty mask.
*/
@Test
public void testEmptyOperationMask() {
@ -38,17 +35,16 @@ public class SigMaskTest extends ParserTst {
+ "protected void foo(int x){} "
+ "private void rand(){}}";
List<ASTMethodDeclaration> nodes = getOrderedNodes(ASTMethodDeclaration.class, TEST);
SigMask<OperationSignature> mask = new OperationSigMask();
for (ASTMethodDeclaration node : nodes) {
assertFalse(mask.covers(OperationSignature.buildFor(node)));
assertTrue(mask.covers(OperationSignature.buildFor(node)));
}
}
/**
* Ensure nothing is covered by an empty mask
* Ensure any field is covered by an empty mask.
*/
@Test
public void testEmptyFieldMask() {
@ -68,10 +64,9 @@ public class SigMaskTest extends ParserTst {
SigMask<FieldSignature> mask = new FieldSigMask();
for (ASTFieldDeclaration node : nodes) {
assertFalse(mask.covers(FieldSignature.buildFor(node)));
assertTrue(mask.covers(FieldSignature.buildFor(node)));
}
}
}