Friday, October 28, 2011

Computing cyclomatic complexity with PowerShell and FxCop

A measure of the cyclomatic complexity of a .net method can be gauged by counting the number of IL branch instructions that do nor branch to the next instruction, and which have a distinct target from any other branch -- this is essentially the algorithm used in NDepend 1.x to make the computation. The introspection mechanism of FxCop provides enough decompilation of the IL that getting the instruction type and offset, and the target offset of a branch. An actual FxCop rule, though feasible to write, however, would be less useful than one could hope.

For one thing, FxCop itself doesn't provide any convenient way of passing parameters to custom rules (to e.g. set a trigger threshold); and for another, any analysis is likely to be run over a debug build (DEBUG and CODE_ANALYSIS variables defined there to not contaminate the released code with [SuppressMessage] annotations), which is likely to have a different underlying complexity to a release build (this is especially true in F# debug builds where there are a lot of sequences that look like

which can be replaced by

which, as it turns out, is pretty much what the release build does.

A more configurable and flexible way of performing the operation is to drive the FxCop facilities from a script -- these days I'm doing a lot of my .net scripting in PowerShell, but it could equally well be done with IronPython or similar .net scripting language. The result looks like this:

and running it over a set of F# code shows that the reported complexity of the release build of a method halves (or more) what is reported for a debug build. I haven't made a comparison over an significant amount of C# as yet, to see how much complexity the compiler removes between the two configurations.

No comments :