/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.rule.complexity;
import net.sourceforge.pmd.lang.apex.ast.ASTBreakStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTContinueStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTDoLoopStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTIfElseBlockStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
import net.sourceforge.pmd.lang.apex.ast.ASTReturnStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTThrowStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTTryCatchFinallyBlockStatement;
import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement;
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
import net.sourceforge.pmd.lang.apex.rule.AbstractStatisticalApexRule;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.stat.DataPoint;
import net.sourceforge.pmd.util.NumericConstants;
/**
* Abstract superclass for NCSS counting methods. Counts tokens according to
* <a href="http://www.kclee.de/clemens/java/javancss/">JavaNCSS rules</a>.
*
* @author ported from Java original of Jason Bennett
*/
public abstract class AbstractNcssCountRule extends AbstractStatisticalApexRule {
private Class<?> nodeClass;
/**
* Count the nodes of the given type using NCSS rules.
*
* @param nodeClass
* class of node to count
*/
protected AbstractNcssCountRule(Class<?> nodeClass) {
this.nodeClass = nodeClass;
setProperty(MINIMUM_DESCRIPTOR, 1000d);
setProperty(CODECLIMATE_CATEGORIES, new String[] { "Complexity" });
setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 100);
setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false);
}
@Override
public Object visit(ApexNode<?> node, Object data) {
int numNodes = 0;
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
ApexNode<?> n = (ApexNode<?>) node.jjtGetChild(i);
Integer treeSize = (Integer) n.jjtAccept(this, data);
numNodes += treeSize.intValue();
}
if (this.nodeClass.isInstance(node)) {
// Add 1 to account for base node
numNodes++;
DataPoint point = new DataPoint();
point.setNode(node);
point.setScore(1.0 * numNodes);
point.setMessage(getMessage());
addDataPoint(point);
}
return Integer.valueOf(numNodes);
}
/**
* Count the number of children of the given node. Adds one to count the
* node itself.
*
* @param node
* node having children counted
* @param data
* node data
* @return count of the number of children of the node, plus one
*/
protected Integer countNodeChildren(Node node, Object data) {
Integer nodeCount;
int lineCount = 0;
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
nodeCount = (Integer) ((ApexNode<?>) node.jjtGetChild(i)).jjtAccept(this, data);
lineCount += nodeCount.intValue();
}
return ++lineCount;
}
@Override
public Object visit(ASTForLoopStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTForEachStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTDoLoopStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTIfBlockStatement node, Object data) {
Integer lineCount = countNodeChildren(node, data);
return lineCount;
}
@Override
public Object visit(ASTIfElseBlockStatement node, Object data) {
Integer lineCount = countNodeChildren(node, data);
lineCount++;
return lineCount;
}
@Override
public Object visit(ASTWhileLoopStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTBreakStatement node, Object data) {
return NumericConstants.ONE;
}
@Override
public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTContinueStatement node, Object data) {
return NumericConstants.ONE;
}
@Override
public Object visit(ASTReturnStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTThrowStatement node, Object data) {
return countNodeChildren(node, data);
}
@Override
public Object visit(ASTStatement node, Object data) {
return NumericConstants.ONE;
}
@Override
public Object visit(ASTMethodCallExpression node, Object data) {
return NumericConstants.ONE;
}
}