Since Checkstyle 3.2
The complexity is equal to the number of decision points + 1
.
Decision points:
if
, while
, do
, for
,
?:
, catch
, switch
, case
statements.
&&
and ||
in the body of target.
when
expression in case labels, also known as guards.
By pure theory level 1-4 is considered easy to test, 5-7 OK, 8-10 consider re-factoring to ease testing, and 11+ re-factor now as testing will be painful.
When it comes to code quality measurement by this metric level 10 is very good level as a ultimate target (that is hard to archive). Do not be ashamed to have complexity level 15 or even higher, but keep it below 20 to catch really bad-designed code automatically.
Please use Suppression to avoid violations on cases that could not be split in few methods without damaging readability of code or encapsulation.
name | description | type | default value | since |
---|---|---|---|---|
max | Specify the maximum threshold allowed. | int | 10 |
3.2 |
switchBlockAsSingleDecisionPoint | Control whether to treat the whole switch block as a single decision point. | boolean | false |
6.11 |
tokens | tokens to check | subset of tokens LITERAL_WHILE , LITERAL_DO , LITERAL_FOR , LITERAL_IF , LITERAL_SWITCH , LITERAL_CASE , LITERAL_CATCH , QUESTION , LAND , LOR , LITERAL_WHEN . | LITERAL_WHILE , LITERAL_DO , LITERAL_FOR , LITERAL_IF , LITERAL_SWITCH , LITERAL_CASE , LITERAL_CATCH , QUESTION , LAND , LOR , LITERAL_WHEN . | 3.2 |
To configure the check:
<module name="Checker"> <module name="TreeWalker"> <module name="CyclomaticComplexity"/> </module> </module>
Example:
class Example1 { int a, b, c, d, e, n; public void testMethod1() { while (a < b && a > c) { fun1(); } if (a == b) { do { fun1(); } while (d==a); } else if (c == d) { while (c > 0) { fun1(); } do { fun1(); } while (a==d); } } // violation below, 'Cyclomatic Complexity is 13 (max allowed is 10)' public void testMethod2() { // 1, function declaration if (a == b) { // 2, if fun1(); } else if (a == 0 // 3, if && b == c) { // 4, && operator if (c == -1) { // 5, if fun1(); } } else if (a == c // 6, if || a == d) { // 7, || operator fun1(); } else if (d == e) { //8, if try { fun1(); } catch (Exception e) { // 9, catch } } else { switch(n) { case 1: // 10, case fun1(); break; case 2: // 11, case fun1(); break; case 3: // 12, case fun1(); break; default: break; } } a = a > 0 ? b : c; // 13, ternary operator } private void fun1() {} }
To configure the check with a threshold of 4 and check only for while and do-while loops:
<module name="Checker"> <module name="TreeWalker"> <module name="CyclomaticComplexity"> <property name="max" value="4"/> <property name="tokens" value="LITERAL_WHILE, LITERAL_DO"/> </module> </module> </module>
Example:
class Example2 { int a, b, c, d, e, n; // violation below, 'Cyclomatic Complexity is 5 (max allowed is 4)' public void testMethod1() { // 1, function declaration while (a < b && a > c) { // 2, while fun1(); } if (a == b) { do { // 3, do fun1(); } while (d==a); } else if (c == d) { while (c > 0) { // 4, while fun1(); } do { // 5, do-while fun1(); } while (a==d); } } public void testMethod2() { if (a == b) { fun1(); } else if (a == 0 && b == c) { if (c == -1) { fun1(); } } else if (a == c || a == d) { fun1(); } else if (d == e) { try { fun1(); } catch (Exception e) { } } else { switch(n) { case 1: fun1(); break; case 2: fun1(); break; case 3: fun1(); break; default: break; } } a = a > 0 ? b : c; } private void fun1() {} }
To configure the check to consider switch-case block as one decision point.
<module name="Checker"> <module name="TreeWalker"> <module name="CyclomaticComplexity"> <property name="switchBlockAsSingleDecisionPoint" value="true"/> </module> </module> </module>
Example:
class Example3 { int a, b, c, d, e, n; public void testMethod1() { while (a < b && a > c) { fun1(); } if (a == b) { do { fun1(); } while (d==a); } else if (c == d) { while (c > 0) { fun1(); } do { fun1(); } while (a==d); } } // violation below, 'Cyclomatic Complexity is 11 (max allowed is 10)' public void testMethod2() { // 1, function declaration if (a == b) { // 2, if fun1(); } else if (a == 0 // 3, if && b == c) { // 4, && operator if (c == -1) { // 5, if fun1(); } } else if (a == c // 6, if || a == d) { // 7, || operator fun1(); } else if (d == e) { // 8, if try { fun1(); } catch (Exception e) { // 9, catch } } else { switch(n) { // 10, switch case 1: fun1(); break; case 2: fun1(); break; case 3: // 10, case fun1(); break; default: break; } } a = a > 0 ? b : c; // 11, ternary operator } private void fun1() {} }
All messages can be customized if the default message doesn't suit you. Please see the documentation to learn how to.
com.puppycrawl.tools.checkstyle.checks.metrics