File: Diagnostics\Suppression\SuppressionTests.cs
Web Access
Project: src\src\Features\CSharpTest\Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Features.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.Suppression;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.CSharp.Shared.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.Suppression;
 
public abstract partial class CSharpSuppressionTests : AbstractSuppressionDiagnosticTest_NoEditor
{
    protected override ParseOptions GetScriptOptions() => Options.Script;
 
    protected internal override string GetLanguage() => LanguageNames.CSharp;
 
    #region "Pragma disable tests"
 
    public abstract partial class CSharpPragmaWarningDisableSuppressionTests : CSharpSuppressionTests
    {
        protected sealed override int CodeActionIndex
        {
            get { return 0; }
        }
 
        [Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
        public sealed class CompilerDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
                => Tuple.Create<DiagnosticAnalyzer, IConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
 
            [Fact]
            public Task TestPragmaWarningDirective()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0;|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            int x = 0;
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
        }
    }
    """);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/26015")]
            public Task TestPragmaWarningDirectiveAroundMultiLineStatement()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|string x = @"multi
    line";|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            string x = @"multi
    line";
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
        }
    }
    """);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/56165")]
            public Task TestPragmaWarningDirectiveAroundMultiLineInterpolatedString()
                => TestAsync(
        """
 
        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void Method()
            {
                var s = $@"
        hi {[|new Session()|]}
        ";
            }
        }
        """,
        $$"""

        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void Method()
            {
        #pragma warning disable CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
                var s = $@"
        hi {new Session()}
        ";
        #pragma warning restore CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
            }
        }
        """);
 
            [Fact]
            public Task TestMultilineStatementPragmaWarningDirective()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0
                  + 1;|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            int x = 0
                  + 1;
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
        }
    }
    """);
 
            [Fact]
            public Task TestMultilineStatementPragmaWarningDirective2()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0,
                y = 1;|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            int x = 0,
                y = 1;
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
        }
    }
    """);
 
            [Fact]
            public Task TestPragmaWarningDirectiveWithExistingTrivia()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            // Start comment previous line
            /* Start comment same line */ [|int x = 0;|] // End comment same line
            /* End comment next line */
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
            // Start comment previous line
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            /* Start comment same line */
            int x = 0; // End comment same line
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            /* End comment next line */
        }
    }
    """);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16681")]
            public Task TestPragmaWarningDirectiveWithDocumentationComment1()
                => TestAsync(
    """
 
    sealed class Class
    {
        /// <summary>Text</summary>
        [|protected void Method()|]
        {
        }
    }
    """,
    $$"""

    sealed class Class
    {
        /// <summary>Text</summary>
    #pragma warning disable CS0628 // {{CSharpResources.WRN_ProtectedInSealed_Title}}
        protected void Method()
    #pragma warning restore CS0628 // {{CSharpResources.WRN_ProtectedInSealed_Title}}
        {
        }
    }
    """);
 
            [Fact]
            public Task TestPragmaWarningExpressionBodiedMember1()
                => TestAsync(
    """
 
    sealed class Class
    {
        [|protected int Method()|] => 1;
    }
    """,
    $$"""

    sealed class Class
    {
    #pragma warning disable CS0628 // {{CSharpResources.WRN_ProtectedInSealed_Title}}
        protected int Method() => 1;
    #pragma warning restore CS0628 // {{CSharpResources.WRN_ProtectedInSealed_Title}}
    }
    """);
 
            [Fact]
            public Task TestPragmaWarningExpressionBodiedMember2()
                => TestAsync(
        """
 
        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            string Method()
                => @$"hi
                {[|new Session()|]}
                ";
        }
        """,
        $$"""

        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            string Method()
        #pragma warning disable CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
                => @$"hi
                {new Session()}
                ";
        #pragma warning restore CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
        }
        """);
 
            [Fact]
            public Task TestPragmaWarningExpressionBodiedLocalFunction()
                => TestAsync(
        """
 
        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void M()
            {
                string Method()
                    => @$"hi
                    {[|new Session()|]}
                    ";
            }
        }
        """,
        $$"""

        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void M()
            {
        #pragma warning disable CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
                string Method()
                    => @$"hi
                    {new Session()}
                    ";
        #pragma warning restore CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
            }
        }
        """);
 
            [Fact]
            public Task TestPragmaWarningExpressionBodiedLambda()
                => TestAsync(
        """
 
        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void M()
            {
                new Func<string>(()
                    => @$"hi
                    {[|new Session()|]}
                    ");
            }
        }
        """,
        $$"""

        using System;
 
        [Obsolete]
        class Session { }
 
        class Class
        {
            void M()
            {
        #pragma warning disable CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
                new Func<string>(()
                    => @$"hi
                    {new Session()}
                    ");
        #pragma warning restore CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
            }
        }
        """);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/16681")]
            public Task TestPragmaWarningDirectiveWithDocumentationComment2()
                => TestAsync(
    """
 
    sealed class Class
    {
        /// <summary>Text</summary>
        /// <remarks>
        /// <see cref="[|Class2|]"/>
        /// </remarks>
        void Method()
        {
        }
    }
    """,
    $$"""

    sealed class Class
    {
 
    #pragma warning disable CS1574 // {{CSharpResources.WRN_BadXMLRef_Title}}
        /// <summary>Text</summary>
        /// <remarks>
        /// <see cref="Class2"/>
        /// </remarks>
        void Method()
    #pragma warning restore CS1574 // {{CSharpResources.WRN_BadXMLRef_Title}}
        {
        }
    }
    """, new CSharpParseOptions(documentationMode: DocumentationMode.Diagnose));
 
            [Fact]
            public Task TestMultipleInstancesOfPragmaWarningDirective()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0, y = 0;|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
            int x = 0, y = 0;
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
        }
    }
    """);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/3311")]
            public async Task TestNoDuplicateSuppressionCodeFixes()
            {
                var source = """
 
                    class Class
                    {
                        void Method()
                        {
                            [|int x = 0, y = 0; string s;|]
                        }
                    }
                    """;
                var parameters = TestParameters.Default;
                using var workspace = CreateWorkspaceFromOptions(source, parameters);
 
                var analyzerReference = new AnalyzerImageReference([new CSharpCompilerDiagnosticAnalyzer()]);
                workspace.TryApplyChanges(workspace.CurrentSolution.WithAnalyzerReferences([analyzerReference]));
 
                var diagnosticService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
                var suppressionProvider = CreateDiagnosticProviderAndFixer(workspace).Item2;
                var suppressionProviderFactory = new Lazy<IConfigurationFixProvider, CodeChangeProviderMetadata>(() => suppressionProvider,
                    new CodeChangeProviderMetadata("SuppressionProvider", languages: [LanguageNames.CSharp]));
                var fixService = new CodeFixService(
                    loggers: [],
                    fixers: [],
                    [suppressionProviderFactory]);
                var document = GetDocumentAndSelectSpan(workspace, out var span);
                var diagnostics = await diagnosticService.GetDiagnosticsForSpanAsync(
                    document, span, DiagnosticKind.All, CancellationToken.None);
                Assert.Equal(2, diagnostics.Where(d => d.Id == "CS0219").Count());
 
                var allFixes = (await fixService.GetFixesAsync(document, span, CancellationToken.None))
                    .SelectMany(fixCollection => fixCollection.Fixes);
 
                var cs0219Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0219").ToArray();
 
                // Ensure that there are no duplicate suppression fixes.
                Assert.Equal(1, cs0219Fixes.Length);
                var cs0219EquivalenceKey = cs0219Fixes[0].Action.EquivalenceKey;
                Assert.NotNull(cs0219EquivalenceKey);
 
                // Ensure that there *is* a fix for the other warning and that it has a *different*
                // equivalence key so that it *doesn't* get de-duplicated
                Assert.Equal(1, diagnostics.Where(d => d.Id == "CS0168").Count());
                var cs0168Fixes = allFixes.Where(fix => fix.PrimaryDiagnostic.Id == "CS0168");
                var cs0168EquivalenceKey = cs0168Fixes.Single().Action.EquivalenceKey;
                Assert.NotNull(cs0168EquivalenceKey);
                Assert.NotEqual(cs0219EquivalenceKey, cs0168EquivalenceKey);
            }
 
            [Fact]
            public Task TestErrorAndWarningScenario()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
            return 0;
            [|int x = "0";|]
        }
    }
    """,
    $$"""

    class Class
    {
        void Method()
        {
            return 0;
    #pragma warning disable CS0162 // {{CSharpResources.WRN_UnreachableCode_Title}}
            int x = "0";
    #pragma warning restore CS0162 // {{CSharpResources.WRN_UnreachableCode_Title}}
        }
    }
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/956453")]
            public Task TestWholeFilePragmaWarningDirective()
                => TestAsync(
    @"class Class { void Method() { [|int x = 0;|] } }",
    $$"""
    #pragma warning disable CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
    class Class { void Method() { int x = 0; } }
    #pragma warning restore CS0219 // {{CSharpResources.WRN_UnreferencedVarAssg_Title}}
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/970129")]
            public Task TestSuppressionAroundSingleToken()
                => TestAsync(
    """
 
    using System;
    [Obsolete]
    class Session { }
    class Program
    {
        static void Main()
        {
          [|Session|]
        }
    }
    """,
    $$"""

    using System;
    [Obsolete]
    class Session { }
    class Program
    {
        static void Main()
        {
    #pragma warning disable CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
            Session
    #pragma warning restore CS0612 // {{CSharpResources.WRN_DeprecatedSymbol_Title}}
        }
    }
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia1()
                => TestAsync(
    """
 
    class Class
    {
        void Method()
        {
 
    // Comment
    // Comment
    [|#pragma abcde|]
 
        }    // Comment   
 
 
 
    }
    """,
    $$"""

    class Class
    {
        void Method()
    #pragma warning disable CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
        {
 
    // Comment
    // Comment
    #pragma abcde
 
        }    // Comment   
    #pragma warning restore CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
 
 
 
    }
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia2()
                => TestAsync(
    @"[|#pragma abcde|]",
    $"""
    #pragma warning disable CS1633 // {CSharpResources.WRN_IllegalPragma_Title}
    #pragma abcde
    #pragma warning restore CS1633 // {CSharpResources.WRN_IllegalPragma_Title}
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia3()
                => TestAsync(
    @"[|#pragma abcde|]  ",
    $"""
    #pragma warning disable CS1633 // {CSharpResources.WRN_IllegalPragma_Title}
    #pragma abcde  
    #pragma warning restore CS1633 // {CSharpResources.WRN_IllegalPragma_Title}
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia4()
                => TestAsync(
    """
 
 
    [|#pragma abc|]
    class C { }
 
 
    """,
    $$"""

 
    #pragma warning disable CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
    #pragma abc
    class C { }
    #pragma warning restore CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
 

    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia5()
                => TestAsync(
    """
    class C1 { }
    [|#pragma abc|]
    class C2 { }
    class C3 { }
    """,
    $$"""
    class C1 { }
    #pragma warning disable CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
    #pragma abc
    class C2 { }
    #pragma warning restore CS1633 // {{CSharpResources.WRN_IllegalPragma_Title}}
    class C3 { }
    """);
 
            [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1066576")]
            public Task TestPragmaWarningDirectiveAroundTrivia6()
                => TestAsync(
    """
    class C1 { }
    class C2 { } /// <summary><see [|cref="abc"|]/></summary>
    class C3 { } // comment
      // comment
    // comment
    """,
    $$"""
    class C1 { }
    #pragma warning disable CS1574 // {{CSharpResources.WRN_BadXMLRef_Title}}
    class C2 { } /// <summary><see cref="abc"/></summary>
    class
    #pragma warning restore CS1574 // {{CSharpResources.WRN_BadXMLRef_Title}}
    C3 { } // comment
      // comment
    // comment
    """, CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose));
        }
 
        public sealed class UserHiddenDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new CSharpSimplifyTypeNamesDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestHiddenDiagnosticCannotBeSuppressed()
                => TestMissingAsync(
    """
 
    using System;
 
    class Class
    {
    int Method()
    {
        [|System.Int32 x = 0;|]
        return x;
    }
    }
    """);
        }
 
        public sealed partial class UserInfoDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
            {
                public static readonly DiagnosticDescriptor Decsciptor =
                    new DiagnosticDescriptor("InfoDiagnostic", "InfoDiagnostic Title", "InfoDiagnostic", "InfoDiagnostic", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
                public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
                {
                    get
                    {
                        return [Decsciptor];
                    }
                }
 
                public override void Initialize(AnalysisContext context)
                    => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
 
                public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                {
                    var classDecl = (ClassDeclarationSyntax)context.Node;
                    context.ReportDiagnostic(Diagnostic.Create(Decsciptor, classDecl.Identifier.GetLocation()));
                }
            }
 
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestInfoDiagnosticSuppressed()
                => TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """,
        """
 
        using System;
 
        #pragma warning disable InfoDiagnostic // InfoDiagnostic Title
        class Class
        #pragma warning restore InfoDiagnostic // InfoDiagnostic Title
        {
            int Method()
            {
                int x = 0;
            }
        }
        """);
        }
 
        public sealed partial class FormattingDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new CSharpFormattingAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            protected override async Task<(ImmutableArray<CodeAction>, CodeAction actionToInvoke)> GetCodeActionsAsync(TestWorkspace workspace, TestParameters parameters)
            {
                var solution = workspace.CurrentSolution;
                var compilationOptions = solution.Projects.Single().CompilationOptions;
                var specificDiagnosticOptions = new[] { KeyValuePair.Create(IDEDiagnosticIds.FormattingDiagnosticId, ReportDiagnostic.Warn) };
                compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(specificDiagnosticOptions);
                var updatedSolution = solution.WithProjectCompilationOptions(solution.ProjectIds.Single(), compilationOptions);
                await workspace.ChangeSolutionAsync(updatedSolution);
 
                return await base.GetCodeActionsAsync(workspace, parameters);
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            [WorkItem("https://github.com/dotnet/roslyn/issues/38587")]
            public Task TestFormattingDiagnosticSuppressed()
                => TestAsync(
        """
 
        using System;
 
        class Class
        {
            int Method()
            {
                [|int x = 0 ;|]
            }
        }
        """,
        """
 
        using System;
 
        class Class
        {
            int Method()
            {
        #pragma warning disable format
                int x = 0 ;
        #pragma warning restore format
            }
        }
        """);
        }
 
        public sealed class UserErrorDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
            {
                private readonly DiagnosticDescriptor _descriptor =
                    new DiagnosticDescriptor("ErrorDiagnostic", "ErrorDiagnostic", "ErrorDiagnostic", "ErrorDiagnostic", DiagnosticSeverity.Error, isEnabledByDefault: true);
 
                public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
                {
                    get
                    {
                        return [_descriptor];
                    }
                }
 
                public override void Initialize(AnalysisContext context)
                    => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
 
                public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                {
                    var classDecl = (ClassDeclarationSyntax)context.Node;
                    context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
                }
            }
 
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestErrorDiagnosticCanBeSuppressed()
                => TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """,
        """
 
        using System;
 
        #pragma warning disable ErrorDiagnostic // ErrorDiagnostic
        class Class
        #pragma warning restore ErrorDiagnostic // ErrorDiagnostic
        {
            int Method()
            {
                int x = 0;
            }
        }
        """);
        }
 
        public sealed class DiagnosticWithBadIdSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
        {
            // Analyzer driver generates a no-location analyzer exception diagnostic, which we don't intend to test here.
            protected override bool IncludeNoLocationDiagnostics => false;
 
            private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
            {
                private readonly DiagnosticDescriptor _descriptor =
                    new DiagnosticDescriptor("@~DiagnosticWithBadId", "DiagnosticWithBadId", "DiagnosticWithBadId", "DiagnosticWithBadId", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
                public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
                {
                    get
                    {
                        return [_descriptor];
                    }
                }
 
                public override void Initialize(AnalysisContext context)
                    => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
 
                public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                {
                    var classDecl = (ClassDeclarationSyntax)context.Node;
                    context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
                }
            }
 
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestDiagnosticWithBadIdSuppressed()
                => TestMissingAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """);
        }
    }
 
    public sealed partial class MultilineDiagnosticSuppressionTests : CSharpPragmaWarningDisableSuppressionTests
    {
        private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
        {
            public static readonly DiagnosticDescriptor Decsciptor =
                new DiagnosticDescriptor("InfoDiagnostic", "InfoDiagnostic Title", "InfoDiagnostic", "InfoDiagnostic", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
            public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            {
                get
                {
                    return [Decsciptor];
                }
            }
 
            public override void Initialize(AnalysisContext context)
                => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
 
            public void AnalyzeNode(SyntaxNodeAnalysisContext context)
            {
                var classDecl = (ClassDeclarationSyntax)context.Node;
                context.ReportDiagnostic(Diagnostic.Create(Decsciptor, classDecl.GetLocation()));
            }
        }
 
        internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
        {
            return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
        [WorkItem("https://github.com/dotnet/roslyn/issues/2764")]
        public Task TestPragmaWarningDirectiveAroundMultilineDiagnostic()
            => TestAsync(
                """
 
                [|class Class
                {
                }|]
 
                """,
                $$"""

                #pragma warning disable {{UserDiagnosticAnalyzer.Decsciptor.Id}} // {{UserDiagnosticAnalyzer.Decsciptor.Title}}
                class Class
                {
                }
                #pragma warning restore {{UserDiagnosticAnalyzer.Decsciptor.Id}} // {{UserDiagnosticAnalyzer.Decsciptor.Title}}

                """);
    }
    #endregion
 
    #region "SuppressMessageAttribute tests"
 
    public abstract partial class CSharpGlobalSuppressMessageSuppressionTests : CSharpSuppressionTests
    {
        protected sealed override int CodeActionIndex => 1;
 
        public sealed class CompilerDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
                => Tuple.Create<DiagnosticAnalyzer, IConfigurationFixProvider>(null, new CSharpSuppressionCodeFixProvider());
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestCompilerDiagnosticsCannotBeSuppressed()
                => TestActionCountAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0;|]
        }
    }
    """, 1);
        }
 
        public sealed class FormattingDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return Tuple.Create<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new CSharpFormattingAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            protected override async Task<(ImmutableArray<CodeAction>, CodeAction actionToInvoke)> GetCodeActionsAsync(TestWorkspace workspace, TestParameters parameters)
            {
                var solution = workspace.CurrentSolution;
                var compilationOptions = solution.Projects.Single().CompilationOptions;
                var specificDiagnosticOptions = new[] { KeyValuePair.Create(IDEDiagnosticIds.FormattingDiagnosticId, ReportDiagnostic.Warn) };
                compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(specificDiagnosticOptions);
                var updatedSolution = solution.WithProjectCompilationOptions(solution.ProjectIds.Single(), compilationOptions);
                await workspace.ChangeSolutionAsync(updatedSolution);
 
                return await base.GetCodeActionsAsync(workspace, parameters);
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            [WorkItem("https://github.com/dotnet/roslyn/issues/38587")]
            public Task TestCompilerDiagnosticsCannotBeSuppressed()
                => TestActionCountAsync(
    """
 
    class Class
    {
        void Method()
        {
            [|int x = 0 ;|]
        }
    }
    """, 1);
        }
 
        public sealed class UserHiddenDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
        {
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new CSharpSimplifyTypeNamesDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
            public Task TestHiddenDiagnosticsCannotBeSuppressed()
                => TestMissingAsync(
    """
 
    using System;
    class Class
    {
        void Method()
        {
            [|System.Int32 x = 0;|]
        }
    }
    """);
        }
 
        [Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
        public sealed partial class UserInfoDiagnosticSuppressionTests : CSharpGlobalSuppressMessageSuppressionTests
        {
            private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
            {
                public static readonly DiagnosticDescriptor Descriptor =
                    new("InfoDiagnostic", "InfoDiagnostic", "InfoDiagnostic", "InfoDiagnostic", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
                public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
                {
                    get
                    {
                        return [Descriptor];
                    }
                }
 
                public override void Initialize(AnalysisContext context)
                    => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration, SyntaxKind.EnumDeclaration, SyntaxKind.NamespaceDeclaration, SyntaxKind.MethodDeclaration, SyntaxKind.PropertyDeclaration, SyntaxKind.FieldDeclaration, SyntaxKind.EventDeclaration);
 
                public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                {
                    switch (context.Node.Kind())
                    {
                        case SyntaxKind.ClassDeclaration:
                            var classDecl = (ClassDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, classDecl.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.NamespaceDeclaration:
                            var ns = (NamespaceDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, ns.Name.GetLocation()));
                            break;
 
                        case SyntaxKind.MethodDeclaration:
                            var method = (MethodDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, method.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.PropertyDeclaration:
                            var property = (PropertyDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, property.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.FieldDeclaration:
                            var field = (FieldDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, field.Declaration.Variables.First().Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.EventDeclaration:
                            var e = (EventDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(Descriptor, e.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.EnumDeclaration:
                            // Report diagnostic on each descendant comment trivia
                            foreach (var trivia in context.Node.DescendantTrivia().Where(t => t.Kind() is SyntaxKind.SingleLineCommentTrivia or SyntaxKind.MultiLineCommentTrivia))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation()));
                            }
 
                            break;
                    }
                }
            }
 
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37529")]
            public async Task GeneratedCodeShouldNotHaveTrailingWhitespace()
            {
                var expected =
                    $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class")]

                    """;
 
                Assert.All(Regex.Split(expected, "\r?\n"), line => Assert.False(HasTrailingWhitespace(line)));
 
                await TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """, expected);
            }
 
            private static bool HasTrailingWhitespace(string line)
                => line.LastOrNull() is char last && char.IsWhiteSpace(last);
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37529")]
            public async Task GeneratedCodeShouldNotHaveLeadingBlankLines()
            {
                var expected =
                    $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class")]

                    """;
 
                var lines = Regex.Split(expected, "\r?\n");
                Assert.False(string.IsNullOrWhiteSpace(lines.First()));
 
                await TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """, expected);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37529")]
            public async Task GeneratedCodeShouldNotHaveMoreThanOneTrailingBlankLine()
            {
                var expected =
                    $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class")]

                    """;
 
                var lines = Regex.Split(expected, "\r?\n");
                Assert.False(string.IsNullOrWhiteSpace(lines[^2]));
 
                await TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """, expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnSimpleType()
            {
                await TestAsync(
        """
 
        using System;
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "~T:Class")]
 
        [|class Class|]
        {
            int Method()
            {
                int x = 0;
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnNamespace()
            {
                await TestInRegularAndScriptAsync(
        """
 
        using System;
 
        [|namespace N|]
        {
            class Class
            {
                int Method()
                {
                    int x = 0;
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "namespace", Target = "~N:N")]

        """, index: 1);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "namespace", Target = "~N:N")]
 
        [|namespace N|]
        {
            class Class
            {
                int Method()
                {
                    int x = 0;
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnTypeInsideNamespace()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N1
        {
            namespace N2
            {
                [|class Class|]
                {
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:N1.N2.Class")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "~T:N1.N2.Class")]
 
        namespace N1
        {
            namespace N2
            {
                [|class Class|]
                {
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnNestedType()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N
        {
            class Generic<T>
            {
                [|class Class|]
                {
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:N.Generic`1.Class")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "~T:N.Generic`1.Class")]
 
        namespace N
        {
            class Generic<T>
            {
                [|class Class|]
                {
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnMethod()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method()
                    {
                        int x = 0;
                    }|]
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~M:N.Generic`1.Class.Method~System.Int32")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~M:N.Generic`1.Class.Method~System.Int32")]
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method()|]
                    {
                        int x = 0;
                    }
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnOverloadedMethod()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method(int y, ref char z)
                    {
                        int x = 0;
                    }|]
 
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~M:N.Generic`1.Class.Method(System.Int32,System.Char@)~System.Int32")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~M:N.Generic`1.Class.Method(System.Int32,System.Char@)~System.Int32")]
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method(int y, ref char z)|]
                    {
                        int x = 0;
                    }
 
                    int Method()
                    {
                        int x = 0;
                    }
                }
            }
        }
        """);
 
                await TestAsync(
    """
 
    using System;
 
    using System.Diagnostics.CodeAnalysis;
 
    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~M:N.Generic`1.Class.Method(System.Int32,System.Char@)~System.Int32")]
 
    namespace N
    {
        class Generic<T>
        {
            class Class
            {
                [|int Method(int y, ref char z)
                {
                    int x = 0;
                }
 
                int Method()
                {
                    int x = 0;
                }|]
            }
        }
    }
    """,
    $"""
    // This file is used by Code Analysis to maintain SuppressMessage
    // attributes that are applied to this project.
    // Project-level suppressions either have no target or are given
    // a specific target and scoped to a namespace, type, member, etc.
 
    using System.Diagnostics.CodeAnalysis;
 
    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~M:N.Generic`1.Class.Method~System.Int32")]

    """);
            }
 
            [Fact]
            public async Task TestSuppressionOnGenericMethod()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method<U>(U u)
                    {
                        int x = 0;
                    }|]
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~M:N.Generic`1.Class.Method``1(``0)~System.Int32")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~M:N.Generic`1.Class.Method``1(``0)~System.Int32")]
 
        namespace N
        {
            class Generic<T>
            {
                class Class
                {
                    [|int Method<U>(U u)|]
                    {
                        int x = 0;
                    }
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnProperty()
            {
                await TestAsync(
        """
 
        using System;
 
        namespace N
        {
            class Generic
            {
                class Class
                {
                    [|int Property|]
                    {
                        get { int x = 0; }
                    }
                }
            }
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~P:N.Generic.Class.Property")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~P:N.Generic.Class.Property")]
 
        namespace N
        {
            class Generic
            {
                class Class
                {
                    [|int Property|]
                    {
                        get { int x = 0; }
                    }
                }
            }
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnField()
            {
                await TestAsync(
        """
 
        using System;
 
        class Class
        {
            [|int field = 0;|]
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~F:Class.field")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~F:Class.field")]
 
        class Class
        {
            [|int field = 0;|]
        }
        """);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/6379")]
            public async Task TestSuppressionOnTriviaBetweenFields()
            {
                await TestAsync(
        """
 
        using System;
 
        // suppressions on field are not relevant.
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~F:E.Field1")]
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~F:E.Field2")]
 
        enum E
        {
            [|
            Field1, // trailing trivia for comma token which doesn't belong to span of any of the fields
            Field2
            |]
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:E")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:E")]
 
        enum E
        {
            [|
            Field1, // trailing trivia for comma token which doesn't belong to span of any of the fields
            Field2
            |]
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnField2()
            {
                await TestAsync(
        """
 
        using System;
 
        class Class
        {
            int [|field = 0|], field2 = 1;
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~F:Class.field")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~F:Class.field")]
 
        class Class
        {
            int [|field|] = 0, field2 = 1;
        }
        """);
            }
 
            [Fact]
            public async Task TestSuppressionOnEvent()
            {
                await TestAsync(
        """
 
        using System;
 
        public class SampleEventArgs
        {
            public SampleEventArgs(string s) { Text = s; }
            public String Text {get; private set;} // readonly
                }
 
        class Class
        {
            // Declare the delegate (if using non-generic pattern). 
            public delegate void SampleEventHandler(object sender, SampleEventArgs e);
 
            // Declare the event. 
            [|public event SampleEventHandler SampleEvent
            {
                add { }
                remove { }
            }|]
        }
        """,
        $"""
        // This file is used by Code Analysis to maintain SuppressMessage
        // attributes that are applied to this project.
        // Project-level suppressions either have no target or are given
        // a specific target and scoped to a namespace, type, member, etc.
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "member", Target = "~E:Class.SampleEvent")]

        """);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                await TestMissingAsync(
        """
 
        using System;
 
        using System.Diagnostics.CodeAnalysis;
 
        [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "member", Target = "~E:Class.SampleEvent")]
 
        public class SampleEventArgs
        {
            public SampleEventArgs(string s) { Text = s; }
            public String Text {get; private set;} // readonly
        }
 
        class Class
        {
            // Declare the delegate (if using non-generic pattern).
            public delegate void SampleEventHandler(object sender, SampleEventArgs e);
 
            // Declare the event.
            [|public event SampleEventHandler SampleEvent|]
            {
                add { }
                remove { }
            }
        }
        """);
            }
 
            [Fact]
            public Task TestSuppressionWithExistingGlobalSuppressionsDocument()
                => TestAsync("""
                    <Workspace>
                        <Project Language="C#" CommonReferences="true" AssemblyName="Proj1">
                            <Document FilePath="CurrentDocument.cs"><![CDATA[
                    using System;
 
                    class Class { }
 
                    [|class Class2|] { }
                    ]]>
                            </Document>
                            <Document FilePath="GlobalSuppressions.cs"><![CDATA[// This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    ]]>
                            </Document>
                        </Project>
                    </Workspace>
                    """, $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class2")]

                    """);
 
            [Fact]
            public Task TestSuppressionWithExistingGlobalSuppressionsDocument2()
                => TestAsync("""
                    <Workspace>
                        <Project Language="C#" CommonReferences="true" AssemblyName="Proj1">
                            <Document FilePath="CurrentDocument.cs"><![CDATA[
                    using System;
 
                    class Class { }
 
                    [|class Class2|] { }
                    ]]>
                            </Document>
                            <Document FilePath="GlobalSuppressions.cs"><![CDATA[
                    // My own file named GlobalSuppressions.cs.
                    using System;
                    class Class { }
                    ]]>
                            </Document>
                        </Project>
                    </Workspace>
                    """, $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class2")]

                    """);
 
            [Fact]
            public Task TestSuppressionWithExistingGlobalSuppressionsDocument3()
                => TestAsync("""
                    <Workspace>
                        <Project Language="C#" CommonReferences="true" AssemblyName="Proj1">
                            <Document FilePath="CurrentDocument.cs"><![CDATA[
                    using System;
 
                    class Class { }
 
                    [|class Class2|] { }
                    ]]>
                            </Document>
                            <Document FilePath="GlobalSuppressions.cs"><![CDATA[
                    // My own file named GlobalSuppressions.cs.
                    using System;
                    class Class { }
                    ]]>
                            </Document>
                             <Document FilePath="GlobalSuppressions2.cs"><![CDATA[// This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    ]]>
                            </Document>
                        </Project>
                    </Workspace>
                    """, $"""
                    // This file is used by Code Analysis to maintain SuppressMessage
                    // attributes that are applied to this project.
                    // Project-level suppressions either have no target or are given
                    // a specific target and scoped to a namespace, type, member, etc.
 
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class2")]

                    """);
 
            [Fact]
            public Task TestSuppressionWithUsingDirectiveInExistingGlobalSuppressionsDocument()
                => TestAsync("""
                    <Workspace>
                        <Project Language="C#" CommonReferences="true" AssemblyName="Proj1">
                            <Document FilePath="CurrentDocument.cs"><![CDATA[
                    using System;
 
                    class Class { }
 
                    [|class Class2|] { }
                    ]]>
                            </Document>
                            <Document FilePath="GlobalSuppressions.cs"><![CDATA[
                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    ]]>
                            </Document>
                        </Project>
                    </Workspace>
                    """, $"""

                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class2")]

                    """);
 
            [Fact]
            public Task TestSuppressionWithoutUsingDirectiveInExistingGlobalSuppressionsDocument()
                => TestAsync("""
                    <Workspace>
                        <Project Language="C#" CommonReferences="true" AssemblyName="Proj1">
                            <Document FilePath="CurrentDocument.cs"><![CDATA[
                    using System;
 
                    class Class { }
 
                    [|class Class2|] { }
                    ]]>
                            </Document>
                            <Document FilePath="GlobalSuppressions.cs"><![CDATA[
                    [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    ]]>
                            </Document>
                        </Project>
                    </Workspace>
                    """, $"""

                    using System.Diagnostics.CodeAnalysis;
 
                    [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "<Pending>", Scope = "type", Target = "Class")]
                    [assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{FeaturesResources.Pending}", Scope = "type", Target = "~T:Class2")]

                    """);
        }
    }
 
    public abstract class CSharpLocalSuppressMessageSuppressionTests : CSharpSuppressionTests
    {
        protected sealed override int CodeActionIndex => 2;
 
        [Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
        public sealed class UserInfoDiagnosticSuppressionTests : CSharpLocalSuppressMessageSuppressionTests
        {
            private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
            {
                private readonly DiagnosticDescriptor _descriptor =
                    new("InfoDiagnostic", "InfoDiagnostic", "InfoDiagnostic", "InfoDiagnostic", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
                public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [_descriptor];
 
                public override void Initialize(AnalysisContext context)
                    => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration, SyntaxKind.NamespaceDeclaration, SyntaxKind.MethodDeclaration, SyntaxKind.ExtensionBlockDeclaration);
 
                public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                {
                    switch (context.Node.Kind())
                    {
                        case SyntaxKind.ClassDeclaration:
                            var classDecl = (ClassDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.NamespaceDeclaration:
                            var ns = (NamespaceDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(_descriptor, ns.Name.GetLocation()));
                            break;
 
                        case SyntaxKind.MethodDeclaration:
                            var method = (MethodDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(_descriptor, method.Identifier.GetLocation()));
                            break;
 
                        case SyntaxKind.ExtensionBlockDeclaration:
                            var extensionBlock = (ExtensionBlockDeclarationSyntax)context.Node;
                            context.ReportDiagnostic(Diagnostic.Create(_descriptor, extensionBlock.Keyword.GetLocation()));
                            break;
 
                    }
                }
            }
 
            internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
            {
                return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                    new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
            }
 
            [Fact]
            public async Task TestSuppressionOnSimpleType()
            {
                var expected = $$"""

                    using System;
 
                    // Some trivia
                    /* More Trivia */
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                    class Class
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    // Some trivia
                    /* More Trivia */ [|class Class|]
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("class Class", "[|class Class|]");
                await TestMissingAsync(expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnSimpleType2()
            {
                // Type already has attributes.
                var expected = $$"""

                    using System;
 
                    // Some trivia
                    /* More Trivia */
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification = "<Pending>")]
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                    class Class
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    // Some trivia
                    /* More Trivia */
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification = "<Pending>")]
                    [|class Class|]
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("class Class", "[|class Class|]");
                await TestMissingAsync(expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnSimpleType3()
            {
                // Type already has attributes with trailing trivia.
                var expected = $$"""

                    using System;
 
                    // Some trivia
                    /* More Trivia */
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification = "<Pending>")]
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                    /* Some More Trivia */
                    class Class
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    // Some trivia
                    /* More Trivia */
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification = "<Pending>")]
                    /* Some More Trivia */
                    [|class Class|]
                    {
                        int Method()
                        {
                            int x = 0;
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("class Class", "[|class Class|]");
                await TestMissingAsync(expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnTypeInsideNamespace()
            {
                var expected = $$"""

                    using System;
 
                    namespace N1
                    {
                        namespace N2
                        {
                            [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                            class Class
                            {
                                int Method()
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace N1
                    {
                        namespace N2
                        {
                            [|class Class|]
                            {
                                int Method()
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("class Class", "[|class Class|]");
                await TestMissingAsync(expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnNestedType()
            {
                var expected = $$"""

                    using System;
 
                    namespace N
                    {
                        class Generic<T>
                        {
                            [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                            class Class
                            {
                                int Method()
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace N
                    {
                        class Generic<T>
                        {
                            [|class Class|]
                            {
                                int Method()
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("class Class", "[|class Class|]");
                await TestMissingAsync(expected);
            }
 
            [Fact]
            public async Task TestSuppressionOnMethod()
            {
                var expected = $$"""

                    using System;
 
                    namespace N
                    {
                        class Generic<T>
                        {
                            class Class
                            {
                                [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                                int Method()
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace N
                    {
                        class Generic<T>
                        {
                            class Class
                            {
                                [|int Method()|]
                                {
                                    int x = 0;
                                }
                            }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("int Method()", "[|int Method()|]");
                await TestMissingAsync(expected);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47427")]
            public async Task TestSuppressionOnMethodWithXmlDoc()
            {
                var expected = $$"""

                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
 
                            /// <summary>
                            /// This is a description
                            /// </summary>
                            [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                            public void Method(int unused) { }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
 
                            /// <summary>
                            /// This is a description
                            /// </summary>
                            [|public void Method(int unused)|] { }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("public void Method(int unused)", "[|public void Method(int unused)|]");
                await TestMissingAsync(expected);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47427")]
            public async Task TestSuppressionOnMethodWithNoTrivia()
            {
                var expected = $$"""

                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
                            [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                            public void Method(int unused) { }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
                    [|public void Method(int unused)|] { }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("public void Method(int unused)", "[|public void Method(int unused)|]");
                await TestMissingAsync(expected);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/47427")]
            public async Task TestSuppressionOnMethodWithTriviaStartsOnTheSameLine()
            {
                var expected = $$"""

                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
                            /*test*/
                            [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                            public void Method(int unused) { }
                        }
                    }
                    """;
                await TestAsync("""
 
                    using System;
 
                    namespace ClassLibrary10
                    {
                        public class Class1
                        {
                            int x;
                            /*test*/[|public void Method(int unused)|] { }
                        }
                    }
                    """, expected);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("public void Method(int unused)", "[|public void Method(int unused)|]");
                await TestMissingAsync(expected);
            }
 
            [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/79375")]
            public async Task TestSuppressionOnExtensionBlock()
            {
                var csharp14Options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersionExtensions.CSharpNext);
 
                var expected = $$"""
                    using System;
 
                    [System.Diagnostics.CodeAnalysis.SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification = "{{FeaturesResources.Pending}}")]
                    struct S
                    {
                        extension(string s)
                        {
                        }
                    }
                    """;
                await TestAsync("""
                    using System;
                    
                    struct S
                    {
                        [|extension(string s)|]
                        {
                        }
                    }
                    """, expected, csharp14Options);
 
                // Also verify that the added attribute does indeed suppress the diagnostic.
                expected = expected.Replace("struct S", "[|struct S|]");
                await TestMissingAsync(expected, new TestParameters(parseOptions: csharp14Options));
            }
        }
    }
 
    #endregion
 
    #region NoLocation Diagnostics tests
 
    public sealed partial class CSharpDiagnosticWithoutLocationSuppressionTests : CSharpSuppressionTests
    {
        private sealed class UserDiagnosticAnalyzer : DiagnosticAnalyzer
        {
            public static readonly DiagnosticDescriptor Descriptor =
                new("NoLocationDiagnostic", "NoLocationDiagnostic", "NoLocationDiagnostic", "NoLocationDiagnostic", DiagnosticSeverity.Info, isEnabledByDefault: true);
 
            public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
                => [Descriptor];
 
            public override void Initialize(AnalysisContext context)
                => context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.ClassDeclaration);
 
            public void AnalyzeNode(SyntaxNodeAnalysisContext context)
                => context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.None));
        }
 
        internal override Tuple<DiagnosticAnalyzer, IConfigurationFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
        {
            return new Tuple<DiagnosticAnalyzer, IConfigurationFixProvider>(
                new UserDiagnosticAnalyzer(), new CSharpSuppressionCodeFixProvider());
        }
 
        protected override int CodeActionIndex => 0;
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073825")]
        public Task TestDiagnosticWithoutLocationCanBeSuppressed()
            => TestAsync(
    """
    [||]
    using System;
 
    class Class
    {
        int Method()
        {
            int x = 0;
        }
    }
    """,
    $"""
    // This file is used by Code Analysis to maintain SuppressMessage
    // attributes that are applied to this project.
    // Project-level suppressions either have no target or are given
    // a specific target and scoped to a namespace, type, member, etc.
 
    using System.Diagnostics.CodeAnalysis;
 
    [assembly: SuppressMessage("NoLocationDiagnostic", "NoLocationDiagnostic:NoLocationDiagnostic", Justification = "{FeaturesResources.Pending}")]

    """);
    }
 
    #endregion
}