FSharpLint icon indicating copy to clipboard operation
FSharpLint copied to clipboard

Cyclomatic Complexity rule yields multiple messages for same scope

Open davidtgillard opened this issue 3 years ago • 1 comments

Description

Under particular circumstances, the present implementation of the Cyclomatic Complexity rule FL0071 will necessarily generate multiple messages when the complexity exceeds the configurable maximum.

Repro steps

As an example: running the linter on the following snippet of code with a maxComplexity of 5 yields the output below.

snippet:

  let multipleStrCases (str: string) =
    match str with
    | "C01" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C02" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C03" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C04" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C05" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C06" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C07" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C08" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C09" -> match str with
                | "A" -> ()
                | "B" -> ()
    | "C010" -> match str with
                | "A" -> ()
                | "B" -> ()
    | _ -> ()

output:

The cyclomatic complexity of this section is 31, which exceeds the maximum suggested complexity of 5.
Error on line 7 starting at column 6
  let multipleStrCases (str: string) =
      ^                               
--------------------------------------------------------------------------------
The cyclomatic complexity of this section is 29, which exceeds the maximum suggested complexity of 5.
Error on line 7 starting at column 6
  let multipleStrCases (str: string) =
      ^                               
--------------------------------------------------------------------------------
The cyclomatic complexity of this section is 27, which exceeds the maximum suggested complexity of 5.
Error on line 7 starting at column 6
  let multipleStrCases (str: string) =
      ^  

...and so on.

Expected behavior

Only one message should be reported, indicating the highest cyclomatic complexity (31 in the example above).

Actual behavior

See above.

Known workarounds

The linter is still usable in its current state, but the over-reporting of messages is confusing and annoying.

Related information

The cause of the issue is that the runner in the CyclomaticComplexity module is issuing a warning for all bindings pushed off the stack when the binding is advanced, even if the start of the binding is the same. It should cut these down to only those with the maximum cyclomatic complexity.

davidtgillard avatar Jul 24 '22 23:07 davidtgillard

I have a fix for this, I've just got to clean it up and write an accompanying test; I will generate a PR when that is ready.

davidtgillard avatar Jul 24 '22 23:07 davidtgillard