1 package com.stateofflow.eclipse.metrics.calculators.complexity;
2
3 import org.eclipse.jdt.core.dom.CatchClause;
4 import org.eclipse.jdt.core.dom.ConditionalExpression;
5 import org.eclipse.jdt.core.dom.DoStatement;
6 import org.eclipse.jdt.core.dom.EnhancedForStatement;
7 import org.eclipse.jdt.core.dom.ForStatement;
8 import org.eclipse.jdt.core.dom.IfStatement;
9 import org.eclipse.jdt.core.dom.MethodDeclaration;
10 import org.eclipse.jdt.core.dom.SwitchCase;
11 import org.eclipse.jdt.core.dom.WhileStatement;
12
13 import com.stateofflow.eclipse.metrics.calculators.AbstractASTVisitorCalculator;
14 import com.stateofflow.eclipse.metrics.configuration.MetricsConfiguration;
15 import com.stateofflow.eclipse.metrics.metric.MetricId;
16 import com.stateofflow.eclipse.metrics.metric.MetricPropertyKey;
17
18 public final class CyclomaticComplexityCalculator extends AbstractASTVisitorCalculator {
19 public static final MetricId METHOD_METRIC_ID = MetricId.createMethodId(CyclomaticComplexityCalculator.class);
20 public static final MetricId WEIGHTED_METHODS_PER_CLASS_METRIC_ID = MetricId.createTypeId(CyclomaticComplexityCalculator.class);
21
22 public static final MetricPropertyKey COUNT_CASE_STATEMENTS_KEY = new MetricPropertyKey(METHOD_METRIC_ID, "countCaseStatements");
23 public static final MetricPropertyKey COUNT_CATCH_CLAUSES_KEY = new MetricPropertyKey(METHOD_METRIC_ID, "countCatchClauses");
24 public static final MetricPropertyKey COUNT_TERNARY_OPERATORS_KEY = new MetricPropertyKey(METHOD_METRIC_ID, "countTernaryOperators");
25
26 private Complexity complexity = new Complexity();
27
28 private final MetricsConfiguration configuration;
29
30 public CyclomaticComplexityCalculator(final MetricsConfiguration configuration) {
31 this.configuration = configuration;
32 }
33
34 public void endVisit(final MethodDeclaration arg0) {
35 if (isConcrete(arg0)) {
36 noteMethodValue(CyclomaticComplexityCalculator.METHOD_METRIC_ID, complexity.getMethodComplexity());
37 }
38 super.endVisit(arg0);
39 }
40
41 protected Object getRestorableState() {
42 return new Complexity(complexity);
43 }
44
45 protected void handleEndOfType() {
46 noteTypeValue(CyclomaticComplexityCalculator.WEIGHTED_METHODS_PER_CLASS_METRIC_ID, complexity.getClassComplexity());
47 super.handleEndOfType();
48 }
49
50 protected void handleNestedClass(final Object inner) {
51 complexity.handleNestedClass(isInMethod(), (Complexity) inner);
52 }
53
54 protected void handleStartOfType() {
55 complexity.startType();
56 super.handleStartOfType();
57 }
58
59 protected void restoreSpecificState(final Object restorableState) {
60 complexity = (Complexity) restorableState;
61 }
62
63 public boolean visit(final CatchClause arg0) {
64 if (configuration.getBoolean(COUNT_CATCH_CLAUSES_KEY)) {
65 complexity.increment();
66 }
67 return super.visit(arg0);
68 }
69
70 public boolean visit(final ConditionalExpression arg0) {
71 if (configuration.getBoolean(COUNT_TERNARY_OPERATORS_KEY)) {
72 complexity.increment();
73 }
74 return super.visit(arg0);
75 }
76
77 public boolean visit(final DoStatement arg0) {
78 complexity.increment();
79 return super.visit(arg0);
80 }
81
82 public boolean visit(final EnhancedForStatement arg0) {
83 complexity.increment();
84 return super.visit(arg0);
85 }
86
87 public boolean visit(final ForStatement arg0) {
88 complexity.increment();
89 return super.visit(arg0);
90 }
91
92 public boolean visit(final IfStatement arg0) {
93 complexity.increment();
94 return super.visit(arg0);
95 }
96
97 public boolean visit(final MethodDeclaration arg0) {
98 if (isConcrete(arg0)) {
99 complexity.startMethod();
100 return super.visit(arg0);
101 }
102 return false;
103 }
104
105 public boolean visit(final SwitchCase arg0) {
106 if (configuration.getBoolean(COUNT_CASE_STATEMENTS_KEY)) {
107 complexity.increment();
108 }
109 return super.visit(arg0);
110 }
111
112 public boolean visit(final WhileStatement arg0) {
113 complexity.increment();
114 return super.visit(arg0);
115 }
116 }