Use WMC metric in GodClassRule

This commit is contained in:
Clément Fournier
2017-08-20 00:24:56 +02:00
parent 43bbe83e6b
commit a9be7d4f59
2 changed files with 15 additions and 75 deletions

View File

@ -13,13 +13,7 @@ import java.util.Set;
import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression;
import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression;
import net.sourceforge.pmd.lang.java.ast.ASTForStatement;
import net.sourceforge.pmd.lang.java.ast.ASTIfStatement;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral; import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
@ -27,8 +21,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; import net.sourceforge.pmd.lang.java.metrics.JavaMetrics;
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.metrics.api.JavaClassMetricKey;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.rule.JavaRuleViolation; import net.sourceforge.pmd.lang.java.rule.JavaRuleViolation;
import net.sourceforge.pmd.lang.java.symboltable.ClassScope; import net.sourceforge.pmd.lang.java.symboltable.ClassScope;
@ -67,8 +61,6 @@ public class GodClassRule extends AbstractJavaRule {
*/ */
private static final double ONE_THIRD_THRESHOLD = 1.0 / 3.0; private static final double ONE_THIRD_THRESHOLD = 1.0 / 3.0;
/** The Weighted Method Count metric. */
private int wmcCounter;
/** The Access To Foreign Data metric. */ /** The Access To Foreign Data metric. */
private int atfdCounter; private int atfdCounter;
@ -86,8 +78,9 @@ public class GodClassRule extends AbstractJavaRule {
* visited. Afterwards the metrics are evaluated against fixed thresholds. * visited. Afterwards the metrics are evaluated against fixed thresholds.
*/ */
@Override @Override
public Object visit(ASTCompilationUnit node, Object data) { public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
wmcCounter = 0; int wmc = (int) JavaMetrics.get(JavaClassMetricKey.WMC, node);
atfdCounter = 0; atfdCounter = 0;
methodAttributeAccess = new HashMap<>(); methodAttributeAccess = new HashMap<>();
@ -103,14 +96,13 @@ public class GodClassRule extends AbstractJavaRule {
// .append("TCC=").append(tcc); // .append("TCC=").append(tcc);
// System.out.println(debug.toString()); // System.out.println(debug.toString());
if (wmcCounter >= WMC_VERY_HIGH && atfdCounter > FEW_THRESHOLD && tcc < ONE_THIRD_THRESHOLD) { if (wmc >= WMC_VERY_HIGH && atfdCounter > FEW_THRESHOLD && tcc < ONE_THIRD_THRESHOLD) {
StringBuilder sb = new StringBuilder(); String sb = getMessage() + " (" + "WMC=" + wmc + ", " + "ATFD="
sb.append(getMessage()).append(" (").append("WMC=").append(wmcCounter).append(", ").append("ATFD=") + atfdCounter + ", " + "TCC=" + tcc + ')';
.append(atfdCounter).append(", ").append("TCC=").append(tcc).append(')');
RuleContext ctx = (RuleContext) data; RuleContext ctx = (RuleContext) data;
ctx.getReport().addRuleViolation(new JavaRuleViolation(this, ctx, node, sb.toString())); ctx.getReport().addRuleViolation(new JavaRuleViolation(this, ctx, node, sb));
} }
return result; return result;
} }
@ -137,11 +129,10 @@ public class GodClassRule extends AbstractJavaRule {
* *
* @return * @return
*/ */
private double calculateTotalMethodPairs() { private int calculateTotalMethodPairs() {
int methodCount = methodAttributeAccess.size(); int methodCount = methodAttributeAccess.size();
int n = methodCount - 1; int n = methodCount - 1;
double totalMethodPairs = n * (n + 1) / 2.0; return n * (n + 1) / 2;
return totalMethodPairs;
} }
/** /**
@ -303,8 +294,6 @@ public class GodClassRule extends AbstractJavaRule {
@Override @Override
public Object visit(ASTMethodDeclaration node, Object data) { public Object visit(ASTMethodDeclaration node, Object data) {
wmcCounter++;
currentMethodName = node.getFirstChildOfType(ASTMethodDeclarator.class).getImage(); currentMethodName = node.getFirstChildOfType(ASTMethodDeclarator.class).getImage();
methodAttributeAccess.put(currentMethodName, new HashSet<String>()); methodAttributeAccess.put(currentMethodName, new HashSet<String>());
@ -315,54 +304,4 @@ public class GodClassRule extends AbstractJavaRule {
return result; return result;
} }
@Override
public Object visit(ASTConditionalOrExpression node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTConditionalAndExpression node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTIfStatement node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTWhileStatement node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTForStatement node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTSwitchLabel node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTCatchStatement node, Object data) {
wmcCounter++;
return super.visit(node, data);
}
@Override
public Object visit(ASTConditionalExpression node, Object data) {
if (node.isTernary()) {
wmcCounter++;
}
return super.visit(node, data);
}
} }

View File

@ -1,9 +1,9 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<ruleset name="Design" <ruleset name="Design"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns="http://pmd.sourceforge.net/ruleset/3.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/3.0.0 http://pmd.sourceforge.net/ruleset_3_0_0.xsd">
<description> <description>
The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches
@ -1857,6 +1857,7 @@ public class HelloWorldBean {
language="java" language="java"
since="5.0" since="5.0"
message="Possible God class" message="Possible God class"
metrics="true"
class="net.sourceforge.pmd.lang.java.rule.design.GodClassRule" class="net.sourceforge.pmd.lang.java.rule.design.GodClassRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#godclass"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#godclass">
<description> <description>