| 1 |
|
|
| 2 |
|
|
| 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.ASTCatchStatement; |
| 9 |
|
import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; |
| 10 |
|
import net.sourceforge.pmd.ast.ASTConditionalAndExpression; |
| 11 |
|
import net.sourceforge.pmd.ast.ASTConditionalExpression; |
| 12 |
|
import net.sourceforge.pmd.ast.ASTConditionalOrExpression; |
| 13 |
|
import net.sourceforge.pmd.ast.ASTConstructorDeclaration; |
| 14 |
|
import net.sourceforge.pmd.ast.ASTDoStatement; |
| 15 |
|
import net.sourceforge.pmd.ast.ASTEnumDeclaration; |
| 16 |
|
import net.sourceforge.pmd.ast.ASTForStatement; |
| 17 |
|
import net.sourceforge.pmd.ast.ASTIfStatement; |
| 18 |
|
import net.sourceforge.pmd.ast.ASTMethodDeclaration; |
| 19 |
|
import net.sourceforge.pmd.ast.ASTMethodDeclarator; |
| 20 |
|
import net.sourceforge.pmd.ast.ASTSwitchLabel; |
| 21 |
|
import net.sourceforge.pmd.ast.ASTSwitchStatement; |
| 22 |
|
import net.sourceforge.pmd.ast.ASTWhileStatement; |
| 23 |
|
import net.sourceforge.pmd.ast.Node; |
| 24 |
|
import net.sourceforge.pmd.ast.SimpleNode; |
| 25 |
|
|
| 26 |
|
import java.util.Stack; |
| 27 |
|
|
| 28 |
|
|
| 29 |
|
@author |
| 30 |
|
@version |
| 31 |
|
@since |
| 32 |
|
|
|
|
|
| 69.7% |
Uncovered Elements: 37 (122) |
Complexity: 29 |
Complexity Density: 0.36 |
|
| 33 |
|
public class CyclomaticComplexity extends AbstractRule { |
| 34 |
|
|
|
|
|
| 90% |
Uncovered Elements: 1 (10) |
Complexity: 5 |
Complexity Density: 1.25 |
|
| 35 |
|
private static class Entry { |
| 36 |
|
private SimpleNode node; |
| 37 |
|
private int decisionPoints = 1; |
| 38 |
|
public int highestDecisionPoints; |
| 39 |
|
public int methodCount; |
| 40 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
| 41 |
8
|
private Entry(SimpleNode node) {... |
| 42 |
8
|
this.node = node; |
| 43 |
|
} |
| 44 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
| 45 |
10
|
public void bumpDecisionPoints() {... |
| 46 |
10
|
decisionPoints++; |
| 47 |
|
} |
| 48 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
| 49 |
3
|
public void bumpDecisionPoints(int size) {... |
| 50 |
3
|
decisionPoints += size; |
| 51 |
|
} |
| 52 |
|
|
|
|
|
| 66.7% |
Uncovered Elements: 1 (3) |
Complexity: 2 |
Complexity Density: 2 |
|
| 53 |
7
|
public int getComplexityAverage() {... |
| 54 |
7
|
return ((double) methodCount == 0) ? 1 : (int) (Math.rint((double) decisionPoints / (double) methodCount)); |
| 55 |
|
} |
| 56 |
|
} |
| 57 |
|
|
| 58 |
|
private Stack entryStack = new Stack(); |
| 59 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 60 |
5
|
public Object visit(ASTIfStatement node, Object data) {... |
| 61 |
5
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 62 |
5
|
super.visit(node, data); |
| 63 |
5
|
return data; |
| 64 |
|
} |
| 65 |
|
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 66 |
0
|
public Object visit(ASTCatchStatement node, Object data) {... |
| 67 |
0
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 68 |
0
|
super.visit(node, data); |
| 69 |
0
|
return data; |
| 70 |
|
} |
| 71 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 72 |
1
|
public Object visit(ASTForStatement node, Object data) {... |
| 73 |
1
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 74 |
1
|
super.visit(node, data); |
| 75 |
1
|
return data; |
| 76 |
|
} |
| 77 |
|
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 78 |
0
|
public Object visit(ASTDoStatement node, Object data) {... |
| 79 |
0
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 80 |
0
|
super.visit(node, data); |
| 81 |
0
|
return data; |
| 82 |
|
} |
| 83 |
|
|
|
|
|
| 95.2% |
Uncovered Elements: 1 (21) |
Complexity: 5 |
Complexity Density: 0.38 |
|
| 84 |
1
|
public Object visit(ASTSwitchStatement node, Object data) {... |
| 85 |
1
|
Entry entry = (Entry) entryStack.peek(); |
| 86 |
1
|
int childCount = node.jjtGetNumChildren(); |
| 87 |
1
|
int lastIndex = childCount - 1; |
| 88 |
13
|
for (int n = 0; n < lastIndex; n++) { |
| 89 |
12
|
Node childNode = node.jjtGetChild(n); |
| 90 |
12
|
if (childNode instanceof ASTSwitchLabel) { |
| 91 |
|
|
| 92 |
4
|
ASTSwitchLabel sl = (ASTSwitchLabel) childNode; |
| 93 |
4
|
if (!sl.isDefault()) { |
| 94 |
3
|
childNode = node.jjtGetChild(n + 1); |
| 95 |
3
|
if (childNode instanceof ASTBlockStatement) { |
| 96 |
3
|
entry.bumpDecisionPoints(); |
| 97 |
|
} |
| 98 |
|
} |
| 99 |
|
} |
| 100 |
|
} |
| 101 |
1
|
super.visit(node, data); |
| 102 |
1
|
return data; |
| 103 |
|
} |
| 104 |
|
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 105 |
1
|
public Object visit(ASTWhileStatement node, Object data) {... |
| 106 |
1
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 107 |
1
|
super.visit(node, data); |
| 108 |
1
|
return data; |
| 109 |
|
} |
| 110 |
|
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 111 |
0
|
public Object visit(ASTConditionalExpression node, Object data) {... |
| 112 |
0
|
((Entry) entryStack.peek()).bumpDecisionPoints(); |
| 113 |
0
|
super.visit(node, data); |
| 114 |
0
|
return data; |
| 115 |
|
} |
| 116 |
|
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 117 |
0
|
public Object visit(ASTConditionalAndExpression node, Object data) {... |
| 118 |
0
|
((Entry) entryStack.peek()).bumpDecisionPoints(node.jjtGetNumChildren() - 1); |
| 119 |
0
|
super.visit(node, data); |
| 120 |
0
|
return data; |
| 121 |
|
} |
| 122 |
|
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
| 123 |
0
|
public Object visit(ASTConditionalOrExpression node, Object data) {... |
| 124 |
0
|
((Entry) entryStack.peek()).bumpDecisionPoints(node.jjtGetNumChildren() - 1); |
| 125 |
0
|
super.visit(node, data); |
| 126 |
0
|
return data; |
| 127 |
|
} |
| 128 |
|
|
|
|
|
| 83.3% |
Uncovered Elements: 2 (12) |
Complexity: 4 |
Complexity Density: 0.5 |
|
| 129 |
4
|
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {... |
| 130 |
4
|
if (node.isInterface()) { |
| 131 |
0
|
return data; |
| 132 |
|
} |
| 133 |
|
|
| 134 |
4
|
entryStack.push(new Entry(node)); |
| 135 |
4
|
super.visit(node, data); |
| 136 |
4
|
Entry classEntry = (Entry) entryStack.pop(); |
| 137 |
4
|
if ((classEntry.getComplexityAverage() >= getIntProperty("reportLevel")) || (classEntry.highestDecisionPoints >= getIntProperty("reportLevel"))) { |
| 138 |
3
|
addViolation(data, node, new String[]{"class", node.getImage(), String.valueOf(classEntry.getComplexityAverage()) + " (Highest = " + String.valueOf(classEntry.highestDecisionPoints) + ")"}); |
| 139 |
|
} |
| 140 |
4
|
return data; |
| 141 |
|
} |
| 142 |
|
|
|
|
|
| 89.3% |
Uncovered Elements: 3 (28) |
Complexity: 6 |
Complexity Density: 0.33 |
|
| 143 |
3
|
public Object visit(ASTMethodDeclaration node, Object data) {... |
| 144 |
3
|
entryStack.push(new Entry(node)); |
| 145 |
3
|
super.visit(node, data); |
| 146 |
3
|
Entry methodEntry = (Entry) entryStack.pop(); |
| 147 |
3
|
int methodDecisionPoints = methodEntry.decisionPoints; |
| 148 |
3
|
Entry classEntry = (Entry) entryStack.peek(); |
| 149 |
3
|
classEntry.methodCount++; |
| 150 |
3
|
classEntry.bumpDecisionPoints(methodDecisionPoints); |
| 151 |
|
|
| 152 |
3
|
if (methodDecisionPoints > classEntry.highestDecisionPoints) { |
| 153 |
3
|
classEntry.highestDecisionPoints = methodDecisionPoints; |
| 154 |
|
} |
| 155 |
|
|
| 156 |
3
|
ASTMethodDeclarator methodDeclarator = null; |
| 157 |
6
|
for (int n = 0; n < node.jjtGetNumChildren(); n++) { |
| 158 |
6
|
Node childNode = node.jjtGetChild(n); |
| 159 |
6
|
if (childNode instanceof ASTMethodDeclarator) { |
| 160 |
3
|
methodDeclarator = (ASTMethodDeclarator) childNode; |
| 161 |
3
|
break; |
| 162 |
|
} |
| 163 |
|
} |
| 164 |
|
|
| 165 |
3
|
if (methodEntry.decisionPoints >= getIntProperty("reportLevel")) { |
| 166 |
2
|
addViolation(data, node, new String[]{"method", (methodDeclarator == null) ? "" : methodDeclarator.getImage(), String.valueOf(methodEntry.decisionPoints)}); |
| 167 |
|
} |
| 168 |
|
|
| 169 |
3
|
return data; |
| 170 |
|
} |
| 171 |
|
|
|
|
|
| 0% |
Uncovered Elements: 8 (8) |
Complexity: 3 |
Complexity Density: 0.5 |
|
| 172 |
0
|
public Object visit(ASTEnumDeclaration node, Object data) {... |
| 173 |
0
|
entryStack.push(new Entry(node)); |
| 174 |
0
|
super.visit(node, data); |
| 175 |
0
|
Entry classEntry = (Entry) entryStack.pop(); |
| 176 |
0
|
if ((classEntry.getComplexityAverage() >= getIntProperty("reportLevel")) || (classEntry.highestDecisionPoints >= getIntProperty("reportLevel"))) { |
| 177 |
0
|
addViolation(data, node, new String[]{"class", node.getImage(), String.valueOf(classEntry.getComplexityAverage()) + "(Highest = " + String.valueOf(classEntry.highestDecisionPoints) + ")"}); |
| 178 |
|
} |
| 179 |
0
|
return data; |
| 180 |
|
} |
| 181 |
|
|
|
|
|
| 87.5% |
Uncovered Elements: 2 (16) |
Complexity: 3 |
Complexity Density: 0.25 |
|
| 182 |
1
|
public Object visit(ASTConstructorDeclaration node, Object data) {... |
| 183 |
1
|
entryStack.push(new Entry(node)); |
| 184 |
1
|
super.visit(node, data); |
| 185 |
1
|
Entry constructorEntry = (Entry) entryStack.pop(); |
| 186 |
1
|
int constructorDecisionPointCount = constructorEntry.decisionPoints; |
| 187 |
1
|
Entry classEntry = (Entry) entryStack.peek(); |
| 188 |
1
|
classEntry.methodCount++; |
| 189 |
1
|
classEntry.decisionPoints += constructorDecisionPointCount; |
| 190 |
1
|
if (constructorDecisionPointCount > classEntry.highestDecisionPoints) { |
| 191 |
1
|
classEntry.highestDecisionPoints = constructorDecisionPointCount; |
| 192 |
|
} |
| 193 |
1
|
if (constructorEntry.decisionPoints >= getIntProperty("reportLevel")) { |
| 194 |
1
|
addViolation(data, node, new String[]{"constructor", classEntry.node.getImage(), String.valueOf(constructorDecisionPointCount)}); |
| 195 |
|
} |
| 196 |
1
|
return data; |
| 197 |
|
} |
| 198 |
|
|
| 199 |
|
} |