How to Use Common EditorConfig as a NuGet Package

Written by igorlopushko | Published 2022/06/17
Tech Story Tags: c-sharp | dotnet | code-style | editor-config | programming | coding | software-development | hackernoon-top-story

TLDREditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. EditorConfig files are easily readable and work nicely with version control systems. EditorConfg has some limitations in the.NET world also specified in this article in the [limitations] section of this article. The EditorConfig project consists of a file format** for defining coding styles and a collection of.text editor plugins** that enable editors to read the file format and adhere to defined styles.via the TL;DR App

The problem

In our organization, we are running multiple GitHub repositories with different web services. All these projects require common rules for code styling. We moved the right way and created a service template project which is a basis for all the .NET solutions and defines a common architecture. It contains a set of projects with correct naming and references. However, we moved the wrong way and copied the .editorconfig file to every new repository. There was a temptation to modify the .editorconfig file whenever it does not fit the developer’s needs. And we did this fault.

There is not much information on the Internet on how to create a common .editorconfig file and distribute it across multiple repositories. The god feeling told that it must be a NuGet package. After a long time of googling the problem, we found this solution. Thanks to Adam Craven who solved the same issue for his project.

Why EditorConfig

EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.

In the .NET world, code analysis rules have various configuration options. You specify these options as key-value pairs in one of the following analyzer configuration files:

  • EditorConfig file: File-based or folder-based configuration options.

  • Global AnalyzerConfig file: Project-level configuration options. Useful when some project files reside outside the project folder.

You can set the severity for compiler warnings or analyzer rules in an EditorConfig file with the following syntax:

dotnet_diagnostic.<rule ID>.severity = <severity>

Setting a rule's severity in an EditorConfig file takes precedence over any severity that's set in a rule set or in Solution Explorer.

In some projects, there is a mix of local and global config files. Moreover, EditorConfg has some limitations in the .NET world also specified in this article in the limitations section. We tried both ways and moved back and forth with these two approaches. And finally decided to move a simple way to use just EditoConfig for our projects.

The solution

First things first, you need to create a new C# library project for the NuGet package. Let’s call it MyProject.EditorConfig. This project will contain the following files:

  • .props file
  • .csproj file
  • .editorconfig file

.props file

You have to add PropertyGroup with the following properties set to the true value:

<PropertyGroup>
  <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  <EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>

  • EnforceCodeStyleInBuild - allows code style rules specified in the EditorConfig file to be checked as part of the build;
  • EnableNETAnalyzers is true by default for .NET 5.0, but rather set it to true to support earlier versions of .NET;

As one of the limitations of EditorConfig is that some rules have Location.None and cannot be specified in an EditorConfig file. If you do not use the Global AnalyzerConfig file as we do, you would have an option to disable those rules in the .props file:

<PropertyGroup>
  <NoWarn>$(NoWarn);CA1014</NoWarn>
</PropertyGroup>

Specify the location of the .editorconfig file to copy from within the NuGet package folder structure:

<ItemGroup>
  <EditorConfigFilesToCopy Include="$(MSBuildThisFileDirectory)../content/Rules/.editorconfig" />
</ItemGroup>

Be careful with \ and / symbols in the file path string on different platforms. It really took us much time to figure out why .editorconfig file is not copied.

Use the MSBuild Copy Task to copy the file to the folder of the .NET Project that is being built. This Target is defined to execute before the MSBuild BeforeBuild Target.

<Target Name="CopyEditorConfig" BeforeTargets="BeforeBuild">
  <Message Text="Copying the .editorconfig file from '@(EditorConfigFilesToCopy)' to '$(SolutionFolder)'"></Message>
  <Copy 
    SourceFiles="@(EditorConfigFilesToCopy)"
    DestinationFolder="$(SolutionFolder)"
    SkipUnchangedFiles="true"
    UseHardlinksIfPossible="false" />
</Target>

.csproj file

By default, when packing NuGet files that start with a period are ignored. To avoid that you have to add the following code to the .csproj file:

<PropertyGroup>
  <NoDefaultExcludes>true</NoDefaultExcludes>
</PropertyGroup>

After that you have to include .props and .editorconfig files:

<ItemGroup>
  <None Include="MyProject.EditorConfig.props" Pack="true" PackagePath="\build" />
  <None Include=".editorconfig" Pack="true" PackagePath="\content\Rules" />
</ItemGroup>

Build and test NuGet package

When the all job is done you can publish NuGet package to the local storage and verify that it works.

Execute the following command in the MyProject.EditorConfig project folder to pack a NuGet package:

dotnet pack MyProject.EditorConfig.csproj -c Release -o out --no-restore

Publish it into local storage (folder). NuGet CLI hast to be installed beforehand:

nuget add out/MyProject.EditorConfig.1.0.0.nupkg -Source /Users/igorlopushko/test_nuget_expand/ -Expand

Specify a target folder with -Source parameter.


Register local NuGet package path:

dotnet nuget add source /Users/igorlopushko/test_nuget_expand/

To add a local NuGet package to the target project execute this command in the target project’s folder:

dotnet add package MyProject.EditorConfig -s /Users/igorlopushko/test_nuget_expand/

When you build your target project you will get the .editorconfig file in the root directory of this project. It will be overwritten every time you build a project. Even if it was modified somehow by mistake the .editorconfig file will be overwritten on the build.

Conclusion

The solution is quite simple, but it made our team's life easier. We have added this NuGet package to all our projects and avoid desynchronization in code styles across all the repositories.


Written by igorlopushko | Programmer, Architect, Teacher
Published by HackerNoon on 2022/06/17