Sunday, September 20, 2009

F# under the covers IV -- FxCop noise

I like to keep my .net code FxCop clean -- and especially when writing an FxCop rule set, it's pretty much part of the ground rules -- even though some of the rules tend at times towards coding for Mort to use your library (rather than educating him). However, FxCop does tend to assume you're coding in any .net language you like, so long as it's C#.

Take this example:

which emulates the C# as keyword (or C++ dynamic_cast<C *>() ) by contrast to the F# :?> which is more akin to dynamic_cast<C &>(). I don't mind the CA1004:GenericMethodsShouldProvideTypeParameter warning this gives -- but taking the F# idiomatic 'a and generating

warning : CA1709 : Microsoft.Naming : On method 'Patterns.As<a>(object)', correct the 
casing of 'a' in generic type parameter name 'a' by changing it to 'A'.
warning : CA1704 : Microsoft.Naming : On method 'Patterns.As<a>(object)', consider 
providing a more meaningful name than generic type parameter name 'a'.
warning : CA1715 : Microsoft.Naming : On method 'Patterns.As<a>(object)', prefix generic 
type parameter name 'a' with 'T'.

seems a bit excessive, even though replacing it with 'Target, like you might if you actually had to write it in C# as well, will suppress all three.

And that's just in code I write.

When the code subject to warnings is itself generated, that tends to add a degree of insult to injury. As in

which conjures up CA1707:IdentifiersShouldNotContainUnderscores from variables state_0 and state_1 in generated code that looks like

or CA1804:RemoveUnusedLocals for name x in the guard pattern

which maps to

because symbol x has to be scoped that way, as well as CA1811:AvoidUncalledPrivateCode or CA1804:RemoveUnusedLocals for entities only present in generated code.

That's debug build. In release build (not normally subject to FxCop, since you don't want to have SuppressMessage attributes floating around in what you ship) we get a different set of messages from differently shaped IL -- for

we at last get the entirely plausible CA1801:ReviewUnusedParameters (by contrast debug build's function body that assigns the argument to a write-only local causes no warnings!), and for the obvious combinator for chaining state with the Either type

we get "'arg_1', a parameter, is cast to type 'Either<x, a>._Right' multiple times in method 'Local.op_GreaterMultiplyGreater... -- but, surprisingly, no warning about underscores in names this time!

This certainly makes it harder to do the right thing, when none of the warnings, apart from the underscores one, actually seem like things that could really be called bugs as such. And it's also harder to frame alternative FxCop rules to use instead of the standard ones, rules that work with F# idiom, beyond possibly the generic type parameter naming cluster.

The debug build for the Feb 2010 CTP is unchanged from this; the release build produces more warnings for both the above cases, mainly about naming -- but also including

"In member 'Module1.op_GreaterMultiplyGreater<q, 
x, a, b>(q, Either<x, a>, FSharpFunc<q, FSharpFunc<a,
 Either<x, b>>>)', remove the underscores from parameter 
name 'arg_0'."

No comments :