Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 237   Methods: 16
NCLOC: 188   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
CyclomaticComplexity.java 62.5% 77.9% 75% 74.1%
coverage coverage
 1    /**
 2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 3    */
 4    package net.sourceforge.pmd.rules;
 5   
 6    import java.util.Stack;
 7   
 8    import net.sourceforge.pmd.AbstractRule;
 9    import net.sourceforge.pmd.ast.ASTBlockStatement;
 10    import net.sourceforge.pmd.ast.ASTCatchStatement;
 11    import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
 12    import net.sourceforge.pmd.ast.ASTCompilationUnit;
 13    import net.sourceforge.pmd.ast.ASTConditionalExpression;
 14    import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
 15    import net.sourceforge.pmd.ast.ASTDoStatement;
 16    import net.sourceforge.pmd.ast.ASTEnumDeclaration;
 17    import net.sourceforge.pmd.ast.ASTExpression;
 18    import net.sourceforge.pmd.ast.ASTForStatement;
 19    import net.sourceforge.pmd.ast.ASTIfStatement;
 20    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 21    import net.sourceforge.pmd.ast.ASTMethodDeclarator;
 22    import net.sourceforge.pmd.ast.ASTSwitchLabel;
 23    import net.sourceforge.pmd.ast.ASTSwitchStatement;
 24    import net.sourceforge.pmd.ast.ASTWhileStatement;
 25    import net.sourceforge.pmd.ast.Node;
 26    import net.sourceforge.pmd.ast.SimpleNode;
 27    import net.sourceforge.pmd.rules.design.NpathComplexity;
 28   
 29    /**
 30    * @author Donald A. Leckie
 31    * @version $Revision: 1.18 $, $Date: 2006/10/16 13:25:23 $
 32    * @since January 14, 2003
 33    */
 34    public class CyclomaticComplexity extends AbstractRule {
 35   
 36    private int reportLevel;
 37   
 38    private static class Entry {
 39    private SimpleNode node;
 40    private int decisionPoints = 1;
 41    public int highestDecisionPoints;
 42    public int methodCount;
 43   
 44  8 private Entry(SimpleNode node) {
 45  8 this.node = node;
 46    }
 47   
 48  3 public void bumpDecisionPoints() {
 49  3 decisionPoints++;
 50    }
 51   
 52  11 public void bumpDecisionPoints(int size) {
 53  11 decisionPoints += size;
 54    }
 55   
 56  7 public int getComplexityAverage() {
 57  7 return ( (double) methodCount == 0 ) ? 1
 58    : (int) ( Math.rint( (double) decisionPoints / (double) methodCount ) );
 59    }
 60    }
 61   
 62    private Stack entryStack = new Stack();
 63   
 64  4 public Object visit(ASTCompilationUnit node, Object data) {
 65  4 reportLevel = getIntProperty( "reportLevel" );
 66  4 super.visit( node, data );
 67  4 return data;
 68    }
 69   
 70  5 public Object visit(ASTIfStatement node, Object data) {
 71  5 int boolCompIf = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 72    // If statement always has a complexity of at least 1
 73  5 boolCompIf++;
 74   
 75  5 ( (Entry) entryStack.peek() ).bumpDecisionPoints( boolCompIf );
 76  5 super.visit( node, data );
 77  5 return data;
 78    }
 79   
 80  0 public Object visit(ASTCatchStatement node, Object data) {
 81  0 ( (Entry) entryStack.peek() ).bumpDecisionPoints();
 82  0 super.visit( node, data );
 83  0 return data;
 84    }
 85   
 86  1 public Object visit(ASTForStatement node, Object data) {
 87  1 int boolCompFor = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 88    // For statement always has a complexity of at least 1
 89  1 boolCompFor++;
 90   
 91  1 ( (Entry) entryStack.peek() ).bumpDecisionPoints( boolCompFor );
 92  1 super.visit( node, data );
 93  1 return data;
 94    }
 95   
 96  0 public Object visit(ASTDoStatement node, Object data) {
 97  0 int boolCompDo = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 98    // Do statement always has a complexity of at least 1
 99  0 boolCompDo++;
 100   
 101  0 ( (Entry) entryStack.peek() ).bumpDecisionPoints( boolCompDo );
 102  0 super.visit( node, data );
 103  0 return data;
 104    }
 105   
 106  1 public Object visit(ASTSwitchStatement node, Object data) {
 107  1 Entry entry = (Entry) entryStack.peek();
 108   
 109  1 int boolCompSwitch = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 110  1 entry.bumpDecisionPoints( boolCompSwitch );
 111   
 112  1 int childCount = node.jjtGetNumChildren();
 113  1 int lastIndex = childCount - 1;
 114  1 for ( int n = 0; n < lastIndex; n++ ) {
 115  12 Node childNode = node.jjtGetChild( n );
 116  12 if ( childNode instanceof ASTSwitchLabel ) {
 117    // default is generally not considered a decision (same as "else")
 118  4 ASTSwitchLabel sl = (ASTSwitchLabel) childNode;
 119  4 if ( !sl.isDefault() ) {
 120  3 childNode = node.jjtGetChild( n + 1 );
 121  3 if ( childNode instanceof ASTBlockStatement ) {
 122  3 entry.bumpDecisionPoints();
 123    }
 124    }
 125    }
 126    }
 127  1 super.visit( node, data );
 128  1 return data;
 129    }
 130   
 131  1 public Object visit(ASTWhileStatement node, Object data) {
 132  1 int boolCompWhile = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 133    // While statement always has a complexity of at least 1
 134  1 boolCompWhile++;
 135   
 136  1 ( (Entry) entryStack.peek() ).bumpDecisionPoints( boolCompWhile );
 137  1 super.visit( node, data );
 138  1 return data;
 139    }
 140   
 141  0 public Object visit(ASTConditionalExpression node, Object data) {
 142  0 if ( node.isTernary() ) {
 143  0 int boolCompTern = NpathComplexity.sumExpressionComplexity( (ASTExpression) node.getFirstChildOfType( ASTExpression.class ) );
 144    // Ternary statement always has a complexity of at least 1
 145  0 boolCompTern++;
 146   
 147  0 ( (Entry) entryStack.peek() ).bumpDecisionPoints( boolCompTern );
 148  0 super.visit( node, data );
 149    }
 150  0 return data;
 151    }
 152   
 153  4 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 154  4 if ( node.isInterface() ) {
 155  0 return data;
 156    }
 157   
 158  4 entryStack.push( new Entry( node ) );
 159  4 super.visit( node, data );
 160  4 Entry classEntry = (Entry) entryStack.pop();
 161  4 if ( ( classEntry.getComplexityAverage() >= reportLevel )
 162    || ( classEntry.highestDecisionPoints >= reportLevel ) ) {
 163  3 addViolation( data, node, new String[] {
 164    "class",
 165    node.getImage(),
 166    classEntry.getComplexityAverage() + " (Highest = "
 167    + classEntry.highestDecisionPoints + ')' } );
 168    }
 169  4 return data;
 170    }
 171   
 172  3 public Object visit(ASTMethodDeclaration node, Object data) {
 173  3 entryStack.push( new Entry( node ) );
 174  3 super.visit( node, data );
 175  3 Entry methodEntry = (Entry) entryStack.pop();
 176  3 int methodDecisionPoints = methodEntry.decisionPoints;
 177  3 Entry classEntry = (Entry) entryStack.peek();
 178  3 classEntry.methodCount++;
 179  3 classEntry.bumpDecisionPoints( methodDecisionPoints );
 180   
 181  3 if ( methodDecisionPoints > classEntry.highestDecisionPoints ) {
 182  3 classEntry.highestDecisionPoints = methodDecisionPoints;
 183    }
 184   
 185  3 ASTMethodDeclarator methodDeclarator = null;
 186  6 for ( int n = 0; n < node.jjtGetNumChildren(); n++ ) {
 187  6 Node childNode = node.jjtGetChild( n );
 188  6 if ( childNode instanceof ASTMethodDeclarator ) {
 189  3 methodDeclarator = (ASTMethodDeclarator) childNode;
 190  3 break;
 191    }
 192    }
 193   
 194  3 if ( methodEntry.decisionPoints >= reportLevel ) {
 195  2 addViolation( data, node, new String[] { "method",
 196  2 ( methodDeclarator == null ) ? "" : methodDeclarator.getImage(),
 197    String.valueOf( methodEntry.decisionPoints ) } );
 198    }
 199   
 200  3 return data;
 201    }
 202   
 203  0 public Object visit(ASTEnumDeclaration node, Object data) {
 204  0 entryStack.push( new Entry( node ) );
 205  0 super.visit( node, data );
 206  0 Entry classEntry = (Entry) entryStack.pop();
 207  0 if ( ( classEntry.getComplexityAverage() >= reportLevel )
 208    || ( classEntry.highestDecisionPoints >= reportLevel ) ) {
 209  0 addViolation( data, node, new String[] {
 210    "class",
 211    node.getImage(),
 212    classEntry.getComplexityAverage() + "(Highest = "
 213    + classEntry.highestDecisionPoints + ')' } );
 214    }
 215  0 return data;
 216    }
 217   
 218  1 public Object visit(ASTConstructorDeclaration node, Object data) {
 219  1 entryStack.push( new Entry( node ) );
 220  1 super.visit( node, data );
 221  1 Entry constructorEntry = (Entry) entryStack.pop();
 222  1 int constructorDecisionPointCount = constructorEntry.decisionPoints;
 223  1 Entry classEntry = (Entry) entryStack.peek();
 224  1 classEntry.methodCount++;
 225  1 classEntry.decisionPoints += constructorDecisionPointCount;
 226  1 if ( constructorDecisionPointCount > classEntry.highestDecisionPoints ) {
 227  1 classEntry.highestDecisionPoints = constructorDecisionPointCount;
 228    }
 229  1 if ( constructorEntry.decisionPoints >= reportLevel ) {
 230  1 addViolation( data, node, new String[] { "constructor",
 231    classEntry.node.getImage(),
 232    String.valueOf( constructorDecisionPointCount ) } );
 233    }
 234  1 return data;
 235    }
 236   
 237    }