July 3, 2018

Applying StyleCop Ordering with ReSharper File Layout

Disclaimer: I imported this post from WordPress to Jekyll on 9/2/23. Forgive the misformatting until I get a chance to clean it up.

I have been wrestling a bit with the ideal ordering of members in my C# classes. Ordering members is obviously a cleanliness/maintainability factor and not a functional one, but I do want to create consistency in my classes.

As a heavy user of ReSharper (R#), I often apply their default C# File Layout via Code Cleanup to automatically re-arrange members. R#’s default File Layout is fairly good, but I would prefer to use Microsoft’s StyleCop ordering guidelines instead. R#, for example, does not default to ordering properties by access level, which I find valuable for consistency.

I found a handful of blog posts and resources around the web doing something similar, but none seemed to be recent and exactly compliant. Additionally, JetBrains does publish a StyleCop extension for R#, but its scope does not seem to be directly applicable to applying a File Layout alone.

StyleCop’s Ordering Rules

The StyleCopAnalyzer project has a subset of rules that I have converted for use in R# File Layout. This handful of rules were cherry-picked only in the sense that they meet the following requirements:

SA1124: Do Not Use

Regions

In R# XAML, this is implemented by adding the RemoveRegions flag in the TypePattern node.

<TypePattern DisplayName="StyleCop Classes, Interfaces, & Structs" RemoveRegions="All">

SA1201: Elements Must Appear In The Correct Order

Sort elements by type in the following order:

In R# XAML, this is implemented by the order of Entry nodes. For example, to put fields before constructors:

<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
</Entry>
<Entry DisplayName="Constructors">
<Entry.Match>
<Kind Is="Constructor" />
</Entry.Match>
</Entry>

SA1202: Elements Must Be Ordered By Access

Sort adjacent elements of the same type in the following order of access level:

In R# XAML, this is implemented via the Access node under Entry.SortBy like below for fields:

<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
</Entry.SortBy>
</Entry>

SA1203: Constants Must Appear Before Fields

In R# XAML, this is implemented by the order of the constant and field Entry nodes.

<Entry DisplayName="Constants">
<Entry.Match>
<Kind Is="Constant" />
</Entry.Match>
</Entry>
<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
</Entry>

SA1204: Static Elements Must Appear Before Instance Elements

In R# XAML, this is implemented via the Static node under Entry.SortBy like below for fields:

<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
</Entry.SortBy>
</Entry>

SA1214: Readonly Elements Must Appear Before Non-Readonly Elements

In R# XAML, this is implemented via the Readonly node under Entry.SortBy like below for fields:

<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>

Final ReSharper File Layout XAML

Converting the above rules directly into ReSharper C# File Layout XAML results in the following TypePattern (also available as a Gist):

<TypePattern DisplayName="StyleCop Classes, Interfaces, & Structs" RemoveRegions="All">
<TypePattern.Match>
<Or>
<Kind Is="Class" />
<Kind Is="Struct" />
<Kind Is="Interface" />
</Or>
</TypePattern.Match>
<Entry DisplayName="Constants">
<Entry.Match>
<Kind Is="Constant" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Fields">
<Entry.Match>
<Kind Is="Field" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Constructors">
<Entry.Match>
<Kind Is="Constructor" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Destructors">
<Entry.Match>
<Kind Is="Destructor" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Delegates">
<Entry.Match>
<Kind Is="Delegate" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Events">
<Entry.Match>
<Kind Is="Event" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Enums">
<Entry.Match>
<Kind Is="Enum" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Interfaces">
<Entry.Match>
<Kind Is="Interface" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Properties">
<Entry.Match>
<Kind Is="Property" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Indexers">
<Entry.Match>
<Kind Is="Indexer" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Methods">
<Entry.Match>
<Kind Is="Method" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Structs">
<Entry.Match>
<Kind Is="Struct" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
<Entry DisplayName="Classes">
<Entry.Match>
<Kind Is="Class" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal ProtectedInternal Protected Private" />
<Static />
<Readonly />
</Entry.SortBy>
</Entry>
</TypePattern>

Saving File Layout in ReSharper

  1. In Visual Studio, navigate to ReSharper -> Options
  2. Navigate to Code Editing -> C# -> File Layout
  3. Click XAML in the top right corner
  4. Copy and paste the above TypePattern into the XAML in the order you want it to fall (such as right before “Default Pattern”)
  5. Click Designer in the top right corner to verify the new TypePattern displays correctly
  6. Save your changes
[![StyleCop ReSharper File Layout TypePattern](/assets/img/styleCopResharperFileLayout_collinmbarrett-300x226.jpg)](/assets/img/styleCopResharperFileLayout_collinmbarrett.jpg)
StyleCop ReSharper File Layout TypePattern