tags:

views:

493

answers:

2

FxCop wants me to spell Username with a capital N (i.e. UserName), due to it being a compound word. However, due to consistency reasons we need to spell it with a lowercase n - so either username or Username.

I've tried tweaking the CodeAnalysisDictionary.xml by adding the following section to the section:

<DiscreteExceptions>
  <Term>username</Term>
</DiscreteExceptions>

From what I understand how custom dictionaries work, this should tell FxCop to treat username as a discrete term and prevent the CompoundWordsShouldBeCasedCorrectly (CA1702) check to fire an error.

Unfortunately this doesn't work. Does anybody have an idea why that is and how to solve this? I don't want to add suppressions, because this would seriously clutter the GlobalSuppressions file as there are quite a lot of occurrences.

Edited to add: For the time being I have solved this by using GlobalSuppressions, but given the nature of the issue this doesn't seem like the ideal way to solve this. Can anybody give a hint on where to look for further information on how FxCop applies the rules defined in a dictionary?

+1  A: 

In the custom dictionary that comes with FxCop (located in my system in C:\Program Files\Microsoft FxCop 1.36\CustomDixtionary.xml, but YMMV) in Words\Compounds has a <Term CompoundAlternate="UserName">username</Term> entry. Delete it. You still need the discrete exception.

Wilhelm
Thanks for your answer. I marked Nick's answer as the accepted answer, because it was more detailed. However, I think that your solutions were pretty much the same.
Anne Schuessler
@Nick If we are eliminating the compound alternate, then it won't automatically count as discrete exception.
Wilhelm
@Wilhelm. My previous explanation for why the discrete exception is not required was wrong. Thank you for pointing that out. I've deleted the comment since it would only serve to confuse others. However, the discrete exception is still not needed in this case since the OP would like to represent username as a single token. Discrete exceptions apply only to part A of the rule as described above, which can fire only on a pair of adjacent tokens.
Nick Guerrera
I should add that if you want FxCop to accept both UserName and Username, then yes, you do need the discrete exception. I don't believe this is what the OP wants...
Nick Guerrera
+4  A: 

I was a developer on the FxCop / Managed Code Analysis Team for 3 years and I have your answer. Things have changed since my time, and I had forgotten exactly how custom dictionary handling worked and so it took me quite a bit of time to figure this out. :)

Executive Summary

The short answer is that you need to remove all references to username, usernames, UserName, and UserNames from C:\Program Files (x86)\Microsoft FxCop 1.36\CustomDictionary.xml.

Normally, I would not recommend this as it should not be required, but you have found what I believe is a bug, and this is the only workaround that I could find.

Full Story

OK, now for the long answer...

The rule has two distinct checks which work as follows:

A. Check for compound words that should be discrete

  1. Split identifier into tokens: e.g. FileName --> { "file", "name" }
  2. Spell check each adjacent pair of tokens.
  3. If the spell check succeeds (e.g. filename is deemed to be a valid word),
    then we have found a potential problem since a single word should not be expressed as two tokens.
  4. However, if there is a <Term CompoundAlternate="FileName">filename</Term> in the <Compound> section of the custom dictionary, then it is taken to mean that although filename is a word, the design guidelines (largely as a nod to consistency with prior art in the Framework that predates the existence of the rule) insist it should be written as FileName, and so we must suppress the warning.
  5. Also, if there is a <Term>filename</Term> entry in the <DiscreteExceptions> section of the custom dictionary, then it is taken to mean that although 'filename' is a word, it might also be two words 'file' and 'name' in a different context. e.g. Onset is a word, but asking the user to change DoSomethingOnSet to DoSomethingOnset would be noise, and so we must suppress the warning.

B. Check for discrete words that should be compound:

  1. Taking the tokens from A.1, check each one individually against the set of compound terms in the custom dictionary.
  2. If there is a match, then we must warn in keeping with the interpretation in step A.4.

Notice that your warning: Username should be UserName is detected in part B, which does not consult the DiscreteExceptions section, which is why you are not able to suppress the warning by modifying that section. The problem is that the default custom dictionary has an entry stating that the correct casing for username is always UserName. It needs to be removed or overridden somehow.

The Bug

Now, the ideal solution would be to leave the default custom dictionary alone, specify SearchFxCopDir=false in your project file, and then merge in only the parts of the default custom dictionary that you want in the CustomDictionary.xml that is used for your project. Sadly, this does not work as FxCop 1.36 ignores the SearchFxCopDir directive and always treats it as true. I believe this is a bug, but it is also possible that this was an intentional change since the directive is not documented and has no corresponding UI. I honestly don't know...

Conclusion

Given that FxCop always uses its default custom dictionary in addition to the project custom dictionary, your only recourse is to remove the entries in question from the default custom dictionary.

If I have a chance, I will contact the current code analysis team to see if this in fact a bug, and report back here...

Nick Guerrera
Thanks for the detailed answer. This confirmed what I suspected, but it was good to get a bit of information on how FxCop works when it checks against the rules.
Anne Schuessler