Skip to content

Metrics

Every function header carries five chips. They are measured from the code’s syntax, so the same code always scores the same.

The rules below are the ones for JavaScript and TypeScript. The other languages count the same things with their own syntax.

Cognitive complexity is how hard a function is to follow. It is the first chip, and the one the colors follow. The measure comes from G. Ann Campbell’s cognitive complexity, as used by SonarSource.

Three things add to it.

  • A branching structure costs 1. That means an if, a for or for…in loop, a while or do loop, a switch, a catch and a ternary (a ? b : c).
  • Nesting adds more. The same structure costs 1 plus the number of structures it sits inside. A callback or nested function also counts as a level.
  • A break in the straight flow costs 1. An else costs 1, and so does each else if. A run of &&, || or ?? costs 1, and 1 more each time the operator changes.

A switch costs 1 once, not once per case. A try costs nothing; its catch does. A plain return costs nothing.

Nesting is why the number grows faster than the line count. Three checks in a row cost 3. The same three checks, one inside the next, cost 6.

charge has three ifs, each inside the last.

LineAddsWhy
if (user)1First structure, nothing around it.
if (order)21, plus 1 for the if it sits in.
if (card)31, plus 2 for the two ifs it sits in.

That is 6, so the chip reads cognitive 6. The other chips on the figure follow below.

Cyclomatic complexity counts the paths through the function. It starts at 1. Each if, loop, catch and ternary adds 1, each case of a switch adds 1, and each &&, || or ?? adds 1. Nesting does not matter to it. charge scores 4: the starting 1 and three ifs.

It is a count of branches, so it grows with the number of decisions, where cognitive complexity also grows with how they are stacked.

The deepest level of nested structures in the function. charge has nesting 3. The fill color of the schematic follows the same depth: the deeper the block, the warmer it is.

The number of return and throw statements that leave the function itself. One inside a callback leaves the callback, so it is not counted. An arrow function with an expression body has one exit. The exit rail on the right of a schematic draws the same exits. charge has none: it ends by running off the end, so its exits chip reads exits 0.

The length of the function, from its first line to its last. It counts comments and blank lines. charge is 9 lines.

The cognitive chip is colored by band.

Cognitive complexityColor
5 or lessGreen
6 to 15Amber
above 15Red

charge scores 6, so its chip is amber. Hotspots, the list of the most complex functions in a repository, orders by this number, and the component map colors each file by how complex it is per line.

A changed function’s chips show a change: cognitive 3 → 6 (+3, more complex). Here the color follows the direction, not the size.

ChangeColorWords
The number went upRed“more complex”
The number went downGreen“simpler”
It did not changeNone

Cognitive complexity and nesting are colored this way. Lines has no color: a longer function is not worse for being longer. The same word is in the chip’s tooltip, so the color is never the only signal.

A function that went from 40 to 38 is green, and is still a function with a score of 38.

A color is there to help you find things. It does not say a function is wrong. A parser with many cases can be red and perfectly clear. A short function can be hard to follow and stay green. A change marked “more complex” may be the right change.

Use the color to choose where to look first, then read the code.