Content updated: 4/23/2019.
Put two developers together and they’re bound to have a discussion about coding style. No two developers write code in the exact same way.
More often than not, one isn’t better than the other and it’s just a matter of taste. In a team or in a single project, it’s more important to be consistent than it is to choose the right style.
Agreeing on a style can be hard enough, but enforcing it shouldn’t be something you do manually. It will be tedious and error-prone.
StyleCop is a tool that can automate this. Let’s have a look at how to set it up and what it brings to the table.? This post will walk you through the following:
- What Stylecop is.
- How to install and run it.
- Configuration.
- Integration into your build.
- Defining rule excpetions
- Analyzing all projects
- Using the command line
So, read on if you want to learn everything there is to know about Stylecop.
What Is StyleCop?
The GitHub page for the old StyleCop tool says this:
StyleCop analyzes C# source code to enforce a set of style and consistency rules.
We’ll get into what this means exactly, but first a little word about the “old” and the “new” StyleCop.
StyleCop used to be a Visual Studio plugin and a NuGet package. You can still use this in Visual Studio 2019, but the current recommended way to use StyleCop is to use the Roslyn-based analyzers.
These analyzers will continue to be supported in the future, whereas the Visual Studio plugin and the NuGet package will no longer receive any major improvements. So for this article, I’ll focus on the StyleCop Analyzers project.
OK, now that we’ve got that out of the way, let’s look at a specific example of what StyleCop provides us. Let’s say your team has agreed to avoid one-line statements like this:
if (someCondition) return;
Rather, you want it to be
if (someCondition) { return; }
StyleCop provides a way of identifying all places in your code where these one-liners occur and optionally enforcing the multi-line statement by not allowing the project to be built.
The merits of the above example are something to discuss with your team, but every team should have guidelines on how they choose to write their code. This increases readability and predictability, making your daily lives a lot more pleasant and helping you avoid useless discussions.
These guidelines can range from whitespace rules to member-naming guidelines and from the order of members in your file to XML documentation guidelines. Whichever style guidelines you choose, StyleCop will allow you to enforce them automatically.
So how do we get started with StyleCop?
Installing StyleCop
To add StyleCop to your project, right-click your project in Visual Studio’s Solution Explorer, and choose “Manage NuGet Packages?”:
Search for “StyleCop.Analyzers” and install the latest stable version:
There’s really nothing more to it.
Running StyleCop
Now, build your project in Visual Studio and chances are, you will see several warnings in the output window. For example, take this simple console application:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace StyleCopDemo { class Program { static void Main(string[] args) { Output1(); Output2(); Output3(); Console.ReadLine(); } private static void Output1() { Console.WriteLine("output 1"); } private static void Output2() { Console.WriteLine("output 2"); } private static void Output3() { Console.WriteLine("output 3"); } } }
This file alone has 12 StyleCop warnings:
If you want to know more about a rule, click on the code and your browser will open a page with documentation on the rule.
To fix the rule violations, we must
- Add XML comments
- Generate an XML documentation file (this can be set in the project properties)
- Add a file header (e.g., copyright information)
- Put the “using” statements inside the “namespace” block
- Put braces on a new line
- Add an empty line between the two method definitions (Output2 and Output3)
This makes our application now look like this:
// <copyright file="Program.cs" company="PlaceholderCompany"> // Copyright (c) PlaceholderCompany. All rights reserved. // </copyright> namespace StyleCopDemo { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; /// <summary> /// Our program /// </summary> public class Program { /// <summary> /// Our main entry point /// </summary> /// <param name="args">Arguments to be passed to the application</param> public static void Main(string[] args) { Output1(); Output2(); Output3(); Console.ReadLine(); } private static void Output1() { Console.WriteLine("output 1"); } private static void Output2() { Console.WriteLine("output 2"); } private static void Output3() { Console.WriteLine("output 3"); } } }
You might not agree with all these rules. Luckily, you can tune StyleCop to your own needs.
Configuring StyleCop
Configuring StyleCop is done in two optional steps.
- First, you can use rule set files to configure which rules are checked and how strongly you feel about them.
- Second, you can add a stylecop.json file to your project to fine-tune some rules.
1. Rule Sets
Rule set files are files containing the rules you want to check.
In the project we’ve created above, right-click on the project and choose “Properties.” In the screen that just opened, select “Code Analysis”:
By default, the “Microsoft Managed Recommended Rules” will be selected. Click on “Open” and you’ll see a long list of rules you can select or deselect:
Notice that you can also change the action for the rules. Select a rule and open the dropdown to change the severity of the rule:
The “Action” dropdown allows you to tell the compiler what to do with the rule:
- “Warning” means a violation will be shown as a warning when building the solution.
- “Error” means a violation will be shown as an error. This also means you’ll see the red squiggly lines in the editor, and the build will fail.
- “Info” means a violation will be shown as an information message.
- “Hidden” means the rule is still checked, but you won’t see it in Visual Studio. This setting is more for use in custom tools than in Visual Studio.
- “None” means the rule will not be checked. This is, in essence, the same as deselecting the rule.
- <Inherit> doesn?t really do much. It?s a feature provided by Roslyn, but in the case of the StyleCop Analyzers, it seems to switch to ?None.?
If you change any of the settings in these default Microsoft rules, it will create a new rule set file and add it to the project. This is now the rule set for your project. Later in this article, we’ll cover solution-wide rule sets.
The default Microsoft rule sets are a great starting point.
By customizing them for your project, you can have an automated analysis that fits your need with little effort. Be sure to add the resulting .ruleset file to your source control system, and let it evolve as your needs evolve.
2. Stylecop.json
The stylecop.json file is a settings file to further configure StyleCop. The easiest way to add the file is to open a file that violates rule SA1633. This is the rule that requires a file header (e.g., a copyright notice). Press “CTRL + .” and you’ll see an option to add the file:
A JSON file with just a few lines will be added to your project:
The “$schema” property is to provide IntelliSense.
The value of the ?companyName? (under settings > documentationRules) will be used to automatically create a copyright notice when you fix rule SA1633. This is the rule that requires a file header at the top of the file. This usually contains a copyright notice, which is why StyleCop needs to know your company name.
However, if you go back to the file without a header, press CTRL + . again and choose the option to add the file header, you will see that the header still contains “PlaceholderCompany,” even if you’ve changed the stylecop.json file.
This is due to an issue that’s not yet resolved at the time of writing. To fix this, open the properties of the stylecop.json file and set the Build Action to “Additional Files.” If you’re writing a .NET Core or .NET Standard project, choose “C# analyzer additional file.”
Now that that’s done, you can add the file header again, and you’ll see the correct copyright notice.
The stylecop.json file allows quite a lot of configuration.
Be sure to check out the documentation because it’s too much to handle here. But let’s look at one example.
The Microsoft guidelines tell you to put the using statements inside the namespace declaration. Because Visual Studio puts them outside the namespace by default, most developers I know consider this awkward.
So let’s configure StyleCop to prefer them outside the namespace.? Notice how, in our example application, the code looked like this:
namespace StyleCopDemo { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; ...
Now let’s add this to the “Settings” property in our stylecop.json:
"orderingRules": { "usingDirectivesPlacement": "outsideNamespace" }
Next time we build, we will get new warnings telling us the “using directive must appear outside a namespace declaration.” To fix this, we simply need to change our code:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace StyleCopDemo { ...
Once again, be sure to check out the documentation to see what’s possible. But don’t worry about getting everything right the first time.
Often, the default values are what you want. If not, discuss this with your team and choose the configuration you agree on.
Breaking the Build
Once you have your rules all set up, you have an automated way of checking for style violations.
This is important if you want to avoid manual and time-consuming inspection. And keeping your code consistent makes it predictable and more readable. This, in turn, makes developers more productive and generally less frustrated.
Coming to an agreement can sometimes take lengthy discussions.
But often, the exact rule isn’t as important as it is to have a rule and not violate it. So whether or not the opening curly brace is on the same line or a new line isn’t very important. What is important is that you stick to the convention for your team or project.
With that said, you might want to start breaking the build when certain rules are violated. You could edit the properties of your project to treat all warnings as errors:
However, that often leads to some frustration when developers see the build failing on issues they don’t regard as being a problem.
A better approach would be to identify the rules you have no or few violations against and change the action from “Warning” to “Error.” Fix the few violations and agree with your team that, from now on, those rules will be breaking the build. Then incrementally increase the number of rules that result in an error until you feel you’ve reached a point where the code looks and reads the way you want.
This approach gradually makes the build stricter and stricter without angering your fellow team members.
The Exceptions to the Rule
Inevitably, you’ll encounter specific cases where you deliberately want to violate a rule.
Let’s say we have a class that contains public fields—something rule SA1401 warns against. We’re going to assume we have some legitimate reason that this cannot be a property. For example, some legacy library might use reflection to get the value of all fields, and this library might be out of our control.
So our code looks like this:
public class Customer { public string Name; }
When we press CTRL + . on the “Name” field, we see the option to suppress SA1401:
As you can see, we have the option of suppressing it directly in the .cs file or in a separate file.
If we choose to suppress the warning in the source file, our code changes to this:
public class Customer { #pragma warning disable SA1401 // Fields must be private public string Name; #pragma warning restore SA1401 // Fields must be private }
The first line we added disables rule SA1401 for all code that follows. The rule remains disabled until the rule is restored again, which happens in the second line that we added.
If we choose to suppress the error in a suppression file, a GlobalSuppressions.cs file is added to the project. In that file, an assembly attribute will have been added. This attribute gives you a little more control than the previous technique because you can scope the suppression.
This line, for example, will suppress the rule for the “Name” property of the customer class:
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage( "StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields must be private", Justification = "Due to legacy library reflection.", Scope = "member", Target = "~F:StyleCopDemo.Customer.Name")]
But by changing the scope and the target, we can suppress this error for all violations in the “Customer” class:
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage( "StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields must be private", Justification = "Due to legacy library reflection.", Scope = "type", Target = "~T:StyleCopDemo.Customer")]
You can also scope to a specific namespace.
Finally, notice how you can provide a justification, which more clearly communicates to other developers why it’s a good idea to suppress the warning.
Analyzing All Projects
In our example, we only added StyleCop to a single library; we added all files to the library. But most solutions consist of multiple projects. In order to use one rule set file for the entire solution, I recommend you take the following steps.
First, put the ruleset file next to your solution file. Add it as a solution item by right-clicking the solution and choosing Add > Existing Item:
Choose the ruleset file and it will be added to your solution:
Now, go to the properties of each project and select the ruleset in the dropdown:
You can use a similar technique for the stylecop.json file.
- First, put the stylecop.json file next to the solution file.
- Then right-click on each project and select ?Add existing item.?
- In the file dialog, choose the stylecop.json file, but don?t click on the ?Add? button. Rather, click on the dropdown and select ?Add As Link.?
(If you just click ?Add,? you?ll create a copy of the file for each project. Any changes to the stylecop.json file would have to be done for each project. When you add it as a link, you keep one copy of the file and only have to edit that one.)
Just remember you need to add the StyleCop.Analyzers package to each project you want to analyze and set the Build Action of each linked stylecop.json file to ?Additional Files? or ?C# analyzer additional file? (depending on your project type).
The Command-line
The StyleCop Analyzers use Roslyn under the hood. Roslyn is the .NET compiler with a rich set of API?s that can be used to analyze code. Because the ?new? StyleCop is no longer a Visual Studio plugin, it can be used outside Visual Studio too.
For example, here?s the output of our project when built using the command-line command ?dotnet build?:
See how our build succeeded, but the stylecop warnings are listed?
Style Isn’t Everything
Having a consistent style and having it enforced automatically is a great step forward to writing maintainable and readable code. But it doesn’t stop there. Automating your code quality analysis also includes things like detecting dead code, calculating cyclomatic complexity, and identifying security issues.
StyleCop will not do all of this for you. This requires other tools like FxCop or CodeIt.Right. (CodeIt.Right, since version 2.5, actually integrates Stylecop into its analysis.)
Let It Evolve
One last word of warning.
Too often, I’ve seen teams lose productivity because of rules they don’t agree with. Or maybe they used to agree with them, but times have changed and so have opinions.
As an example, I’m thinking of a company where the “var” keyword wasn’t allowed…in any project. This company-wide rule seemed set in stone and frustrated developers wanting to use modern language features.
Teams should come to an agreement on which rules they want to enforce and how severe violations are. And when opinions change, rules should follow.
The idea is to let StyleCop do the work for you and enable you to have a clean, consistent codebase with minimal effort. But the definition of clean and consistent can change over time.
I’ve provided a fairly complete guide to help you get started with StyleCop. So get together with your team and talk about how you want your code to look. Then set up StyleCop with some rules and move on from there. You’ll see the quality of your code improve. Good luck!
32 Comments. Leave new
[…] StyleCop: A Detailed Guide to Starting and Using It – Peter Morlion […]
Do you know how I can use StyleCop.Analyzer to integrate with Visual Studio 2017, so “Format document” will run based on stylecop settings?
Hi Philip, unfortunately, I don’t think that is possible. Maybe something to open on the Visual Studio user voice. There are multiple tools out there that provide more or less the same functionality, but each have their advantages and disadvantages: .editorconfig files, Resharper’s settings, Visual Studio formatting, StyleCop and of course CodeIt.Right. There may be even more that I’m not aware of. And they don’t always play nice together.
This guide was very useful, thanks Peter. Do you know if it is possible to ad a custom naming rule to StyleCop.json, so that the protected variables should start with underscore?
Hello Hooman, thanks for the feedback! I don’t know of any way of doing what you want in stylecop.json. In such a case, I think you would have to write your own analyzer. Maybe you can take this rule (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SX1309FieldNamesMustBeginWithUnderscore.cs) as a starting point to write your own.
Thanks a lot.
Hey hello,
I’d like to know where is the dropdown you’re talking about to add the stylecop.json file as link? I can’t see any dropdown in the file dialog when I want to add an existing item to my solution.
Thank you
Hi Jerome,
Sorry for not having made that clear. The Add button of the “Add existing item” dialog, actually has a built in drop-down, i.e. the button has a small arrow at the right (still inside the button). Click on that, instead of on the “Add” text, and it should open a small dropdown with two options.
Let me know if you find it or not.
Peter
Sorry my bad, I should better read what you wrote. Didn’t see that I should click on each project to add the file as link.
Thanks a lot for this tutorial, excellent introduction to StyleCop
No problem! Glad you liked it.
Hello, My team only has VS 2013 and thus we would need to use StyleCop Classic. However, I can’t find a guide on this anywhere. Does this article still apply to classic or do things work differently? Also, the StyleCop Analyzers github page has extensive documentation while the classic has none. Does the Analyzers documentation apply to classic as well?
I’d have to research it further, but does this help? https://stackoverflow.com/questions/23639815/how-do-i-integrate-stylecop-4-7-with-visual-studio-2013
Superb articall
There is some trick when you want to apply ruleset, stylecop.json and analyzers across all existing and added in future projects.
it is file Directory.Build.props on root folder of solution
This is sample from mine
<PropertyGroup Label="Package">
<Version>1.0.0</Version>
<AssemblyVersion>1.0.0</AssemblyVersion>
<Authors></Authors>
<Company></Company>
<Product></Product>
<Description></Description>
<Copyright>Copyright ? All rights Reserved</Copyright>
<Features>IOperation</Features>
</PropertyGroup>
<!-- Based on article https://www.thomaslevesque.com/2017/09/18/common-msbuild-properties-and-items-with-directory-build-props/ -->
<PropertyGroup>
<!-- Common ruleset shared by all projects -->
<CodeAnalysisRuleset>$(MSBuildThisFileDirectory)Custom.ruleset</CodeAnalysisRuleset>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<!-- Add reference to analyzers to all projects -->
<PackageReference Include="AsyncFixer" Version="1.1.6" />
<PackageReference Include="Asyncify" Version="0.9.7" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.9.2" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.2" />
<PackageReference Include="Microsoft.Net.Compilers" Version="3.0.0" />
<PackageReference Include="Roslynator.Analyzers" Version="2.0.0" />
<PackageReference Include="Roslynator.CodeFixes" Version="2.0.0" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.14.0.8411" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<!-- Common StyleCop configuration -->
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" />
</ItemGroup>
Thanks for the tip! I didn’t know that.
First, excellent article! Second, I’m trying to find the RuleSets, but I can’t for the life of me find them. I right clicked my project and selected properties, but I don’t see Code Analysis in the list. Was it moved?
Hi Gene! I’m glad you liked the article. I want to help you out, but need some more information. What kind of project is it and what version of Visual Studio are you using? Maybe we should move such a discussion to StackOverflow, because we’ll probably need some screenshots, some Q&A back and forth, etc. If you open a question there and point me to it, I’ll be happy to investigate and help out (as might others).
I found it by right clicking Solution Explorer/References/Analyzers and selecting open Active RuleSet. thanks again!
It’s probably because your project uses .Net Core as a Target framework. Code Analysis tab is only available for older framework versions (.NET Framework 4.7.2 and lower versions), because .NET Core uses Roslyn code analyzers instead of static code analysis. If you insist on using static code analysis, you will have to install it manually as a nuget “Microsoft.CodeAnalysis.FxCopAnalyzers.” and then add the ruleset as an xml file manually to the project as well.
Not sure if someone mentioned this in the comments, but I think you are mixing Code Analysis and StyleCop settings here. These are two independent systems. Configuring rule sets is not required to run StyleCop at all, those are for old (not Roslyn) static code analysis. You can see which rule belongs to code analysis and which belongs to StyleCop by their name. Code analysis rules start with “CA”, while StyleCop rules start with “SA”.
Update: Code analysis rules can also start with prefix “CS”, “C”, “IDE”, “A”, “AD” or “RE”. I usually see only CS and CA though, others are not that common. All built-in StyleCop rules start with “SA” prefix. If you use StyleCop extensions, you may see “SX” prefix as well.
Thanks Andrej!
When I just created RuleSet, VS show me all rules: https://take.ms/gxmRA
But when I restart VS, VS show me only few rules: https://take.ms/wMuAB
Why?!!!
Hi Denis, that’s weird indeed. Can you share the solution (or a trimmed down version) somewhere?
It’s just created solution. No sense to share it.
I opened issue https://developercommunity.visualstudio.com/content/problem/679767/ruleset-editor-show-not-all-rules.html
Hope it will be fixed.
Good idea! Let us know when/how it gets fixed.
Where does stylecop decide what version of C#? We see SA1002 warnings for C# 6 features that build without issue.
Hi Powell, can you give me an example? SA1002 is about semicolons and spacing, so I don’t think it’s related to any C# 6 feature? But I may be wrong of course. If you can give me an example that gives such a warning, and which you feel should not, I can investigate further.
Hi Peter, how can I temporarily disable the stylecop in VS 2015 ?
Hi Raj, it should be possible by adding something like this to you csproj:
true
Check out these Stack Overflow answers: https://stackoverflow.com/questions/17163746/visual-studio-temporarily-disable-stylecop
I haven’t tested it out myself yet, but it seems there are solutions.
Thank you, well written document and it is more clear. As you have mentioned in the early of the document, we are not seeing any topic for solution level settings. If possible please share., BTW, this is the very good article on Stylecop.,
[…] Each file should contain a header block. The header block should consist of the following which adheres to the format defined by StyleCop. […]