Clover coverage report - PMD - 3.7 Coverage timestamp: Wed May 31 2006 09:25:59 EDT FRAMES NO FRAMES |
file stats: | LOC: | 160 |  | Methods: | 12
| NCLOC: | 129 |  | Classes: | 2
Source file | Conditionals | Statements | Methods | TOTAL
CyclomaticComplexity.java | 64.3% | 89.7% | 91.7% | 83.3% |

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 net.sourceforge.pmd.AbstractRule;
7 |  | import net.sourceforge.pmd.ast.ASTBlockStatement;
8 |  | import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
9 |  | import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
10 |  | import net.sourceforge.pmd.ast.ASTEnumDeclaration;
11 |  | import net.sourceforge.pmd.ast.ASTForStatement;
12 |  | import net.sourceforge.pmd.ast.ASTIfStatement;
13 |  | import net.sourceforge.pmd.ast.ASTMethodDeclaration;
14 |  | import net.sourceforge.pmd.ast.ASTMethodDeclarator;
15 |  | import net.sourceforge.pmd.ast.ASTSwitchLabel;
16 |  | import net.sourceforge.pmd.ast.ASTSwitchStatement;
17 |  | import net.sourceforge.pmd.ast.ASTWhileStatement;
18 |  | import net.sourceforge.pmd.ast.Node;
19 |  | import net.sourceforge.pmd.ast.SimpleNode;
20 |  |
21 |  | import java.util.Stack;
22 |  |
23 |  | /**
24 |  | * @author Donald A. Leckie
25 |  | * @version $Revision: 1.11 $, $Date: 2006/03/29 13:58:50 $
26 |  | * @since January 14, 2003
27 |  | */
28 |  | public class CyclomaticComplexity extends AbstractRule {
29 |  |
30 |  | private static class Entry {
31 |  | private SimpleNode node;
32 |  | private int decisionPoints = 1;
33 |  | public int highestDecisionPoints;
34 |  | public int methodCount;
35 |  |
36 | 8 | private Entry(SimpleNode node) {
37 | 8 | this.node = node;
38 |  | }
39 |  |
40 | 11 | public void bumpDecisionPoints() {
41 | 11 | decisionPoints++;
42 |  | }
43 |  |
44 | 3 | public void bumpDecisionPoints(int size) {
45 | 3 | decisionPoints += size;
46 |  | }
47 |  |
48 | 7 | public int getComplexityAverage() {
49 | 7 | return ((double) methodCount == 0) ? 1 : (int) (Math.rint((double) decisionPoints / (double) methodCount));
50 |  | }
51 |  | }
52 |  |
53 |  | private Stack entryStack = new Stack();
54 |  |
55 | 5 | public Object visit(ASTIfStatement node, Object data) {
56 | 5 | ((Entry) entryStack.peek()).bumpDecisionPoints();
57 | 5 | super.visit(node, data);
58 | 5 | return data;
59 |  | }
60 |  |
61 | 1 | public Object visit(ASTForStatement node, Object data) {
62 | 1 | ((Entry) entryStack.peek()).bumpDecisionPoints();
63 | 1 | super.visit(node, data);
64 | 1 | return data;
65 |  | }
66 |  |
67 | 1 | public Object visit(ASTSwitchStatement node, Object data) {
68 | 1 | Entry entry = (Entry) entryStack.peek();
69 | 1 | int childCount = node.jjtGetNumChildren();
70 | 1 | int lastIndex = childCount - 1;
71 | 1 | for (int n = 0; n < lastIndex; n++) {
72 | 12 | Node childNode = node.jjtGetChild(n);
73 | 12 | if (childNode instanceof ASTSwitchLabel) {
74 | 4 | childNode = node.jjtGetChild(n + 1);
75 | 4 | if (childNode instanceof ASTBlockStatement) {
76 | 4 | entry.bumpDecisionPoints();
77 |  | }
78 |  | }
79 |  | }
80 | 1 | super.visit(node, data);
81 | 1 | return data;
82 |  | }
83 |  |
84 | 1 | public Object visit(ASTWhileStatement node, Object data) {
85 | 1 | ((Entry) entryStack.peek()).bumpDecisionPoints();
86 | 1 | super.visit(node, data);
87 | 1 | return data;
88 |  | }
89 |  |
90 | 4 | public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
91 | 4 | if (node.isInterface()) {
92 | 0 | return data;
93 |  | }
94 |  |
95 | 4 | entryStack.push(new Entry(node));
96 | 4 | super.visit(node, data);
97 | 4 | Entry classEntry = (Entry) entryStack.pop();
98 | 4 | if ((classEntry.getComplexityAverage() >= getIntProperty("reportLevel")) || (classEntry.highestDecisionPoints >= getIntProperty("reportLevel"))) {
99 | 3 | addViolation(data, node, new String[]{"class", node.getImage(), String.valueOf(classEntry.getComplexityAverage()) + " (Highest = " + String.valueOf(classEntry.highestDecisionPoints) + ")"});
100 |  | }
101 | 4 | return data;
102 |  | }
103 |  |
104 | 3 | public Object visit(ASTMethodDeclaration node, Object data) {
105 | 3 | entryStack.push(new Entry(node));
106 | 3 | super.visit(node, data);
107 | 3 | Entry methodEntry = (Entry) entryStack.pop();
108 | 3 | int methodDecisionPoints = methodEntry.decisionPoints;
109 | 3 | Entry classEntry = (Entry) entryStack.peek();
110 | 3 | classEntry.methodCount++;
111 | 3 | classEntry.bumpDecisionPoints(methodDecisionPoints);
112 |  |
113 | 3 | if (methodDecisionPoints > classEntry.highestDecisionPoints) {
114 | 3 | classEntry.highestDecisionPoints = methodDecisionPoints;
115 |  | }
116 |  |
117 | 3 | ASTMethodDeclarator methodDeclarator = null;
118 | 6 | for (int n = 0; n < node.jjtGetNumChildren(); n++) {
119 | 6 | Node childNode = node.jjtGetChild(n);
120 | 6 | if (childNode instanceof ASTMethodDeclarator) {
121 | 3 | methodDeclarator = (ASTMethodDeclarator) childNode;
122 | 3 | break;
123 |  | }
124 |  | }
125 |  |
126 | 3 | if (methodEntry.decisionPoints >= getIntProperty("reportLevel")) {
127 | 2 | addViolation(data, node, new String[]{"method", (methodDeclarator == null) ? "" : methodDeclarator.getImage(), String.valueOf(methodEntry.decisionPoints)});
128 |  | }
129 |  |
130 | 3 | return data;
131 |  | }
132 |  |
133 | 0 | public Object visit(ASTEnumDeclaration node, Object data) {
134 | 0 | entryStack.push(new Entry(node));
135 | 0 | super.visit(node, data);
136 | 0 | Entry classEntry = (Entry) entryStack.pop();
137 | 0 | if ((classEntry.getComplexityAverage() >= getIntProperty("reportLevel")) || (classEntry.highestDecisionPoints >= getIntProperty("reportLevel"))) {
138 | 0 | addViolation(data, node, new String[]{"class", node.getImage(), String.valueOf(classEntry.getComplexityAverage()) + "(Highest = " + String.valueOf(classEntry.highestDecisionPoints) + ")"});
139 |  | }
140 | 0 | return data;
141 |  | }
142 |  |
143 | 1 | public Object visit(ASTConstructorDeclaration node, Object data) {
144 | 1 | entryStack.push(new Entry(node));
145 | 1 | super.visit(node, data);
146 | 1 | Entry constructorEntry = (Entry) entryStack.pop();
147 | 1 | int constructorDecisionPointCount = constructorEntry.decisionPoints;
148 | 1 | Entry classEntry = (Entry) entryStack.peek();
149 | 1 | classEntry.methodCount++;
150 | 1 | classEntry.decisionPoints += constructorDecisionPointCount;
151 | 1 | if (constructorDecisionPointCount > classEntry.highestDecisionPoints) {
152 | 1 | classEntry.highestDecisionPoints = constructorDecisionPointCount;
153 |  | }
154 | 1 | if (constructorEntry.decisionPoints >= getIntProperty("reportLevel")) {
155 | 1 | addViolation(data, node, new String[]{"constructor", classEntry.node.getImage(), String.valueOf(constructorDecisionPointCount)});
156 |  | }
157 | 1 | return data;
158 |  | }
159 |  |
160 |  | }