Roslyn-analyzers: Disable CA1822 on ASP.Net Startup Classes etc

Created on 8 Jul 2020  路  20Comments  路  Source: dotnet/roslyn-analyzers

Classes like ConfigureServices are being marked with CA1822 as a fix. If the method is static it will not work unless I am missing something.

This also occurs in controller methods which don't access any instance data. (Again won't work if you apply the fix)

Most helpful comment

All 20 comments

Could you let us know the version of the analyzer you are using? We did a couple of updates to the rule to try to have better results for web developpers: https://github.com/dotnet/roslyn-analyzers/blob/master/src/NetAnalyzers/Core/Microsoft.CodeQuality.Analyzers/QualityGuidelines/MarkMembersAsStatic.cs#L255-L272

BTW if you see any missing case please feel free to let us know (ideally with a working example as we are not expert with web dev).

I am using the latest:

image

And thank you for the input, if I do notice anything will surely let you know.

Interesting... Could you confirm that the controller methods you are referring to have one of the attributes I have listed in the other comment?

Regarding the ConfigureServices you are mentioning a class but the doc seems to suggest it is a method on a Startup class (see https://docs.microsoft.com/aspnet/core/fundamentals/startup?view=aspnetcore-3.1). If that's what you are referring to then yes it seems more convention based methods need to be handled for web.

@mavasani We often have FPs for web apps, do you know someone from asp.net team that could help identify all (the main) cases we need to handle? I can try to browse the doc but it seems I am not so good at it.

We often have FPs for web apps, do you know someone from asp.net team that could help identify all (the main) cases we need to handle? I can try to browse the doc but it seems I am not so good at it.

Probably @Pilchie can help find a good contact?

@pranavkm ?

do you know someone from asp.net team that could help identify all (the main) cases we need to handle

What sort of details do you need from us?

You might find this related.

As a FYI this is also occurring on Entity Framework properties that are marked get; set; with or without [NotMapped] but especially with { [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] get; [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] set; }

@pranavkm We'd like to know all methods that should not be marked as static for a web application either because they are convention based methods or because they have some specific attribute on them. In case of the attribute, please could you share the attribute. In case of a convention method, please specify if the method has to be in a specific class (specific name, or class inherits from some base class or something else).

Regarding properties, as I was mentioning in #2834

Lastly, I have some trouble understanding why properties, especially auto-properties, are flagged. It seems quite rare to have static properties compared to methods. I could see the point of flagging a property only returning/dealing with a constant/static value but auto-properties kindda mean I want an instance "object".

There are a few more with JSInterop APIs, SignalR hub method etc, but the general pattern a lot of APIs in ASP.NET Core is called via reflection. The rule of thumb is that these APIs are public. Are we able to change the analyzer to skip public APIs? It guarantees that the change is non-breaking and you don't have to play whack-a-mole with frameworks that heavily rely on reflection.

Tagging @sharwell as well

Are we able to change the analyzer to skip public APIs?

No, the analyzer is designed to flag all non-static APIs that can be made static. We should not change that behavior.

It guarantees that the change is non-breaking and you don't have to play whack-a-mole with frameworks that heavily rely on reflection.

Unfortunately, large bucket of analyzers will lead to false positives on any frameworks that use non-declarative technique for runtime code execution, such as reflection, MEF, etc. It is not feasible to ensure each analyzer handle/special case all scenarios for such frameworks. If there are only a handful of special cases, then we can update the analyzer to handle it. Otherwise, it seems better from a maintainability perspective that each such framework write a special DiagnosticSuppressor that ships with the framework and suppresses false positives that are applicable and special just for the framework.

A classic example for this was https://github.com/dotnet/roslyn/issues/30172, where unused/uninitialized field diagnostic for certain fields are false positives in context of Unity framework that uses reflection to initialize and/or read the field. Unity wrote a bunch of diagnostic suppressors that ship with the framework and now avoid false positives: https://github.com/microsoft/Microsoft.Unity.Analyzers/blob/master/doc/index.md#diagnostic-suppressors. I believe the correct solution here would be a similar set of diagnostic suppressors to ship with ASP.NET core SDK.

Seems like the suppressors can potentially go here: https://github.com/dotnet/aspnetcore/tree/master/src/Analyzers/Analyzers/src

@mavasani Shall I start to add some more aspnet related exceptions in the analyzer or do you want to stop exclusions for now?

@Evangelink I think it might be better to instead make the analysis conservative by not analyzing public APIs by default as @pranavkm suggested. We can add an option to switch the analyzer to perform public API analysis when user explicitly requests it. This will still generate false positives for the latter case, but they are not as critical as it is not on by default.

@pranavkm What would be the best way we can detect if a project is an asp.net core project? Say, any MSBuild property or by looking for a specific reference assembly or a well known type? If so, we can just make a more targeted fix to skip public APIs for asp.net core projects.

The presence of the FrameworkReference would be the most accurate way to detect it for apps targeting 3.1 or newer: https://github.com/dotnet/sdk/blob/master/src/WebSdk/Web/Sdk/Sdk.props#L35. For 2.1, the presence of a package reference to Microsoft.AspNetCore.App would be the way to go about it.

If evaluating ItemGroups is cumbersome, you could wing it and detect the presence of the Web.SDK:
https://github.com/dotnet/sdk/blob/master/src/WebSdk/Web/Sdk/Sdk.props#L17. It should cover the vast majority of projects.

Thanks. Seems it would be reasonable to define a new property name UsingMicrosoftNETSdkWeb below: https://github.com/dotnet/roslyn-analyzers/blob/641b5e8b6ddf8ccf095f5ac58a346ed1de546a18/src/Utilities/Compiler/Options/MSBuildPropertyOptionNames.cs#L5-L12

and then use the below API in the analyzer to fetch this option: https://github.com/dotnet/roslyn-analyzers/blob/a7c2ef6fff162581bc3ff55059cb7f8ae05e571c/src/Utilities/Compiler/Options/AnalyzerOptionsExtensions.cs#L505-L511

I will simplify the API above to not require passing in a symbol/syntax tree as it is a compilation level option.

I have a PR out for this: https://github.com/dotnet/roslyn-analyzers/pull/3875. Verified that the issue is fixed with locally built NuGet package with this change. @Evangelink can you please review?

As a FYI this is also occurring on Entity Framework properties that are marked get; set; with or without [NotMapped] but especially with { [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] get; [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] set; }

@mavasani How do you want to handle this comment?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stephentoub picture stephentoub  路  3Comments

paulomorgado picture paulomorgado  路  3Comments

paulomorgado picture paulomorgado  路  3Comments

fschlaef picture fschlaef  路  4Comments

KrisVandermotten picture KrisVandermotten  路  3Comments