NML

NML project style cop setup and configuration

Posted on 25 April 2019
Francois Nel

Configuring StyleCop.Analyzers

More information: StyleCop.Analyzers on GitHub

  1. Create a file named Directory.Build.props in the same directory as your .sln solution file, containing the following configuration. This will add the global rule set to every project, install the StyleCop.Analyzers package for every project, and link the global stylecop.json file in every project. The package version will need to be periodically updated.
<Project>
    <!-- StyleCop Analyzers configuration -->
    <PropertyGroup>
        <CodeAnalysisRuleSet>$(SolutionDir)StyleCop.ruleset</CodeAnalysisRuleSet>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="StyleCop.Analyzers" Version="1.1.1-rc.114" PrivateAssets="all"/>
        <AdditionalFiles Include="$(SolutionDir)stylecop.json" Link="stylecop.json"/>
    </ItemGroup>
</Project>
  1. Create a file named StyleCop.ruleset in the same directory as your .sln solution file, containing the following rules. The rule set file defines what actions to take if the rules are broken, modify them to suit your needs. More info about the rules and their available fixes.
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Microsoft Managed Recommended Rules"
         Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. It is recommended to include this rule set in any custom rule set you create for your projects."
         ToolsVersion="10.0">
    <Localization ResourceAssembly="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.dll"
                  ResourceBaseName="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.Localized">
        <Name Resource="MinimumRecommendedRules_Name"/>
        <Description Resource="MinimumRecommendedRules_Description"/>
    </Localization>
    <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
        <Rule Id="CA1001" Action="Warning"/>
        <Rule Id="CA1009" Action="Warning"/>
        <Rule Id="CA1016" Action="Warning"/>
        <Rule Id="CA1033" Action="Warning"/>
        <Rule Id="CA1049" Action="Warning"/>
        <Rule Id="CA1060" Action="Warning"/>
        <Rule Id="CA1061" Action="Warning"/>
        <Rule Id="CA1063" Action="Warning"/>
        <Rule Id="CA1065" Action="Warning"/>
        <Rule Id="CA1301" Action="Warning"/>
        <Rule Id="CA1400" Action="Warning"/>
        <Rule Id="CA1401" Action="Warning"/>
        <Rule Id="CA1403" Action="Warning"/>
        <Rule Id="CA1404" Action="Warning"/>
        <Rule Id="CA1405" Action="Warning"/>
        <Rule Id="CA1410" Action="Warning"/>
        <Rule Id="CA1415" Action="Warning"/>
        <Rule Id="CA1821" Action="Warning"/>
        <Rule Id="CA1900" Action="Warning"/>
        <Rule Id="CA1901" Action="Warning"/>
        <Rule Id="CA2002" Action="Warning"/>
        <Rule Id="CA2100" Action="Warning"/>
        <Rule Id="CA2101" Action="Warning"/>
        <Rule Id="CA2108" Action="Warning"/>
        <Rule Id="CA2111" Action="Warning"/>
        <Rule Id="CA2112" Action="Warning"/>
        <Rule Id="CA2114" Action="Warning"/>
        <Rule Id="CA2116" Action="Warning"/>
        <Rule Id="CA2117" Action="Warning"/>
        <Rule Id="CA2122" Action="Warning"/>
        <Rule Id="CA2123" Action="Warning"/>
        <Rule Id="CA2124" Action="Warning"/>
        <Rule Id="CA2126" Action="Warning"/>
        <Rule Id="CA2131" Action="Warning"/>
        <Rule Id="CA2132" Action="Warning"/>
        <Rule Id="CA2133" Action="Warning"/>
        <Rule Id="CA2134" Action="Warning"/>
        <Rule Id="CA2137" Action="Warning"/>
        <Rule Id="CA2138" Action="Warning"/>
        <Rule Id="CA2140" Action="Warning"/>
        <Rule Id="CA2141" Action="Warning"/>
        <Rule Id="CA2146" Action="Warning"/>
        <Rule Id="CA2147" Action="Warning"/>
        <Rule Id="CA2149" Action="Warning"/>
        <Rule Id="CA2200" Action="Warning"/>
        <Rule Id="CA2202" Action="Warning"/>
        <Rule Id="CA2207" Action="Warning"/>
        <Rule Id="CA2212" Action="Warning"/>
        <Rule Id="CA2213" Action="Warning"/>
        <Rule Id="CA2214" Action="Warning"/>
        <Rule Id="CA2216" Action="Warning"/>
        <Rule Id="CA2220" Action="Warning"/>
        <Rule Id="CA2229" Action="Warning"/>
        <Rule Id="CA2231" Action="Warning"/>
        <Rule Id="CA2232" Action="Warning"/>
        <Rule Id="CA2235" Action="Warning"/>
        <Rule Id="CA2236" Action="Warning"/>
        <Rule Id="CA2237" Action="Warning"/>
        <Rule Id="CA2238" Action="Warning"/>
        <Rule Id="CA2240" Action="Warning"/>
        <Rule Id="CA2241" Action="Warning"/>
        <Rule Id="CA2242" Action="Warning"/>
    </Rules>
    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
        <!-- Errors -->
        <Rule Id="SA1027" Action="Error"/> <!-- Use tabs correctly -->
        <!-- Ignores -->
        <Rule Id="SA0001" Action="None"/> <!-- XML comment analysis disabled -->
        <Rule Id="SA1101" Action="None"/> <!-- Prefix local calls with this -->
        <Rule Id="SA1108" Action="None"/> <!-- Block statements should not contain embedded comments -->
        <Rule Id="SA1111" Action="None"/> <!-- Closing parenthesis should be on line of last parameter -->
        <Rule Id="SA1116" Action="None"/> <!-- Split parameters should start on line after declaration -->
        <Rule Id="SA1117" Action="None"/> <!-- Parameters should be on same line or separate lines -->
        <Rule Id="SA1118" Action="None"/> <!-- Parameters should be on same line or separate lines -->
        <Rule Id="SA1122" Action="None"/> <!-- Use string.Empty for empty strings -->
        <Rule Id="SA1129" Action="None"/> <!-- Do not use default value type constructor -->
        <Rule Id="SA1309" Action="None"/> <!-- Field names should not begin with underscore -->
        <Rule Id="SA1401" Action="None"/> <!-- Fields should be private -->
        <Rule Id="SA1407" Action="None"/> <!-- Arithmetic expressions should declare precedence -->
        <Rule Id="SA1408" Action="None"/> <!-- Conditional expressions should declare precedence -->
        <Rule Id="SA1413" Action="None"/> <!-- Use trailing comma in multi-line initializers -->
        <Rule Id="SA1501" Action="None"/> <!-- Statement should not be on a single line -->
        <Rule Id="SA1503" Action="None"/> <!-- Braces should not be omitted -->
        <Rule Id="SA1512" Action="None"/> <!-- Single-line comments should not be followed by blank line -->
        <Rule Id="SA1519" Action="None"/> <!-- Braces should not be omitted from multi-line child statement -->
        <Rule Id="SA1600" Action="None"/> <!-- Elements should be documented -->
        <Rule Id="SA1601" Action="None"/> <!-- Partial elements should be documented -->
        <Rule Id="SA1602" Action="None"/> <!-- Enumeration items should be documented -->
        <Rule Id="SA1604" Action="None"/> <!-- Element documentation should have summary -->
        <Rule Id="SA1605" Action="None"/> <!-- Partial element documentation should have summary -->
        <Rule Id="SA1633" Action="None"/> <!-- File should have header -->
        <!-- FWN: SA1009 should be configured in stylecop.json once spacing configs are available -->
        <Rule Id="SA1009" Action="None"/> <!-- Closing parenthesis should be spaced correctly -->
    </Rules>
</RuleSet>
  1. Create a file named stylecop.json in the same directory as your .sln solution file, containing the following settings. The JSON file configures the behaviour of certain rules, such as tabs vs. spaces. More info about the available JSON configurations.
{
    "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
    "settings": {
        "indentation": {
            "indentationSize": 4,
            "tabSize": 4,
            "useTabs": true
        },
        "layoutRules": {
            "newlineAtEndOfFile": "require"
        },
        "orderingRules": {
            "usingDirectivesPlacement": "outsideNamespace",
            "blankLinesBetweenUsingGroups": "omit"
        }
    }
}
  1. Remove [Ss]tyle[Cc]op.* from your repository's .gitignore if it exists.

  2. Remove all <CodeAnalysisRuleSet>...</CodeAnalysisRuleSet> tags from project .csproj files, to allow the tags be be overridden by the global rule set configured by Directory.Build.props in the first step.

  3. If you're using Rider, enable the following setting to allow Rider to read the global settings: Settings > Editor > Inspection Settings > "Read settings from editorconfig, project settings and rule sets".

  4. To avoid conflicts with Rider/Resharper's built in code cleanup, add the following settings to your (projectname).sln.DotSettings team-shared settings file and make sure it's checked into your git repository. More info about setting up team level settings for Rider/Resharper.

<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
  1. Linting will now be performed at build time, but only on changed files. Perform linting on all files by rebuilding the whole solution or by running code analysis in Visual Studio (Alt+F11). Fixes to issues identified by the linting can be applied solution wide in Visual Studio by going to a particular instance of the warning, pressing Alt+Enter, and applying the fix to the whole solution.

Original source guide: Linting C# in 2019 — StyleCop, Sonar, Resharper, Visual Studio and Roslyn

An error has occurred. This application may no longer respond until reloaded. Reload