SteveGilham / altcover

Cross-platform coverage gathering and processing tool set for dotnet/.Net Framework and Mono
MIT License
498 stars 18 forks source link

Question about cyclomatic complexity for pattern match #213

Closed MatthijsPrent closed 6 months ago

MatthijsPrent commented 6 months ago

Hello!

Is it possible to lower the reported cyclomatic complexity or to exclude a specific method from calculating cyclomatic complexity?

In my code, I have a relatively big match with statement, to map the different error codes to a string. The underlying types (ftdError) are all types defines in an enum.

For this type, a cyclomatic complexity of 34 is reported, which seems correct. However, in my opinion this is not bad code, so it can be excluded for any warnings that would be generated for the complexity > 30.

Is there any way to report a lower, or no complexity for this specific method? image

image

Thank you in advance for the response!

SteveGilham commented 6 months ago

There is no such exemption currently.

Rather than using a multiway branch, there are, of course, other approaches to the same end that move the branching to system code, such as

let FtdErrorStrings = [(FtdError.InvalidHandle, "Invalid Handle(s) given")
...
                       (FtdError.OtherError, "Undefined Internal USB Error")]
              |> Map.ofList
...
let FtdiErrorToString (code:FtdError) =
  FtdErrorStrings
  |> Map.tryFindKey code
  |> Option.defaultValue "Undefined Error code returned"

or from a resource file with similar key/value data,

  <data name="FtdError.InvalidHandle" xml:space="preserve">
    <value>Invalid Handle(s) given</value>
  </data>
...
  <data name="FtdError.OtherError" xml:space="preserve">
    <value>Undefined Internal USB Error</value>
  </data>
  <data name="Undefined+FtdError" xml:space="preserve">
    <value>Undefined Error code returne</value>
  </data>

and

let resourceManager = System.Resources.ResourceManager([resource name], Assembly.GetExecutingAssembly())
...
let FtdiErrorToString (code:FtdError) =
  match resourceManger.GetString("FtdError." + code.toString())
  | null -> resourceManger.GetString("Undefined+FtdError")
  | value -> value

which allows you to localize error messages as required.

There are other techniques using attributes on the enum values, but that would require it to be an enum that you define.

MatthijsPrent commented 6 months ago

Hello Steve,

Thank you for your response and for the suggested solution. I have just implemented the first suggestion in my code and the complexity for this method has dropped from 34 to 5.