Microsoft recently released Microsoft Source Code Analysis for C# better know as StyleCop. It comes with a lot of great rules. But some rules, like say, always using spaces, are mostly of a religious nature. I think its fair to say that there are good arguments to be made on both sides. And the most important thing is constancy. So if you are working in a tab shop and you want to take advantage of StyleCop what are you to do? Clearly it is time to embrace and extend. Now the easy way to do this would be like this. But I didn't have much luck, to be fair I didn't try very hard either. So instead I figured I would take advantage of another really fun, but little know about tool from Microsoft ILMerge. This tool, at its most basic, takes two .Net assemblies and merges them into one. This can be great fun. Here is the project with it all set up. I won't bore you with the details of how to set everything up as I think Paul does a better job than i can walking you through how to set everything up. The only difference is that you'll need to copy the Microsoft.SourceAnalysis.CSharp.Rules.dll back to the StyleCop install directory after the build.
I'll leave you with the source for the three custom rules I use as examples:
1)Check for tabs:
<blockquote>
<pre>
private void CheckForTabs(DocumentRoot root, MasterList<CsToken> tokens)
{
if (tokens.Count > 0)
{
for (Node<CsToken> node = tokens.First; node != null; node = node.Next)
{
if (this.Cancel)
{
return;
}
if (node.Value.Generated)
{
continue;
}
if (node.Value.CsTokenType == CsTokenType.EndOfLine)
{
Node<CsToken> startOfLine = node.Next;
if (null == startOfLinestartOfLine.Value.CsTokenType!=CsTokenType.WhiteSpace)
{
continue;
}
Whitespace whitespace = (Whitespace)startOfLine.Value;
if (whitespace.SpaceCount > 0)
{
this.AddViolation(root, whitespace.LineNumber, "UseTabsNotSpaces", new object[1]);
}
}
}
}
}
2)Check for bad words, make sure no swear words ot peoples names make it in source code:
private void CheckForBadWords(DocumentRoot root, MasterList<CsToken> tokens,IEnumerable<string> badWords)
{
if (tokens.Count > 0)
{
for (Node<CsToken> node = tokens.First; node != null; node = node.Next)
{
if (this.Cancel)
{
return;
}
if (node.Value.Generated)
{
continue;
}
if (badWords.Any(x=>node.Value.Text.ToLowerInvariant().Contains(x.ToLowerInvariant())))
{
string badWord = badWords.First(x => node.Value.Text.ToLowerInvariant().Contains(x.ToLowerInvariant()));
this.AddViolation(root, node.Value.LineNumber, "CheckForBadWords", new object[1]{badWord});
}
}
}
}
3)Mandate _field names:
private void CheckUnderscores(CsElement element)
{
if (ElementType.Field == element.ElementType)
{
Field f = (Field)element;
if (!f.Readonly && f.AccessModifier == AccessModifierType.Private && !f.Const)
{
if (!f.Name.StartsWith("_") true)
{
this.AddViolation(f, f.LineNumber, "PrivateFieldsMustBeginWithUnderscore", f.Name);
}
}
}
element.ChildElements.ToList().ForEach(x => this.CheckUnderscores(x));
}
And lastly one more tip, I found it a lot easier to base rules off an existing one, at least while learning the APIs. A great reverse engineering tool to try out is Relfector.
Hopefully this gives you another way to go about adding in your own custom rules and make this great tool even better.
0 comments:
Post a Comment