Easing the StyleCop Pain With Atomineer

If you too find your team voting in favour of introducing StyleCop (the Microsoft born aesthetic compliance tool) it’s possible you have found yourself in a whole world of pain, but there is help at hand.

So what’s StyleCop again?

“StyleCop analyzes C# source code to enforce a set of style and consistency rules. It can be run from inside of Visual Studio or integrated into an MSBuild project. StyleCop has also been integrated into many third-party development tools.”

.. or as some developers like to call it: “a pain in the arse”.

How does Atomineer help?

Once you have engaged your inner OCD and found yourself unconsciously writing your code to be in-line with the StyleCop rules you’ll quickly find that the majority of the work for your average C# class file is adding the necessary document headers and comments – this is where a tool like Atomineer or GhostDoc can really help.

Both these utilities attempt to create the document comments in your document based on a set of pattern rules, in most cases doing a pretty good job. As an example comments for get {} and set {} are mostly going to follow a uniform pattern and are therefore easy to generate, other scenarios are always going to need attention and authorship to be of credible use.

Using Atomineer to kick-start the documentation process is a real time (and sanity) saver and in many cases I’ve only had to make one key-press (to add comments to the whole document scope) and copy/paste the using statements inside the namespace for StyleCop to be happy – WINNER!

Show me how

Atomineer ‘out of the box’ includes several different documenting standards that you can use, unfortunately none of them comply with StyleCop rules so for starters you are going to want to start improving what’s there; let me run you through my settings.

Installation

When installing Atomineer it will prompt you to run through an initial configuration wizard, to set the baseline of where my changes started you may wish to adhere to the same:

  • Documentation format: “Documentation XML”
  • Black border styles: “TripSlash (Plain)”
  • Text layout (standalone): “Symmetrical tags, indented text”
  • Text layout (groups): “Exception ticked, Tabular for the entire group (inline end tag)”

When completing the wizard process Atomineer will put some file-based XML configuration files in it’s default installation directory “c:\users\documents\Visual Studio 2008\Addins” (other versions will reference this directory); it seems only when entering the preferences application and using buttons under “Advanced Customisation” will it move all configuration to file-based.

Settings

Outside the pattern generation that Atomineer employs there are some more general settings around styling, these too need to be right to meet StyleCop’s approval. Fortunately Atomineer stores also stores these settings in an XML configuration file (prefs.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?xml version="1.0"?>
<Prefs>
  <DocComment>
    <CommentStyle value="DocXml" />
    <Separator value="(No first line separator)" />
    <SeparatorB value="(No last line separator)" />
    <LineHeader2 value="/// " />
    <AlignBlockStartColumns value="true" />
    <VBSeparator value="'''-------------------------------------------------------------------------------------------------" />
    <VBSeparatorB value="'''-------------------------------------------------------------------------------------------------" />
    <LineHeader />
    <DateCulture value="" />
    <SingleLinePrefix value="///< " />
    <SingleLineSuffix value="(None)" />
    <SingleLineMinColumn value="0" />
    <LineCommentOnSameLine value="false" />
    <WordWrapColumn value="100" />
    <BlanksAbove value="-1" />
    <BlanksAfterRegion value="-1" />
    <BlanksBelow value="-1" />
    <BlanksBetweenEntries value="false" />
    <WordWrapRelative value="true" />
    <DateFormat value="d" />
    <LiveCommentUpdate value="true" />
    <LiveCommentCreation value="true" />
    <ConvertEntities value="true" />
    <AddDocTableForEnums value="false" />
    <LiveSLCommentUpdate value="true" />
  </DocComment>
  <Doxygen>
    <CommandPrefix value="\" />
    <SuppressBriefTags value="false" />
    <SuppressPrototypes value="false" />
  </Doxygen>
  <Format>
    <EntrySuppressNewlines value="false" />
    <EntryTag value="Newline" />
    <EntryNewline value="Nothing" />
    <EntryBody value="Newline" />
    <SingleTag value="Space" />
    <SingleBody value="Space" />
    <GroupSuppressNewlines value="true" />
    <GroupTag value="Space" />
    <GroupNewline value="Nothing" />
    <GroupBody value="Space" />
    <AlignBlockStartColumns value="true" />
  </Format>
  <Misc>
    <RulesPath value="" />
    <UserName value="(Use login name)" />
    <ShowOutliningCmds value="true" />
    <ShowCppCmds value="true" />
    <ShowClipboardCmds value="true" />
    <ShowContextCmds value="true" />
    <EditXmlInNotepad />
  </Misc>
  <DocXml>
    <BlockFormatNew />
    <BlockFormatOld />
    <BlockFormatForGroup />
  </DocXml>
  <OutlineDocComment>
    <OnOpenDoc value="false" />
    <SkipFirstLine value="true" />
    <EatTrailingBlank value="true" />
  </OutlineDocComment>
  <OutlineRegion>
    <OnOpenDoc value="false" />
    <Tidy value="false" />
  </OutlineRegion>
  <OutlineAttr>
    <OnOpenDoc value="false" />
    <EatBlanks value="true" />
  </OutlineAttr>
  <CopyAsText>
    <StripIndent value="true" />
    <TabSize value="4" />
  </CopyAsText>
  <AddAccessMethods>
    <VarTemplate value="varName" />
    <MemberPrefix />
    <MethodTemplate value="GetVarName,SetVarName" />
    <ParamTemplate value="varName" />
  </AddAccessMethods>
  <ImplementMethod>
    <AddDocComment value="true" />
    <ReturnToOrigDoc value="false" />
  </ImplementMethod>
  <Separators>
    <FileType ext="htm,html,xhtml,xml,xsd,xslt,xaml,config,resx">
      <Separator value="<!--" />
      <LineHeader2 value="(None)" />
      <SeparatorB value="-->" />
    </FileType>
    <FileType ext="sql">
      <Separator value="/* " />
      <LineHeader2 value=" * " />
      <SeparatorB value=" */" />
    </FileType>
    <FileType ext="lua">
      <Separator value="-----------------------------------------------------------------------------------------------" />
      <LineHeader2 value="-- " />
      <SeparatorB value="-----------------------------------------------------------------------------------------------" />
    </FileType>
    <FileType ext="pl,pm,ps1,psc1,psd1,psm1,py,pyc,pyo,rb,tcl">
      <Separator value="###############################################################################################" />
      <LineHeader2 value="# " />
      <SeparatorB value="###############################################################################################" />
    </FileType>
    <FileType ext="bat,bas">
      <Separator value="rem -------------------------------------------------------------------------------------------" />
      <LineHeader2 value="rem " />
      <SeparatorB value="rem -------------------------------------------------------------------------------------------" />
    </FileType>
  </Separators>
</Prefs>

Example

As an example how you might take the existing DocXML standards that are provided and make them StyleCop friendly here is the change I made to “methods.xml” for the constructor document header on a c# class file:

Before DocXML

1
2
3
4
5
6
7
8
<If methodType="constructor">
  <If specialType="static" desc="Static constructor" />
  <If numArgs="0" desc="Default constructor" />
  <If numArgs="1">
    <If argType1="%containingclass%,%containingclass%#,# %containingclass%,# %containingclass%#" desc="Copy constructor" />
  </If>
  <Set desc="Constructor" />
</If>

Before result

1
2
3
4
5
6
7
8
9
10
public class SomeClass
{
    /// 
    /// Default constructor.
    /// 
    public SomeClass()
    {
        // Do something
    }
}

After DocXML

1
2
3
4
5
6
7
8
<If methodType="constructor">
  <If specialType="static" desc="Static constructor" />
  <If numArgs="0" desc="Initializes a new instance of the %containingclass% class" />
  <If numArgs="1">
    <If argType1="%containingclass%,%containingclass%#,# %containingclass%,# %containingclass%#" desc="Initializes a new instance of the %containingclass% class" />
  </If>
  <Set desc="Initializes a new instance of the %containingclass% class" />
</If>

After result

1
2
3
4
5
6
7
8
9
10
public class SomeClass
{
    ///
    /// Initializes a new instance of the SomeClass class.
    ///
    public SomeClass()
    {
        // Do something
    }
  }

As you can see it’s quite easy to start updating the rules as you find your way through your StyleCop experience.

Final word

Find below a link to a GitHub repository that I will *attempt* to continue to update with the latest version of the StyleCop modifications, if you would like to contribute to this project please feel free – the more contributing then the further towards 100% StyleCop compliance Atomineer will become :)

http://github.com/ianbattersby/AtomineerForStyleCop

Comments