Linting C# in 2019 — StyleCop, Sonar, Resharper, Visual Studio and Roslyn

Michael Parker
5 min readFeb 22, 2019

--

Screenshot of Visual Studio editing a .ruleset file, disabling StyleCop rules

There are multiple ways to lint C# for code formatting, styling inconsistencies, plus plugins to add deeper analysis. I recently had to figure out how to do this myself and was amazed at the lack of clarity online — not only how many different options there were, but many of the articles are now out of date as the tech has moved on.

TL:DR:

I used StyleCop first, using StyleCop.Analyzers nuget package, and automatically added it to all projects.

  1. Create a Directory.Build.props file next to your solution, looks like this:
<Project>
<!-- StyleCop Analyzers configuration -->
<PropertyGroup>
<CodeAnalysisRuleSet>$(SolutionDir)StyleCop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include=”StyleCop.Analyzers” Version=”1.1.1-rc.108" PrivateAssets=”all” />
<AdditionalFiles Include=”$(SolutionDir)stylecop.json” Link=”stylecop.json” />
</ItemGroup>
</Project>

2. Create a StyleCop.ruleset file next to your solution, looks like this: https://gist.github.com/mikeparker/c24e56172f548d66e9c2379896b8b563

(Feel free to customise the rules)

3. (OPTIONAL) Create a stylecop.json file next to your solution, looks like this:

{
“$schema”: https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
“settings”: {
“orderingRules”: {
“usingDirectivesPlacement”: “outsideNamespace”
}
}
}

This file is to customise the rule behaviour (NOT to enable/disable rules!). For example, this example changes the usingDirectivesPlacement rule to enforce that using statements should be outside the namespace (i.e. at the top of the file). This is an alternative to simply disabling the rule.

4. That’s it :) StyleCop will now lint your code on build (NOTE: It will only lint the code that has changed since the last rebuild!). In Visual Studio you can press Alt + F11 to lint the entire solution.

Fixing linting errors

StyleCop as above comes with a sibling nuget package called StyleCop.Analyzers.CodeFixes which allows Visual Studio (and probably VS Code and others) to provide user prompts to automatically fix errors. In Visual Studio this is as simple as pressing Ctrl + . or Alt + Enter and selecting the fix from the menu.

Note that these menu fixes typically come with a ‘fix all in solution’ button which will fix the linting error across the whole solution:

The full list of which errors have automatic solutions coded is listed here https://dotnetanalyzers.github.io/StyleCopAnalyzers/

StyleCop

To use StyleCop in 2019 you simply install the nuget package StyleCop.Analyzers . You can do this on a per-project basis or globally (as above) using Directory.Build.props.

Once you’ve installed the nuget package you will start getting warnings for things you don’t care about, and will want to disable rules. The documentation for disabling rules tells you to use the Visual Studio UI, but I’ve found this useless at dealing with a solution-level ruleset file. If you use Visual Studio to Suppress a rule, it typically gives you the options:

  • In Source (#pragma warning disable)
  • In Suppression file ( GlobalSuppressions.cs )

Ideally there would be a In Ruleset file option, but this isn’t implemented. (I opened a feature request for it here)

To add it to your global ruleset file, you must do it manually! I’ve had to manually write out XML lines to suppress rules. Please let me know if theres an automated solution I’ve missed! Here is a gist to show what a file looks like.

NOTE: Ruleset files in Visual Studio normally open with the ‘Ruleset file editor’ which is bad. Just right click -> Open With -> XML Text Editor, and save yourself the pain!

The whole system is quite flexible, so for example you can have different ruleset files for different projects (maybe one for test projects, one for production code?) and you have even reference more than one and they override each others settings based on the order you reference them..

If you want to enable StyleCop on just some projects then either directly reference the .ruleset file from your .csproj files or reference a .props file from your .csproj file that references the .ruleset file.

Sonar

Sonar is, IMO, not a competitor to Stylecop, it is designed for a different purpose and can be used alongside Stylecop. It does deeper analysis of your code than stylecop, so it is (warning: over-generalisation!) less concerned with where you put your braces and more concerned with cyclomatic complexity. You can use both.

Sonar does NOT have automatic fixes for its errors, which might annoy some people as it purely tells you what’s wrong, but doesn’t help you fix it.

Sonar DOES have the ability to rate your code cleanliness, host a central server, track your code over time by integrating into CI. If you want a simple linter with automatic fixes, StyleCop is what you want. If you want a higher level tracking system for how complex your codebase is over time, and maybe even comparing codebases between teams, and tracking technical debt, Sonar is what you want. We intend to use both.

Resharper

Resharper provides a free command line tool to lint your code. However, this doesn’t hook into your IDE without configuration and AFAIK, it does not provide automated fixes without you also buying and installing the Resharper plugin for Visual Studio (or using Project Rider). So this is a paid solution and requires everyone on your team to be licensed. I won’t cover the resharper setup because my team is not licensed for it.

In you are a Resharper fan (as a lot of C# developers are) bear in mind that Microsoft are providing more and more Resharper functionality in Visual Studio, Roslyn, and related tooling, so it’s worth keeping an eye on how Microsoft progresses in this area, and also how much Resharper slows down Visual Studio, how much it costs etc. It seems both Microsoft and JetBrains are not happy with Visual Studio performing essentially the same code parsing twice all the time, as evidenced by:

(a) Visual Studio telling you ‘Resharper just took 45 seconds to load’ and bugging you to get rid of slow plugins

(b) JetBrains starting their own C# IDE (Project Rider) so they aren’t bogged down with VS slowness

Personally, if I can get everything out of the box with Visual Studio and I no longer need Resharper then in my eyes thats 1 less thing to install and manage, but right now there are still many refactoring tools missing from Visual Studio which makes Resharper still very useful. I feel I’m getting closer to dropping Resharper altogether. But I’m not there yet!

Other Analyzers

If you use async / await, you may want to check out this analyzer also:

https://github.com/Microsoft/vs-threading/blob/master/doc/analyzers/index.md

.editorconfig

Microsoft have said that .editorconfig files are the future and will potentially take over from .ruleset files. For now it doesnt seem the ecosystem is set up for .editorconfig files to completely take over all the .ruleset file functionality.

In the meantime it’s probably possible for .editorconfig rules to state something different from the .ruleset rules and have them clash, but I am yet to see it.

Questions?

Please ask in the comments. I’ll update this post with things I’ve missed.

--

--