How does Sonar calculate the cyclomatic complexity?

Celinio Fernandes picture Celinio Fernandes · Sep 13, 2017 · Viewed 9.7k times · Source

Sonar gives me the following cyclomatic complexity number : 22.

For the following program :

private static SomeDto checkSomething(AnotherDto anotherDto, String reference)
{
SomeDto someDto = new SomeDto();

// condition 1
if (!someDto.getA())
    return new SomeDto("bla1", "blabla");

// condition 2
if (someDto.getName2() == null || checkSurName(anotherDto.getName()))
    return new SomeDto("bla2", "blabla");

// condition 3
if (someDto.getName3() == null || checkSurName(anotherDto.getName()))
    return new SomeDto("bla3", "blabla");

// condition 4
if (someDto.getName4() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla4", "blabla");

// condition 5
if (someDto.getName5() == null || checkSurName(anotherDto.getName()))
    return new SomeDto("bla5", "blabla");

// condition 6
if (someDto.getName6() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla6", "blabla");

// condition 7
if (someDto.getName7() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla7", "blabla");

// condition 8
if (someDto.getName8() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla8", "blabla");

// condition 9
if (someDto.getName9() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla9", "blabla");

// condition 10
if (someDto.getName10() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla10", "blabla");

// condition 11
if (someDto.getName11() == null && checkSurName(anotherDto.getName()))
    return new SomeDto("bla11", "blabla");

return someDto;
}    

The issue i get is the following :

"The Cyclomatic Complexity of this method "checkSomething" is 22 which is greater than 12 authorized."

My question is : considering the Mac Cabe formula v(g) = e - n + 2, how does Sonar reach the number of 22 ?

Where :

e = number of edges

n = number of nodes

How many edges and nodes are there in this method ? What is the control flow for this method ?

We're on SonarQube Version 6.3 (build 19869).

Answer

bluesman80 picture bluesman80 · Oct 16, 2019

The SonarQube documentation for the latest version clearly states how it calculates the Cyclomatic Complexity:

Complexity (complexity) It is the Cyclomatic Complexity calculated based on the number of paths through the code. Whenever the control flow of a function splits, the complexity counter gets incremented by one. Each function has a minimum complexity of 1. This calculation varies slightly by language because keywords and functionalities do.

And if you open the "Language-specific details" underneath that paragraph, the Java line reads as follows.

Keywords incrementing the complexity: if, for, while, case, catch, throw, &&, ||, ?

Since the OP was using version 6.3 by the time of the question, I also checked the documentation for the oldest version that I could find, which is 6.7. By then, the calculation was slightly different.

Keywords incrementing the complexity: if, for, while, case, catch, throw, return (that is not the last statement of a method), &&, ||, ?

Notes:

else, default, and finally keywords do not increment the complexity.

a simple method with a switch statement and a huge block of case statements can have a surprisingly high complexity value (still it has the same value when converting a switch block to an equivalent sequence of if statements).

Example: the following method has a complexity of 5

public void process(Car myCar){          // +1
    if(myCar.isNotMine()){               // +1
         return;                         // +1
    }
    car.paint("red");
    car.changeWheel();
    while(car.hasGazol() && car.getDriver().isNotStressed()){   // +2
         car.drive();
    }
    return; }