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