[clang-tidy] Implement readability-function-cognitive-complexity check

Authored by lebedev.ri on Aug 17 2017, 8:57 AM.


[clang-tidy] Implement readability-function-cognitive-complexity check

Currently, there is basically just one clang-tidy check to impose
some sanity limits on functions - clang-tidy-readability-function-size.
It is nice, allows to limit line count, total number of statements,
number of branches, number of function parameters (not counting
implicit this), nesting level.

However, those are simple generic metrics. It is still trivially possible
to write a function, which does not violate any of these metrics,
yet is still rather unreadable.

Thus, some additional, slightly more complicated metric is needed.
There is a well-known Cyclomatic complexity, but certainly has its downsides.
And there is a COGNITIVE COMPLEXITY by SonarSource, which is available for opensource on https://sonarcloud.io/.

This check checks function Cognitive Complexity metric, and flags
the functions with Cognitive Complexity exceeding the configured limit.
The default limit is 25, same as in 'upstream'.

The metric is implemented as per COGNITIVE COMPLEXITY by SonarSource specification version 1.2 (19 April 2017), with two notable exceptions:

  • preprocessor conditionals (#ifdef, #if, #elif, #else, #endif) are not accounted for. Could be done. Currently, upstream does not account for them either.
  • each method in a recursion cycle is not accounted for. It can't be fully implemented, because cross-translational-unit analysis would be needed, which is not possible in clang-tidy. Thus, at least right now, i completely avoided implementing it.

There are some further possible improvements:

  • Are GNU statement expressions (BinaryConditionalOperator) really free? They should probably cause nesting level increase, and complexity level increase when they are nested within eachother.
  • Microsoft SEH support
  • ???

Reviewed By: aaron.ballman, JonasToth, lattner

Differential Revision: https://reviews.llvm.org/D36836