Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change CodeAnalysis rules from 'Info' to 'Warning' after fixing all instances of the violations #7174

Open
elachlan opened this issue Dec 29, 2021 · 26 comments
Labels
Milestone

Comments

@elachlan
Copy link
Contributor

elachlan commented Dec 29, 2021

As a follow up to #5656 each code analysis rule that is marked as Action="Info" should be evaluated and migrated to Action="Warning" once all instances of the violations are fixed or marked with ignore.

To make the process as painless as possible. Each rule should be implemented in its own PR.

Before the merges:

List of rules to enable after resolving occurrences:

@elachlan
Copy link
Contributor Author

CA1837: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/ca1837

We can't use this one because it isn't available in older versions of .NET. When the team decides to no longer support versions below .NET 5 then this can be enabled.

@elachlan
Copy link
Contributor Author

elachlan commented Dec 30, 2021

CA2241: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/CA2241
This has lots of matches in msbuild\src\Build.UnitTests\FileUtilitiesRegex_Tests.cs

Example:

string winDirectory = string.Format("", _directoryStart);
string unixDirectory = string.Format("", _altDirectoryStart);

I don't know if this is on purpose. This would just result in an empty string afaik.

@elachlan
Copy link
Contributor Author

ca2249: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/ca2249

This one also has issues because of the missing overloads on string.Contains. So not all usages can be converted.

@elachlan
Copy link
Contributor Author

@Forgind I can't manage to get StyleCop Analyzers to run anymore. Are they working for you?

@Forgind
Copy link
Member

Forgind commented Dec 30, 2021

CA2241: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/CA2241 This has lots of matches in msbuild\src\Build.UnitTests\FileUtilitiesRegex_Tests.cs

Example:

string winDirectory = string.Format("", _directoryStart);
string unixDirectory = string.Format("", _altDirectoryStart);

I don't know if this is on purpose. This would just result in an empty string afaik.

The cases I saw looked like they should resolve to an empty string, so I think it's fine to replace those with string.Empty and skip the format part.

@Forgind
Copy link
Member

Forgind commented Dec 30, 2021

ca2249: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/ca2249

This one also has issues because of the missing overloads on string.Contains. So not all usages can be converted.

Does this also complain about cases like:

string s = "foobar";
int i = s.IndexOf("b");
if (i > 0) {
// Uses i
}

? Also, what do you mean by missing overloads? Like string.Contains requires a string, and we sometimes use a char? If that's the case, I'd leave the ones where we use a char; it's more efficient memory-wise to not allocate a string for no reason—though I guess it's probably short enough that the runtime wouldn't actually have to allocate anyway.

@Forgind
Copy link
Member

Forgind commented Dec 30, 2021

@Forgind I can't manage to get StyleCop Analyzers to run anymore. Are they working for you?

Do you mean locally or in PRs? I just tested a local build, and the analyzer seemed to work fine. If PR builds aren't catching it anymore, it might be throttled, but I don't know how to change that.

@elachlan
Copy link
Contributor Author

Locally, I am probably doing it wrong somehow. It has been a long while since I worked on this. Do I use visual studio 2019 release , 2022 release, or 2022 preview?

@Forgind
Copy link
Member

Forgind commented Dec 30, 2021

I don't think it matters. What are you doing to run them? I went to my msbuild repo and ran build.cmd. msbuild MSBuild.sln also worked, though it didn't upgrade the warning to an error.

@elachlan
Copy link
Contributor Author

ca2249: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/ca2249
This one also has issues because of the missing overloads on string.Contains. So not all usages can be converted.

Does this also complain about cases like:

string s = "foobar";
int i = s.IndexOf("b");
if (i > 0) {
// Uses i
}

? Also, what do you mean by missing overloads? Like string.Contains requires a string, and we sometimes use a char? If that's the case, I'd leave the ones where we use a char; it's more efficient memory-wise to not allocate a string for no reason—though I guess it's probably short enough that the runtime wouldn't actually have to allocate anyway.

yes, there is a char overload and there are functions which take different comparators than StringComparison.Ordinal. But those are only added in .NET 5.

@elachlan
Copy link
Contributor Author

CA2241: https://docs.microsoft.com/en-au/dotnet/fundamentals/code-analysis/quality-rules/CA2241 This has lots of matches in msbuild\src\Build.UnitTests\FileUtilitiesRegex_Tests.cs
Example:

string winDirectory = string.Format("", _directoryStart);
string unixDirectory = string.Format("", _altDirectoryStart);

I don't know if this is on purpose. This would just result in an empty string afaik.

The cases I saw looked like they should resolve to an empty string, so I think it's fine to replace those with string.Empty and skip the format part.

Awesome. I will submit a PR with the fixes.

@elachlan
Copy link
Contributor Author

@rainersigwald some of these PRs are about to increase churn pretty heavily. How would you like me to handle larger change sets like those?

For now I will avoid any analyzers with over 1-2k warnings.

@elachlan
Copy link
Contributor Author

@Forgind I just want to summarise where I am up to on this. Basically we ran into an issue where some of the analysers fail the build because of code pulled in from nuget packages e.g :

This is because of how analyzers work with .editorconfigs and .globalconfigs. The main difference between the two formats is that .editorconfigs apply to a directory where as .globalconfigs apply to a project. So with the switch to .globalconfigs it now means all code is analyzed not just the code in the project directory.

This was all explained in dotnet/roslyn#55992. Where many people gave input on the system. This culminated in this pull request to demonstrate a solution:

There is a catch in that solution, in that the added NuGet.config creates a folder in the project directory as a cache for all the nuget packages used by the solution. This means the solution avoids using the global cache. This resulted in an extra 2GB being used on my machine and extra downloading of packages when a first did a project restore. The advantage of this method is that it specifically excludes the nuget package code files from being analyzed.

The other solution is that we move back to using the .editorconfig and avoid the .globalconfig so that the analyzers are applied to the whole solution directory and excludes any files in the project that are included from outside that directory (code files from nuget packages). I like this option because it keeps it simple. But it means the .editorconfig becomes massive.

There may be another method around this but it wasn't suggested from the other people. Could you please discuss with the team and then get back to me? I will then make the required changes.

@elachlan
Copy link
Contributor Author

@sharwell do you have any thoughts of the configuration of analyzers based on the above issues?

@Forgind
Copy link
Member

Forgind commented Jan 26, 2022

I'd like to wait to see what sharwell suggests. Personally, both solutions sound problematic in their own ways, and although I'd personally be fine with wasting a couple gbs, I suspect at least one person on my team will be strongly opposed. On the other hand, it would be frustrating to have a massive .editorconfig.

One other option I think we should at least consider is only promoting analysis messages to warnings if we can do some without a warning coming from anything we depend on. That's a stupid requirement, but it may be the most pragmatic. We have a lot of issues we want to tackle for 17.2 with major customer impact, and you've probably noticed we're pretty far behind even with just reviewing and merging what's already open.

@elachlan
Copy link
Contributor Author

I'd like to wait to see what sharwell suggests. Personally, both solutions sound problematic in their own ways, and although I'd personally be fine with wasting a couple gbs, I suspect at least one person on my team will be strongly opposed. On the other hand, it would be frustrating to have a massive .editorconfig.

One other option I think we should at least consider is only promoting analysis messages to warnings if we can do some without a warning coming from anything we depend on. That's a stupid requirement, but it may be the most pragmatic. We have a lot of issues we want to tackle for 17.2 with major customer impact, and you've probably noticed we're pretty far behind even with just reviewing and merging what's already open.

We need to address this as it is the same issue we ran into for #7571, but its worse because code style can be different between the nuget package code and msbuild.

@sharwell are you able to look at #7174 (comment) and let us know your thoughts?

@Nirmal4G
Copy link
Contributor

You should add file scoped namespaces to the list, is there a code for it?

@sharwell
Copy link
Member

sharwell commented Apr 29, 2022

@sharwell are you able to look at #7174 (comment) and let us know your thoughts?

Style rules in .globalconfig will not apply to a correctly authored NuGet package. If you are running into problems with the global NuGet cache, there is a bug in one or more NuGet packages which needs to be corrected (or have a workaround). It's not clear which package(s) or rule(s) are involved in the problem you saw.

@rainersigwald
Copy link
Member

@sharwell the package in question is microsoft.codeanalysis.collections, for instance in this check run: https://github.com/dotnet/msbuild/runs/6150398057.

@sharwell
Copy link
Member

sharwell commented Apr 29, 2022

There are a few ways to resolve:

  • A good solution for the NuGet package itself is to use the approach of IsExternalInit, where the NuGet package contains the source code, but it's copied to the obj directory by build logic and included in the compilation from there. The copy operation would know to rename files from *.cs (which is how they appear in Roslyn, since they aren't generated code in that repository) to *.g.cs so they are automatically treated as generated code by downstream builds.
  • You can work around the issue by setting the generated_code property in .globalconfig for each of the impacted files
  • You can work around the issue by creating a DiagnosticSuppressor that knows how to suppress style rules in the files in this package. This is how Roslyn modified VSTHRD200 behavior after a feature request to add logic to the rule itself was rejected (VSTHRD200 should not trigger on test methods microsoft/vs-threading#670).

@rainersigwald
Copy link
Member

  • You can work around the issue by setting the generated_code property in .globalconfig for each of the impacted files

My understanding is that this isn't possible because we don't know an absolute path for the NuGet packages folder. Is that not the case?

@sharwell
Copy link
Member

My understanding is that this isn't possible because we don't know an absolute path for the NuGet packages folder. Is that not the case?

I'm not completely sure here. For central builds (with determinism enabled), the paths should be normalized to a /_/ prefix of some sort that's predictable. I'm not sure if there's something similar for local builds.

Forgind pushed a commit that referenced this issue Apr 29, 2022
#7571)

Relates to #7174
https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1518.md

The two remaining warnings/suggestions are from RoslynImmutableInterlocked pulled in from Microsoft.CodeAnalysis.Collections in Microsoft.Build.Framework.

Solution for the warnings from the nuget package is outlined in dotnet/roslyn#55992
@vlada-shubina
Copy link
Member

Code-style rules (IDE) are also useful.
They can be enabled using dotnet_analyzer_diagnostic.category-Style.severity = warning or individually.

@vlada-shubina
Copy link
Member

vlada-shubina commented Jan 20, 2023

SA1010 - #7205

in ObjectModelHelpers (shared file), this check is not flagged as warning. Probably worth checking why.

ignore me, it is SA1110.

@vlada-shubina
Copy link
Member

Additional checks to enable once fixed:

# Cast is redundant
dotnet_diagnostic.IDE0004.severity = suggestion

# IDE0005: Remove unnecessary usings/imports
dotnet_diagnostic.IDE0005.severity = warning

# Use explicit type instead of 'var'
dotnet_diagnostic.IDE0008.severity = suggestion

# Populate switch
dotnet_diagnostic.IDE0010.severity = suggestion

# Null check can be simplified
dotnet_diagnostic.IDE0016.severity = suggestion

# Object initialization can be simplified
dotnet_diagnostic.IDE0017.severity = suggestion

# Variable declaration can be inlined
dotnet_diagnostic.IDE0018.severity = suggestion

# Use pattern matching
dotnet_diagnostic.IDE0019.severity = suggestion
dotnet_diagnostic.IDE0020.severity = suggestion

# Use expression body for constructor
dotnet_diagnostic.IDE0021.severity = suggestion

# Use expression body for method
dotnet_diagnostic.IDE0022.severity = suggestion

# Use expression body for conversion operator
dotnet_diagnostic.IDE0023.severity = suggestion

# Use block body for operator
dotnet_diagnostic.IDE0024.severity = suggestion

# Use expression body for property
dotnet_diagnostic.IDE0025.severity = suggestion

# Use expression body for indexer
dotnet_diagnostic.IDE0026.severity = suggestion

# Use expression body for accessor
dotnet_diagnostic.IDE0027.severity = suggestion

# Collection initialization can be simplified
dotnet_diagnostic.IDE0028.severity = suggestion

# Null check can be simplified
dotnet_diagnostic.IDE0031.severity = suggestion

# Use auto property
dotnet_diagnostic.IDE0032.severity = suggestion

# 'default' expression can be simplified
dotnet_diagnostic.IDE0034.severity = suggestion

# Member name can be simplified
dotnet_diagnostic.IDE0037.severity = suggestion

# Use local function
dotnet_diagnostic.IDE0039.severity = suggestion

# Null check can be simplified
dotnet_diagnostic.IDE0041.severity = suggestion

# Variable declaration can be deconstructed
dotnet_diagnostic.IDE0042.severity = suggestion

# Made field readonly
dotnet_diagnostic.IDE0044.severity = suggestion

# 'if' statement can be simplified
dotnet_diagnostic.IDE0045.severity = suggestion
dotnet_diagnostic.IDE0046.severity = suggestion

# Parentheses can be removed
dotnet_diagnostic.IDE0047.severity = suggestion

# Parentheses should be added for clarity
dotnet_diagnostic.IDE0048.severity = suggestion

# Member name can be simplified
dotnet_diagnostic.IDE0049.severity = suggestion

# Use compound assignment
dotnet_diagnostic.IDE0054.severity = suggestion

# Indexing can be simplified
dotnet_diagnostic.IDE0056.severity = suggestion

# Slice can be simplified
dotnet_diagnostic.IDE0057.severity = suggestion

# Expression value is never used
dotnet_diagnostic.IDE0058.severity = suggestion

# Unnecessary assignment of a value
dotnet_diagnostic.IDE0059.severity = suggestion

# Remove unused parameter
dotnet_diagnostic.IDE0060.severity = suggestion

# Use expression body for a local function
dotnet_diagnostic.IDE0061.severity = suggestion

# Local function can be made static
dotnet_diagnostic.IDE0062.severity = suggestion

# Using directives must be placed outside of a namespace declaration
dotnet_diagnostic.IDE0065.severity = suggestion

# Use 'switch' expression
dotnet_diagnostic.IDE0066.severity = suggestion

# 'GetHashCode' implementation can be simplified
dotnet_diagnostic.IDE0070.severity = suggestion

# Interpolation can be simplified
dotnet_diagnostic.IDE0071.severity = suggestion

# Populate switch
dotnet_diagnostic.IDE0072.severity = suggestion

# Use compound assignment
dotnet_diagnostic.IDE0074.severity = suggestion

# Conditional expression can be simplified
dotnet_diagnostic.IDE0075.severity = suggestion

# Use pattern matching
dotnet_diagnostic.IDE0078.severity = suggestion
dotnet_diagnostic.IDE0083.severity = suggestion

# 'typeof' can be converted to 'nameof'
dotnet_diagnostic.IDE0082.severity = suggestion

# 'new' expression can be simplified
dotnet_diagnostic.IDE0090.severity = suggestion

# Simplify LINQ expression
dotnet_diagnostic.IDE0120.severity = suggestion

# namespace does not match folder structure
dotnet_diagnostic.IDE0130.severity = suggestion

# Null check can be clarified
dotnet_diagnostic.IDE0150.severity = suggestion

# Convert to block scoped namespaces
dotnet_diagnostic.IDE0160.severity = suggestion

# Simplify property pattern
dotnet_diagnostic.IDE0170.severity = suggestion

# Use tuple to swap values
dotnet_diagnostic.IDE0180.severity = suggestion

# Use tuple to swap values
dotnet_diagnostic.IDE0180.severity = suggestion

# Lambda expression can be removed
dotnet_diagnostic.IDE0200.severity = suggestion

# Convert to top-level statements
dotnet_diagnostic.IDE0210.severity = suggestion

# 'foreach' statement implicitly converts
dotnet_diagnostic.IDE0220.severity = suggestion

# Use UTF-8 string literal
dotnet_diagnostic.IDE0230.severity = suggestion

# Nullable directives
dotnet_diagnostic.IDE0240.severity = suggestion
dotnet_diagnostic.IDE0241.severity = suggestion

# Struct can be made 'readonly'
dotnet_diagnostic.IDE0250.severity = suggestion

# Null check can be simplified
dotnet_diagnostic.IDE0270.severity = suggestion

# naming rule violation
dotnet_diagnostic.IDE1006.severity = suggestion

@stan-sz
Copy link
Contributor

stan-sz commented Jan 31, 2023

Regarding some of the rules, per @rainersigwald's comment in https://github.com/dotnet/msbuild/pull/7953/files/c517eaada858f113d7bbf6c06cdf6044b5accb15#r1051020281, it does make sense to leave them as warning for the inner-loop agility, while turn warnings to errors at CI builds.

@AR-May AR-May added the triaged label Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants