1*6e566bc5SRichard.. title:: clang-tidy - readability-function-cognitive-complexity
2*6e566bc5SRichard
3*6e566bc5SRichardreadability-function-cognitive-complexity
4*6e566bc5SRichard=========================================
5*6e566bc5SRichard
6*6e566bc5SRichardChecks function Cognitive Complexity metric.
7*6e566bc5SRichard
8*6e566bc5SRichardThe metric is implemented as per the `COGNITIVE COMPLEXITY by SonarSource
9*6e566bc5SRichard<https://www.sonarsource.com/docs/CognitiveComplexity.pdf>`_ specification
10*6e566bc5SRichardversion 1.2 (19 April 2017).
11*6e566bc5SRichard
12*6e566bc5SRichardOptions
13*6e566bc5SRichard-------
14*6e566bc5SRichard
15*6e566bc5SRichard.. option:: Threshold
16*6e566bc5SRichard
17*6e566bc5SRichard   Flag functions with Cognitive Complexity exceeding this number.
18*6e566bc5SRichard   The default is `25`.
19*6e566bc5SRichard
20*6e566bc5SRichard.. option:: DescribeBasicIncrements
21*6e566bc5SRichard
22*6e566bc5SRichard   If set to `true`, then for each function exceeding the complexity threshold
23*6e566bc5SRichard   the check will issue additional diagnostics on every piece of code (loop,
24*6e566bc5SRichard   `if` statement, etc.) which contributes to that complexity. See also the
25*6e566bc5SRichard   examples below. Default is `true`.
26*6e566bc5SRichard
27*6e566bc5SRichard.. option:: IgnoreMacros
28*6e566bc5SRichard
29*6e566bc5SRichard   If set to `true`, the check will ignore code inside macros. Note, that also
30*6e566bc5SRichard   any macro arguments are ignored, even if they should count to the complexity.
31*6e566bc5SRichard   As this might change in the future, this option isn't guaranteed to be
32*6e566bc5SRichard   forward-compatible. Default is `false`.
33*6e566bc5SRichard
34*6e566bc5SRichardBuilding blocks
35*6e566bc5SRichard---------------
36*6e566bc5SRichard
37*6e566bc5SRichardThere are three basic building blocks of a Cognitive Complexity metric:
38*6e566bc5SRichard
39*6e566bc5SRichardIncrement
40*6e566bc5SRichard^^^^^^^^^
41*6e566bc5SRichard
42*6e566bc5SRichardThe following structures increase the function's Cognitive Complexity metric
43*6e566bc5SRichard(by `1`):
44*6e566bc5SRichard
45*6e566bc5SRichard* Conditional operators:
46*6e566bc5SRichard
47*6e566bc5SRichard   - ``if()``
48*6e566bc5SRichard   - ``else if()``
49*6e566bc5SRichard   - ``else``
50*6e566bc5SRichard   - ``cond ? true : false``
51*6e566bc5SRichard
52*6e566bc5SRichard* ``switch()``
53*6e566bc5SRichard* Loops:
54*6e566bc5SRichard
55*6e566bc5SRichard   - ``for()``
56*6e566bc5SRichard   - C++11 range-based ``for()``
57*6e566bc5SRichard   - ``while()``
58*6e566bc5SRichard   - ``do while()``
59*6e566bc5SRichard
60*6e566bc5SRichard* ``catch ()``
61*6e566bc5SRichard* ``goto LABEL``, ``goto *(&&LABEL))``,
62*6e566bc5SRichard* sequences of binary logical operators:
63*6e566bc5SRichard
64*6e566bc5SRichard   - ``boolean1 || boolean2``
65*6e566bc5SRichard   - ``boolean1 && boolean2``
66*6e566bc5SRichard
67*6e566bc5SRichardNesting level
68*6e566bc5SRichard^^^^^^^^^^^^^
69*6e566bc5SRichard
70*6e566bc5SRichardWhile by itself the nesting level does not change the function's Cognitive
71*6e566bc5SRichardComplexity metric, it is tracked, and is used by the next, third building block.
72*6e566bc5SRichardThe following structures increase the nesting level (by `1`):
73*6e566bc5SRichard
74*6e566bc5SRichard* Conditional operators:
75*6e566bc5SRichard
76*6e566bc5SRichard   - ``if()``
77*6e566bc5SRichard   - ``else if()``
78*6e566bc5SRichard   - ``else``
79*6e566bc5SRichard   - ``cond ? true : false``
80*6e566bc5SRichard
81*6e566bc5SRichard* ``switch()``
82*6e566bc5SRichard* Loops:
83*6e566bc5SRichard
84*6e566bc5SRichard   - ``for()``
85*6e566bc5SRichard   - C++11 range-based ``for()``
86*6e566bc5SRichard   - ``while()``
87*6e566bc5SRichard   - ``do while()``
88*6e566bc5SRichard
89*6e566bc5SRichard* ``catch ()``
90*6e566bc5SRichard* Nested functions:
91*6e566bc5SRichard
92*6e566bc5SRichard   - C++11 Lambda
93*6e566bc5SRichard   - Nested ``class``
94*6e566bc5SRichard   - Nested ``struct``
95*6e566bc5SRichard* GNU statement expression
96*6e566bc5SRichard* Apple Block Declaration
97*6e566bc5SRichard
98*6e566bc5SRichardNesting increment
99*6e566bc5SRichard^^^^^^^^^^^^^^^^^
100*6e566bc5SRichard
101*6e566bc5SRichardThis is where the previous basic building block, `Nesting level`_, matters.
102*6e566bc5SRichardThe following structures increase the function's Cognitive Complexity metric by
103*6e566bc5SRichardthe current `Nesting level`_:
104*6e566bc5SRichard
105*6e566bc5SRichard* Conditional operators:
106*6e566bc5SRichard
107*6e566bc5SRichard   - ``if()``
108*6e566bc5SRichard   - ``cond ? true : false``
109*6e566bc5SRichard
110*6e566bc5SRichard* ``switch()``
111*6e566bc5SRichard* Loops:
112*6e566bc5SRichard
113*6e566bc5SRichard   - ``for()``
114*6e566bc5SRichard   - C++11 range-based ``for()``
115*6e566bc5SRichard   - ``while()``
116*6e566bc5SRichard   - ``do while()``
117*6e566bc5SRichard
118*6e566bc5SRichard* ``catch ()``
119*6e566bc5SRichard
120*6e566bc5SRichardExamples
121*6e566bc5SRichard--------
122*6e566bc5SRichard
123*6e566bc5SRichardThe simplest case. This function has Cognitive Complexity of `0`.
124*6e566bc5SRichard
125*6e566bc5SRichard.. code-block:: c++
126*6e566bc5SRichard
127*6e566bc5SRichard  void function0() {}
128*6e566bc5SRichard
129*6e566bc5SRichardSlightly better example. This function has Cognitive Complexity of `1`.
130*6e566bc5SRichard
131*6e566bc5SRichard.. code-block:: c++
132*6e566bc5SRichard
133*6e566bc5SRichard  int function1(bool var) {
134*6e566bc5SRichard    if(var) // +1, nesting level +1
135*6e566bc5SRichard      return 42;
136*6e566bc5SRichard    return 0;
137*6e566bc5SRichard  }
138*6e566bc5SRichard
139*6e566bc5SRichardFull example. This function has Cognitive Complexity of `3`.
140*6e566bc5SRichard
141*6e566bc5SRichard.. code-block:: c++
142*6e566bc5SRichard
143*6e566bc5SRichard  int function3(bool var1, bool var2) {
144*6e566bc5SRichard    if(var1) { // +1, nesting level +1
145*6e566bc5SRichard      if(var2)  // +2 (1 + current nesting level of 1), nesting level +1
146*6e566bc5SRichard        return 42;
147*6e566bc5SRichard    }
148*6e566bc5SRichard
149*6e566bc5SRichard    return 0;
150*6e566bc5SRichard  }
151*6e566bc5SRichard
152*6e566bc5SRichardIn the last example, the check will flag `function3` if the option Threshold is
153*6e566bc5SRichardset to `2` or smaller. If the option DescribeBasicIncrements is set to `true`,
154*6e566bc5SRichardit will additionally flag the two `if` statements with the amounts by which they
155*6e566bc5SRichardincrease to the complexity of the function and the current nesting level.
156*6e566bc5SRichard
157*6e566bc5SRichardLimitations
158*6e566bc5SRichard-----------
159*6e566bc5SRichard
160*6e566bc5SRichardThe metric is implemented with two notable exceptions:
161*6e566bc5SRichard   * `preprocessor conditionals` (``#ifdef``, ``#if``, ``#elif``, ``#else``,
162*6e566bc5SRichard     ``#endif``) are not accounted for.
163*6e566bc5SRichard   * `each method in a recursion cycle` is not accounted for. It can't be fully
164*6e566bc5SRichard     implemented, because cross-translational-unit analysis would be needed,
165*6e566bc5SRichard     which is currently not possible in clang-tidy.
166