Roslyn: SuppressMessage works in IDE but still produces warnings in build output

Created on 7 Oct 2019  路  12Comments  路  Source: dotnet/roslyn

Version Used:
VS 16.3.2
Steps to Reproduce:

  1. Create new c# .net core Console Project with following code
    ```c#
    using System;

    namespace ConsoleApp2
    {
    class Program
    {
    private string test;

        static void Main(string[] args)
        {
            var p = new Program() { test = "bl" };
            Console.WriteLine("Hello World!" + p.test);
        }
    }
    

    }

    ```

  2. Enable nullable in .csproj (field test will show green squigles with non initilized non-nullable warning)
  3. Add Gloabl suppression file with
    c# [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Code Quality", "CS8618:Non-nullable field is uninitialized. Consider declaring as nullable.", Justification = "<Pending>", Scope = "member", Target = "~F:ConsoleApp2.Program.test")]
    (warning in source code will vanish)

Expected Behavior:

Bild shows no warnings

Actual Behavior:
Build shows warning Program.cs(7,24,7,28): warning CS8618: Non-nullable field 'test' is uninitialized. Consider declaring the field as nullable.

Area-Analyzers Bug Resolution-Fixed

All 12 comments

@agocke What is the designed behavior here?

The build and error list output should match. This should be suppressing the warning, IIRC

This also applies to CS8602, CS8603, CS8618. CS8625

To provide some background on why I'm running into this - if you enable nullable types and then scaffold the Microsoft.AspNetCode.Identity.UI - you will get a million warnings related to nullable types. You can suppress most of them - except the last 100 CS86xx ones.

Compiler warnings cannot be suppressed using SuppressMessageAttribute. See https://github.com/dotnet/roslyn/issues/28479#issuecomment-414546343.

The bug here is the the attribute should _also_ have no impact inside the IDE.

Should it be? I really like the targeting of SuppressMessageAttribute (exclude an entire namespace) and it fits my situation perfectly. Unfortunately you can't do that with pragma's.

I guess, it's just a bit weird when it comes to Nullable types and external libraries.

I agree with @batkuip. What is the logic behind this? Why is this feature implemented like this? We can't scope the suppressions to a namespace, for exemple, like we do with other warnings.

I have changed this issue to be an IDE bug. The SuppressMessageAttribute should not be impacting the IDE behavior because the compiler ignores it. The feature request to make these attributes usable for compiler warnings is #6471.

A SuppressMessageAttribute has no impact on compiler diagnostics in IDE live analysis or compiler build output, and there is no public API from compiler layer to allow a host such as IDE to explicitly apply suppress message attribute suppressions. I believe there is a different issue here - likely CS8618 is not even reported when computing open file diagnostics OR IDE de-duping logic for build and live diagnostics has some bug.

@mavasani I have verified that SuppressMessageAttribute will suppress both CS0219 and CS8600 inside Visual Studio 2019 version 16.5 Preview 2.

NOTE: Implementing #6471 has potential of adding a build time performance overhead. Currently, compiler diagnostics can only be suppressed with pragmas, so all logic to compute effective compiler diagnostic severity + suppression is local to a file. Respecting SuppressMessageattribute suppressions means it would need to decode all global assembly level attributes. For example, SemanticModel.GetDiagnsotics(SyntaxTree) would now become much costlier operation as it has to force complete assembly attributes.

Example:

#nullable enable

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0059", Scope = "member", Target = "~M:SomeClass.SomeMethod")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "CS0219", Scope = "member", Target = "~M:SomeClass.SomeMethod")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "CS8600", Scope = "member", Target = "~M:SomeClass.SomeMethod")]

internal class SomeClass
{
    public void SomeMethod()
    {
        string value = null;
    }
}

Ah, I see the issue:

  1. IDE should not be invoking CompilationWithAnalyzers.GetEffectiveDiagnostics, which seems to be the one filtering out compiler diagnostics.
  2. We should harden the logic here to not invoke suppressMessageState.ApplySourceSuppressions for compiler diagnostics, and also add a corresponding assert in ApplySourceSuppressions that it is never invoked for a compiler diagnostic.

I will create a PR to fix it.

Was this page helpful?
0 / 5 - 0 ratings