Dotnet Roslyn analyzers for code consistency and beyond
Combining multiple Roslyn analyzers with .editorconfig
is a powerful and flexible way for enforcing code style in dotnet projects. They can also detect possible security and performance issues in a very early stage.
Analyzers can be used for more than just dotnet. Here's one for sql, for example. This post, however, looks into three options for dotnet:
Roslynator
Roslynator is the one to start with, since it offers a CLI for performing fixes on most of the findings. The rules are mostly about code style and consistency.
An easy way to enable Roslynator and other analyzers is having a Directory.Build.props
on the solution root including this:
<ItemGroup>
<PackageReference Include="Roslynator.Analyzers" Version="4.13.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
Once that is done, the analyzers are run on build. .editorconfig
can be used to configure analysis levels:
# Set severity for all Roslynator rules at once
dotnet_analyzer_diagnostic.category-roslynator.severity = warning
# Or one by one
dotnet_diagnostic.rcs0029.severity = none
# Enable/disable all refactorings
roslynator_refactorings.enabled = true
# Enable/disable all compiler diagnostic fixes
roslynator_compiler_diagnostic_fixes.enabled = true
Rules can also be disabled on the project/Directory.Build.props
level:
<PropertyGroup>
<NoWarn>RCS1141;RCS1168;</NoWarn>
</PropertyGroup>
Once the project references and the configurations are in place, most of the warnings can be automatically fixed by running the CLI with roslynator fix
.
SonarAnalyzer
SonarAnalyzer is focused more on security and performance. There's a lot of overlap between Roslynator and SonarAnalyzer 'code smells', so running roslynator fix
beforehand is recommended.
The list of rules for C# are available here.
As with Roslynator, using the analyzers is straightforward:
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.6.0.109712">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
Dotnet rules
Every project with .NET 5 or later includes a standard set of analyzers. Only a subset is enabled by default, but you can enable more.
Once again, in the project file or Directory.Build.props
:
<PropertyGroup>
<AnalysisMode>Recommended</AnalysisMode>
<AnalysisModeSecurity>All</AnalysisModeSecurity>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
The top level AnalysisMode
is the generic option, and levels can be set for each category separately, as shown in the AnalysismodeSecurity
.
Putting it all together
Having this in Directory.Build.props
or project file(s)
<PropertyGroup>
<AnalysisMode>Recommended</AnalysisMode>
<AnalysisModeSecurity>All</AnalysisModeSecurity>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.6.0.109712">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.13.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
and having enabled Roslynator rules in .editorconfig
takes the project one step closer to a consistent style between developers and editors, plus some checks for security and performance. Assuming, of course, that warnings are not ignored, like I know some people do... 😶
Surprisingly enough, I've not seen many conflicts in the few projects with these analyzers enabled, but there have been a few rules I've disabled. I recommend enabling one set of analyzers at a time, fixing or ignoring the warnings and then adding more, but you could also big bang it to achieve a truly glorious warning count.
Why can't we have nice things
One (only?) thing I'm jealous to the frontend devs for is that companies seem eager to provide ready-to-go, reusable rules for code style for js stuff. See for example eslint-config-airbnb.
I wish the same was true for dotnet - some competition in providing fleshed out, Roslynator included .editorconfig rules. Sure, there's the one that dotnet runtime developers use, but that is quite sparse and at least not marketed as 'Hey, use this Microsoft sanctioned configuration'.
If you feel like your org has a great .editorconfig
and can showcase it with a decent sized repo, I think that popularity would be guaranteed.
Thoughts, comments? Send me an email!