Introduction
Analyzers and EditorConfig are a set of rules that allow a team to have a common base on how to write readable and better code and importantly avoid losing time in code review on feedback that can be applied locally during development before submitting a pull request.
In this blog post, you will learn how to set up EditorConfig and Analyzers step by step for an existing project in your team and get it adopted.
The first thing to do is discuss the topic with your team, the way you all get repetitive feedback about code style and best practices before setting up the analyzers and EditorConfig.
Once it’s done, you can now decide on the rules you want to apply and the severity of each rule.
Add EditorConfig to your solution
EditorConfig is an open specification and file format for syntax highlighting, text editors and integrated development environment (IDEs) that aims to maintain a consistent coding style, particularly aimed at groups working together - Wikipedia
You can add one to your solution by using the dotnet CLI:
dotnet new editorconfig
This command will create an .editorconfig file at the root of your solution with default .NET code style settings.
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = space
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = false
## Simplified for brevity 👇
# ...
We will come back to the EditorConfig later, but for now, let’s move to the analyzers.
Analyzers
Code analyzers are tools that can inspect your code and give you feedback about potential issues, code style, best practices, etc.
The .NET SDK already comes with a bunch of analyzers that are enabled by default, but you can also add more analyzers to your project by adding the corresponding NuGet packages.
Below are some analyzers I’ve already tried in my projects:
If you decide to go with Roslynator for instance, you can add them to your Directory.Packages.props and Directory.Build.props files as follows:
Directory.Packages.props
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- Simplified for brevity 👇 -->
<!-- Simplified for brevity 👆 -->
<ItemGroup>
<!-- Analyzers -->
<PackageVersion Include="Roslynator.Analyzers" Version="4.15.0" />
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.15.0" />
</ItemGroup>
</Project>
Directory.Build.props
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Roslynator.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Formatting.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Now you can define what will happen during the build of the solution. Should code style be enforced during build? Should warnings be treated as errors? etc.
You can do that by adding the following properties to your Directory.Build.props file:
-
AnalysisMode: Which set of rules do you want to enable?Possible values are
None(all rules are disabled),Default,Minimum,RecommendedandAll(all rules are enabled). -
AnalysisLevel: Lets you specify a set of code analyzers to run according to a .NET version. You can for example setlatest(latest code analyzers that have been released are used) or set a specific version like10.0,9.0,8.0or even make a combination withAnalysisModelikelatest-recommended. -
TreatWarningsAsErrors: Any warning will be treated as an error whentrue.falsemeans compiler warnings stay warnings and do not fail the build. -
CodeAnalysisTreatWarningsAsErrors: Same idea, but only for code quality analysis warnings,CAxxxx rules. -
EnforceCodeStyleInBuild: When set totrue, code style rules will be enforced during build. This means that any code style violation will fail the build,IDExxxx rules. -
RunAnalyzersDuringBuild: Controls whether analyzers execute during build.trueenables analyzer execution in CI/local builds.
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- 👇 -->
<AnalysisMode>Recommended</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
</PropertyGroup>
</Project>
At this step, you will probably have a bunch of errors in your codebase.
Putting it all together
You would probably want to disable code analysis rules for some files (generated code for example) or some projects (test projects, etc.).
A common bad practice is to put the <NoWarn>xxxx</NoWarn> property in the csproj file.
The best approach is to use the EditorConfig file and add the official description of the rules you want to disable.
## Exclude EF Core Migrations files
[**/Migrations/*]
generated_code = true
dotnet_analyzer_diagnostic.severity = none
dotnet_analyzer_diagnostic.category-roslynator.severity = none
## Disable some rules for test projects
[**.Test*/**.cs]
dotnet_diagnostic.CA1707.severity = none # Identifiers should not contain underscores
###########################
# Roslynator configuration
###########################
# Set severity for all analyzers that are enabled by default
dotnet_analyzer_diagnostic.category-roslynator.severity = error
# Enable/disable all refactorings
roslynator_refactorings.enabled = true
# Enable/disable all compiler diagnostic fixes
roslynator_compiler_diagnostics_fixes.enabled = true
For an existing large project, my approach is to first group all rules by category and disable them in the EditorConfig file. Then, together with the team, we review each category and decide which rules we want to enable and the severity of each rule.
For the grouping, you don’t need to do that manually; you can just assign the task to your coding agent.
[*.cs]
## Roslynator formatting
dotnet_diagnostic.RCS0058.severity = none # Normalize whitespace at the end of a file
## Roslynator analyzers
dotnet_diagnostic.RCS1021.severity = none # Convert lambda expression body to expression body
dotnet_diagnostic.RCS1031.severity = none # Remove unnecessary braces in switch section
dotnet_diagnostic.RCS1032.severity = none # Remove redundant parentheses
# ... The remaining rules
## CAxxxx rules
dotnet_diagnostic.CA1001.severity = none # Types that own disposable fields should be disposable
dotnet_diagnostic.CA1831.severity = none # Use AsSpan instead of range-based indexers for string when appropriate
# ... The remaining rules
## IDExxxx rules
dotnet_diagnostic.IDE0005.severity = none # Remove unnecessary import
dotnet_diagnostic.IDE0007.severity = none # Use var instead of explicit type
# ... The remaining rules
## CSxxxx rules
dotnet_diagnostic.CS0168.severity = none # Variable is declared but never used
dotnet_diagnostic.CS0612.severity = none # 'member' is obsolete
# ... The remaining rules
The goal with all these rules disabled is to not block your CI or local builds.
Once your team decides on the rules to enable and their severity, you can update the EditorConfig according to your preference.
Final thoughts
Setting up analyzers and EditorConfig for an existing project can be tedious, but it’s worth it to have a consistent code style and avoid losing time during code review.
Resources
- https://learn.microsoft.com/en-us/community/content/how-to-enforce-dotnet-format-using-editorconfig-github-actions
- https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-option
- https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-10
- https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysislevel
- https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?#code-quality-analysis
- https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
- https://learn.microsoft.com/en-us/visualstudio/code-quality/disable-code-analysis
- https://josefpihrt.github.io/docs/roslynator/configuration