How do I specify a custom code analysis ruleset for multiple projects in a solution using Visual Studio 2019?
Asked Answered
N

4

9

I've got a custom code analysis ruleset that I want to apply to all configurations of multiple projects in my solution but can't see how I can do it.

To be clear, I'm looking for a way (if any) of doing this in a single step rather then editing the properties of each project from the IDE.

I found this guidance so far: https://learn.microsoft.com/en-us/visualstudio/code-quality/how-to-configure-code-analysis-for-a-managed-code-project?view=vs-2019#specify-rule-sets-for-multiple-projects-in-a-solution

But it doesn't seem to be correct. In Visual Studio 2019, if I go to Analyze > Configure Code Analysis > For Solution I get a blank property page with the message:

NOTE: This property page has been deprecated and will be removed in a future product release.

Is there another way I can do this? I have lots of projects :(

Thanks.

Nissa answered 12/9, 2019 at 10:37 Comment(0)
N
5

I've had no answers about if there's a way to do this in Visual Studio so I've had to resort to altering .csproj files directly in a batch fashion.

This script I found by John Robbins is excellent: https://www.wintellect.com/batch-updating-changing-visual-studio-projects-with-powershell/

After installation, my usage was like this in case anyone is interested:

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "CodeAnalysisRuleSet" = ".\SystemStandard.ruleset" }

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "RunCodeAnalysis" = "false" }

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "TreatWarningsAsErrors" = "true" } 
Nissa answered 16/9, 2019 at 9:57 Comment(1)
I also have vbproj in a large solution and can't just enable treatwarningsaserrors or even turn on strict. Yes I inherited legacy code...and want to search for dead code with this ruleset #30974933Rectrix
I
5

To specify a rule set for a project, use the CodeAnalysisRuleSet MSBuild property.

To do that, there are several ways you can customize your build

Impressionism answered 12/9, 2019 at 21:11 Comment(2)
Yes, indeed. But my question is, how to do this for all configurations of all projects in a single or simple step rather than editing the properties of each project individually via the IDE.I'll adjust my question to make it clearer.Nissa
@Nissa Late to the party, but this should do the trick: https://mcmap.net/q/1180864/-how-do-i-specify-a-custom-code-analysis-ruleset-for-multiple-projects-in-a-solution-using-visual-studio-2019Tum
N
5

I've had no answers about if there's a way to do this in Visual Studio so I've had to resort to altering .csproj files directly in a batch fashion.

This script I found by John Robbins is excellent: https://www.wintellect.com/batch-updating-changing-visual-studio-projects-with-powershell/

After installation, my usage was like this in case anyone is interested:

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "CodeAnalysisRuleSet" = ".\SystemStandard.ruleset" }

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "RunCodeAnalysis" = "false" }

dir -recurse *.csproj | Set-ProjectProperties -OverrideDefaultProperties -CustomConfigurationProperties @{ "TreatWarningsAsErrors" = "true" } 
Nissa answered 16/9, 2019 at 9:57 Comment(1)
I also have vbproj in a large solution and can't just enable treatwarningsaserrors or even turn on strict. Yes I inherited legacy code...and want to search for dead code with this ruleset #30974933Rectrix
T
3

If I understand the question correctly, this can be done quite easily by following the steps outlined in this blog post.

The Directory.Build.props approach

The guide is written with StyleCop in mind but the same step should work with any analyzer.

  1. Create a file named Directory.Build.props (use this exact casing) along with your .sln file, i.e. at the top-level of your project. Its content should be something like this:
<Project>
  <PropertyGroup>
    <!-- This part specifies the ruleset file name. Change to something
         more appropriate if not using StyleCop. -->
    <CodeAnalysisRuleSet>$(SolutionDir)StyleCop.ruleset</CodeAnalysisRuleSet>
  </PropertyGroup>
  <!-- This part adds StyleCop as a reference in all projects + makes the 
       top-level stylecop.json file be used by all projects. Skip this
       altogether if you are not spefically using StyleCop. -->
  <ItemGroup>    
    <PackageReference Include=”StyleCop.Analyzers” Version=”1.1.1-rc.108" PrivateAssets=”all” />
    <AdditionalFiles Include=”$(SolutionDir)stylecop.json” Link=”stylecop.json” />
  </ItemGroup>
</Project>
  1. Create a StyleCop.ruleset file with your analyzer configuration.

That's it. The next time you run dotnet build or build your project in Visual Studio (you might have to close/reopen the solution if you have it open), these rules should apply.


For reference, here is the Directory.Build.props file in a project of mine: https://github.com/perlun/perlang/blob/master/Directory.Build.props

Tum answered 14/10, 2020 at 19:4 Comment(1)
This will work on dotnet build but not working on Visual Studio when editing the source file. It editor will still show the errors even if it was suppressed in the rule set specify with this method.Loathing
G
0

If projects in your solution have a hierarchical structure, meaning they reference each other and have a common, most abstract base that is root in the structure similar to this:

Common
├── Worker
└── Persistence
    └── API

...then you can reference StyleCop.Analyzers package in your root project and set the value of <PrivateAssets> tag to none:

<ItemGroup>
  <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    <PrivateAssets>none</PrivateAssets>
  </PackageReference>
</ItemGroup>

all is set by default when you add the StyleCop.Analyzers package reference to your project. What does it mean?

You might be using a dependency purely as a development harness and might not want to expose that to projects that will consume your package. In this scenario, you can use the PrivateAssets metadata to control this behavior. ~ Docs

So, by default StyleCop.Analyzers will only be enabled in the project in which you explicitly reference the package. But in almost all code bases I've been part of, enforcing the StyleCode rules in all projects in solution was desired (almost all, except for projects with auto-generated code e.g. EF migrations). Changing all to none in the package reference metadata will result in passing down the styling rules to all projects that depend on it.

Solution

Summarizing, the root project Common will have to reference StyleCop.Analyzers package while setting <PrivateAssets> to none:

<ItemGroup>
  <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    <PrivateAssets>none</PrivateAssets>
  </PackageReference>
</ItemGroup>

and Worker or Persistence or any other dependent project will only have to reference the previous layer, which is common practice in any layered architecture anyway:

<ItemGroup>
    <ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>
Gaslit answered 9/5, 2021 at 22:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.