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

Add a new SuppressMessageAttribute target scope to suppress diagnosti… #31092

Merged

Conversation

mavasani
Copy link
Contributor

@mavasani mavasani commented Nov 10, 2018

…cs in a namespace and all its descendant symbols

Fixes #486

This SuppressMessageAttribute feature has been requested for a very long time and still gets frequent customer requests to date.

The current "Namespace" target scope for SuppressMessageAttribute suppresses diagnostics only in nodes directly contained within the namespace, but not in any of it's descendant symbols. This makes it very tedious to suppress certain analyzer diagnostics in entire namespace as one needs to add suppressions to individual types/namespaces within the namespace. This also creates a maintenance nightmare.

This PR adds a new target scope "NamespaceAndChildren" which suppresses diagnostics on the corresponding namespace and all its descendant symbols/members. Better naming suggestions for this scope name are welcome!

Example: [assembly: SuppressMessage("Test", "Declaration", Scope="NamespaceAndChildren", Target="N.N1")]

…cs in a namespace and all its descendant symbols

Fixes dotnet#486

This SuppressMessageAttribute feature has been requested for a very long time and still gets frequent customer requests to date.

The current "Namespace" target scope for SuppressMessageAttribute suppresses diagnostics only in nodes directly contained within the namespace, but in none of it's child symbols. This makes it very tedious to suppress certain analyzer diagnostics in entire namespace as one needs to add suppressions to individual types/namespaces within the namespace. This also creates a maintenance nightmare.

This PR adds a new target scope "NamespaceAndChildren" which suppresses diagnostics on the corresponding namespace and all its descendant symbols/members. Better naming suggestions for this scope name are welcome!
@mavasani
Copy link
Contributor Author

mavasani commented Nov 10, 2018

retest windows_release_vs-integration_prtest please #Resolved

@josefpihrt
Copy link
Contributor

josefpihrt commented Nov 12, 2018

Maybe it would be better to use name "NamespaceAndDescendants" to keep established terminology. #Resolved

@mavasani
Copy link
Contributor Author

mavasani commented Nov 12, 2018

Maybe it would be better to use name "NamespaceAndDescendants" to keep established terminology.

That seems reasonable. If we don't reach a consensus on the terminology in the PR, then I will follow-up offline on preferred terminology once the PR has been reviewed.

Ping @dotnet/roslyn-analysis @dotnet/roslyn-compiler for reviews. #Resolved

@mavasani
Copy link
Contributor Author

mavasani commented Nov 13, 2018

Ping @dotnet/roslyn-analysis @dotnet/roslyn-compiler for reviews - Note that this change only affects suppression for analyzer diagnostics, compiler diagnostics can only be suppressed with pragmas. #Resolved

};

private static bool TryGetTargetScope(SuppressMessageInfo info, out TargetScope scope)
{
string scopeString = info.Scope != null ? info.Scope.ToLowerInvariant() : null;
Copy link
Member

@jcouv jcouv Nov 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

info.Scope != null ? info.Scope.ToLowerInvariant() : null [](start = 33, length = 57)

nit: could be simplified to info.Scope?.ToLowerInvariant() #Resolved

@jcouv
Copy link
Member

jcouv commented Nov 14, 2018

                    inImmediatelyContainingSymbol = false;

Not caused by your change, but I'm a little surprised by this.
I would have expected that we would set inImmediatelyContainingSymbol to false after the foreach, when declaredSymbols was not empty.
I think we set inImmediatelyContainingSymbol to false too early, for scenarios where a node declares multiple symbols. For example, with a multi-declaration field, all the declared symbols should be treated with the same inImmediatelyContainingSymbol (we shouldn't change it between declared symbols).

Consider adding a test and filing an issue if confirmed. #Resolved


Refers to: src/Compilers/Core/Portable/DiagnosticAnalyzer/SuppressMessageAttributeState.cs:174 in 677d520. [](commit_id = 677d520, deletion_comment = False)

await VerifyCSharpAsync(@"
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage(""Test"", ""Declaration"", Scope=""NamespaceAndChildren"", Target=""N.N1"")]
Copy link
Member

@jcouv jcouv Nov 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NamespaceAndChildren [](start = 62, length = 20)

Consider using varied casings for "NamespaceAndChildren" #Resolved

@mavasani
Copy link
Contributor Author

                    inImmediatelyContainingSymbol = false;

Your observation is correct. However, the value of this flag is only used for namespace symbols, hence there is no observable effect with your proposed change. I will still make the suggested change as that is a more correct implementation.


In reply to: 438849151 [](ancestors = 438849151)


Refers to: src/Compilers/Core/Portable/DiagnosticAnalyzer/SuppressMessageAttributeState.cs:174 in 677d520. [](commit_id = 677d520, deletion_comment = False)

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks (iteration 1)

@jcouv jcouv self-assigned this Nov 14, 2018
};

private static bool TryGetTargetScope(SuppressMessageInfo info, out TargetScope scope)
{
string scopeString = info.Scope != null ? info.Scope.ToLowerInvariant() : null;
Copy link
Member

@jaredpar jaredpar Nov 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could use info.Scope?.ToLowerInvariant() #Resolved

@jaredpar
Copy link
Member

jaredpar commented Nov 14, 2018

    private static readonly SmallDictionary<string, TargetScope> s_suppressMessageScopeTypes = new SmallDictionary<string, TargetScope>()

Why not use an invariant comparer here to avoid the ToLowerInvariant allocations below? #Resolved


Refers to: src/Compilers/Core/Portable/DiagnosticAnalyzer/SuppressMessageAttributeState.cs:15 in 677d520. [](commit_id = 677d520, deletion_comment = False)

Copy link
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@mavasani
Copy link
Contributor Author

I am going to retain the current terminology and file a documentation bug for the implications of the new scope


In reply to: 437902179 [](ancestors = 437902179)

@mavasani
Copy link
Contributor Author

Filed documentation bug: https://github.com/dotnet/docs/issues/9046

@mavasani
Copy link
Contributor Author

retest windows_release_vs-integration_prtest please

@mavasani mavasani merged commit 8740f8b into dotnet:dev16.0-preview2 Nov 15, 2018
@mavasani
Copy link
Contributor Author

Filed #31196 to finalize the naming for the new suppression scope.

@ericbl
Copy link

ericbl commented Nov 17, 2018

I arrive too late in the battle, but brainstorming on the topic yesterday (for Roslyn FxCop on .NET Standard library), is the new scope very necessary? What about NOT specifying the scope and extending the 'inclusive' strategy of project wide validity to the given target?

In the GlobalSuppresion file, if you don't specify neither scope not target, the SuppressionMessage is valid for the whole project.
We could imagine specifying only the target, but not the scope, and whatever the target is (e.g. namespace or type), the suppression message would apply for everything within this target and all descendants items, following the 'include all' strategy of the project wide SuppressionMessage.

Where does the scope 'type' exactly apply?
Think nested classes: are the sub classes considered in the scope 'type' or not?
If not, having a target without a scope could make the difference.
Or we need yet another scope 'typeAndChildren' here...

@nelsonprsousa
Copy link

nelsonprsousa commented Dec 13, 2018

This is just awesome, I am looking forward for it. When will it be available and how can I update to get it? Thanks!

Edit: I am not sure where this will be applied. Some Visual Studio version? .NET Framework version?

@mavasani
Copy link
Contributor Author

We could imagine specifying only the target, but not the scope, and whatever the target is (e.g. namespace or type), the suppression message would apply for everything within this target and all descendants items, following the 'include all' strategy of the project wide SuppressionMessage.

@ericbl That seems like a very non-explicit approach and is not quite intuitive compared to an explicitly specified scope. Also it will be confusing when target is a type as the default behavior for types is to suppress it within everything under a type.

@mavasani
Copy link
Contributor Author

This is just awesome, I am looking forward for it. When will it be available and how can I update to get it? Thanks!

@nelsonprsousa This feature should be available with Dev16.0 preview 2. Given that the primary use case here is suppression during CI, you need to ensure that compiler toolset is at least the one that ships with this preview or later. You can follow this page for preview releases: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview

@nelsonprsousa
Copy link

This is just awesome, I am looking forward for it. When will it be available and how can I update to get it? Thanks!

@nelsonprsousa This feature should be available with Dev16.0 preview 2. Given that the primary use case here is suppression during CI, you need to ensure that compiler toolset is at least the one that ships with this preview or later. You can follow this page for preview releases: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview

You guys rock!

@mavasani
Copy link
Contributor Author

FYI: The new scope has been renamed to NamespaceAndDescendants (#31940)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants