File: Diff.Attribute.Tests.cs
Web Access
Project: ..\..\..\test\Microsoft.DotNet.ApiDiff.Tests\Microsoft.DotNet.ApiDiff.Tests.csproj (Microsoft.DotNet.ApiDiff.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
namespace Microsoft.DotNet.ApiDiff.Tests;
 
public class DiffAttributeTests : DiffBaseTests
{
    #region Type attributes
 
    [Fact]
    public Task TypeAttributeAdd() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [MyAttribute]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [MyNamespace.MyAttributeAttribute]
                      public class MyClass
                      {
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task TypeAttributeDeleteAndAdd() =>
        // Added APIs always show up at the end.
        RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [MyAttribute1]
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    [MyAttribute2]
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                -     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                -     public class MyAttribute1Attribute : System.Attribute
                -     {
                -         public MyAttribute1Attribute();
                -     }
                -     [MyNamespace.MyAttribute1Attribute]
                +     [MyNamespace.MyAttribute2Attribute]
                      public class MyClass
                      {
                      }
                +     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                +     public class MyAttribute2Attribute : System.Attribute
                +     {
                +         public MyAttribute2Attribute();
                +     }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task TypeAttributeSwitch() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    [MyAttribute1]
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    [MyAttribute2]
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                -     [MyNamespace.MyAttribute1Attribute]
                +     [MyNamespace.MyAttribute2Attribute]
                      public class MyClass
                      {
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task TypeChangeAndAttributeAdd() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass1
                    {
                        public MyClass1() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [MyAttribute]
                    public class MyClass2
                    {
                        public MyClass2() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                -     public class MyClass1
                -     {
                -         public MyClass1();
                -     }
                +     [MyNamespace.MyAttributeAttribute]
                +     public class MyClass2
                +     {
                +         public MyClass2();
                +     }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task TypeChangeButAttributeStays() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [MyAttribute]
                    public class MyClass1
                    {
                        public MyClass1() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [MyAttribute]
                    public class MyClass2
                    {
                        public MyClass2() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                -     [MyNamespace.MyAttributeAttribute]
                -     public class MyClass1
                -     {
                -         public MyClass1();
                -     }
                +     [MyNamespace.MyAttributeAttribute]
                +     public class MyClass2
                +     {
                +         public MyClass2();
                +     }
                  }
                """,
                attributesToExclude: []);
 
    #endregion
 
    #region Member attributes
 
    [Fact]
    public Task MemberAttributeAdd() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public void MyMethod() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        [MyAttribute]
                        public void MyMethod() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                +         [MyNamespace.MyAttributeAttribute]
                          public void MyMethod();
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task MemberAttributeDeleteAndAdd() =>
        // Added APIs always show up at the end.
        RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute1]
                        public void MyMethod() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute2]
                        public void MyMethod() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                -     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                -     public class MyAttribute1Attribute : System.Attribute
                -     {
                -         public MyAttribute1Attribute();
                -     }
                      public class MyClass
                      {
                -         [MyNamespace.MyAttribute1Attribute]
                +         [MyNamespace.MyAttribute2Attribute]
                          public void MyMethod();
                      }
                +     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                +     public class MyAttribute2Attribute : System.Attribute
                +     {
                +         public MyAttribute2Attribute();
                +     }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task MemberAttributeSwitch() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute1]
                        public void MyMethod() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute2]
                        public void MyMethod() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                -         [MyNamespace.MyAttribute1Attribute]
                +         [MyNamespace.MyAttribute2Attribute]
                          public void MyMethod();
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task MemberChangeAndAttributeAdd() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        public void MyMethod1() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute]
                        public void MyMethod2() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                -         public void MyMethod1();
                +         [MyNamespace.MyAttributeAttribute]
                +         public void MyMethod2();
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task MemberChangeButAttributeStays() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute]
                        public void MyMethod1() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass() { }
                        [MyAttribute]
                        public void MyMethod2() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                -         [MyNamespace.MyAttributeAttribute]
                -         public void MyMethod1();
                +         [MyNamespace.MyAttributeAttribute]
                +         public void MyMethod2();
                      }
                  }
                """,
                attributesToExclude: []);
 
    #endregion
 
    #region Parameter attributes
 
    //[Fact]
    [Fact(Skip = "Parameter attributes are not showing up in the syntax tree.")]
    public Task ParameterAttributeAdd() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass(int x) { }
                        public void MyMethod(int y) { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass([MyAttribute] int x) { }
                        public void MyMethod([MyAttribute] int y) { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                -         public MyClass(int x);
                +         public MyClass([MyNamespace.MyAttributeAttribute] int x);
                -         public void MyMethod(int y);
                +         public void MyMethod([MyNamespace.MyAttributeAttribute] int y);
                      }
                  }
                """,
                attributesToExclude: []);
 
    #endregion
 
    #region Attribute list expansion
 
    [Fact]
    public Task TypeAttributeListExpansion() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    [MyAttribute1, MyAttribute2]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [MyNamespace.MyAttribute1Attribute]
                +     [MyNamespace.MyAttribute2Attribute]
                      public class MyClass
                      {
                      }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task MethodAttributeListExpansion() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass(int x) { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        [MyAttribute1, MyAttribute2]
                        public MyClass(int x) { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                +         [MyNamespace.MyAttribute1Attribute]
                +         [MyNamespace.MyAttribute2Attribute]
                          public MyClass(int x);
                      }
                  }
                """,
                attributesToExclude: []);
 
    //[Fact]
    [Fact(Skip = "Parameter attributes are not showing up in the syntax tree.")]
    public Task ParameterAttributeListNoExpansion() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass(int x) { }
                        public void MyMethod(int y) { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttribute1Attribute : System.Attribute
                    {
                        public MyAttribute1Attribute() { }
                    }
                    [System.AttributeUsage(System.AttributeTargets.Parameter)]
                    public class MyAttribute2Attribute : System.Attribute
                    {
                        public MyAttribute2Attribute() { }
                    }
                    public class MyClass
                    {
                        public MyClass([MyAttribute1, MyAttribute2] int x) { }
                        public void MyMethod([MyAttribute1, MyAttribute2] int y) { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                -         public MyClass(int x);
                +         public MyClass([MyNamespace.MyAttribute1Attribute, MyNamespace.MyAttribute2Attribute] int x);
                -         public void MyMethod(int y);
                +         public void MyMethod([MyNamespace.MyAttribute1Attribute, MyNamespace.MyAttribute2Attribute] int y);
                      }
                  }
                """,
                attributesToExclude: []);
 
    #endregion
 
    #region Attribute exclusion
 
    [Fact]
    public Task SuppressAllDefaultAttributesUsedByTool()
    {
        // The attributes that should get hidden in this test must all be part of
        // the AttributesToExclude.txt file that the ApiDiff tool uses by default.
 
        FileInfo file = new FileInfo("AttributesToExclude.txt");
        if (!file.Exists)
        {
            throw new FileNotFoundException($"{file.FullName} file not found.");
        }
        string[] attributesToExclude = File.ReadAllLines(file.FullName);
 
        return RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
                    [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Text")]
                    [MyAttribute]
                    [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Text")]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [MyNamespace.MyAttributeAttribute]
                      public class MyClass
                      {
                      }
                +     public class MyAttributeAttribute : System.Attribute
                +     {
                +         public MyAttributeAttribute();
                +     }
                  }
                """,
                attributesToExclude: attributesToExclude);
    }
 
    [Fact]
    public Task SuppressNone() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
                    [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Text")]
                    [MyAttribute]
                    [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Text")]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
                +     [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Text")]
                +     [MyNamespace.MyAttributeAttribute]
                +     [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Text")]
                      public class MyClass
                      {
                      }
                +     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                +     public class MyAttributeAttribute : System.Attribute
                +     {
                +         public MyAttributeAttribute();
                +     }
                  }
                """,
                attributesToExclude: []);
 
    [Fact]
    public Task SuppressOnlyCustom() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public MyAttributeAttribute() { }
                    }
                    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
                    [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Text")]
                    [MyAttribute]
                    [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Text")]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
                +     [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Text")]
                +     [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Text")]
                      public class MyClass
                      {
                      }
                +     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                +     public class MyAttributeAttribute : System.Attribute
                +     {
                +         public MyAttributeAttribute();
                +     }
                  }
                """,
                attributesToExclude: ["T:MyNamespace.MyAttributeAttribute"]); // Overrides the default list
 
    [Fact]
    public Task SuppressChangedAttribute() => RunTestAsync(
                // Includes dummy property addition so that something else shows up in the diff, but not the attribute change.
                beforeCode: """
                namespace MyNamespace
                {
                    [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Original text")]
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Changed text")]
                    public class MyClass
                    {
                        public int X { get; }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                +         public int X { get; }
                      }
                  }
                """,
                attributesToExclude: ["T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute"]); // Overrides the default list
 
    [Fact]
    public Task SuppressAttributesRepeatedWithDifferentArguments() => RunTestAsync(
                // Include dummy property
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")]
                    [System.Runtime.Versioning.UnsupportedOSPlatform("linux")]
                    public class MyClass
                    {
                        public int X { get; }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                      public class MyClass
                      {
                +         public int X { get; }
                      }
                  }
                """,
                attributesToExclude: ["T:System.Runtime.Versioning.UnsupportedOSPlatformAttribute"]); // Overrides the default list
 
    [Fact]
    public Task SuppressTypeAndAttributeUsage() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                    }
                    [MyAttribute]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: "",
                attributesToExclude: ["T:MyNamespace.MyAttributeAttribute"], // Exclude the attribute decorating other APIs
                apisToExclude: ["T:MyNamespace.MyAttributeAttribute"]); // Excludes the type definition of the attribute itself
 
    #endregion
 
    #region Attributes with arguments
 
    [Fact]
    public Task AttributeWithArguments() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                afterCode: """
                namespace MyNamespace
                {
                    [System.AttributeUsage(System.AttributeTargets.All)]
                    public class MyAttributeAttribute : System.Attribute
                    {
                        public string First { get; }
                        public string Second { get; }
                        public MyAttributeAttribute(string first, string second)
                        {
                            First = first;
                            Second = second;
                        }
                    }
                    [MyAttribute(first: "First", second: "Second")]
                    public class MyClass
                    {
                        public MyClass() { }
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [MyNamespace.MyAttributeAttribute("First", "Second")]
                      public class MyClass
                      {
                      }
                +     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
                +     public class MyAttributeAttribute : System.Attribute
                +     {
                +         public MyAttributeAttribute(string first, string second);
                +         public string First { get; }
                +         public string Second { get; }
                +     }
                  }
                """,
                attributesToExclude: []); // Make sure to show AttributeUsage, which by default is suppressed
 
    [Fact]
    public Task AttributesRepeatedWithDifferentArguments() => RunTestAsync(
                beforeCode: """
                namespace MyNamespace
                {
                    public class MyClass
                    {
                    }
                }
                """,
                afterCode: """
                using System;
                namespace MyNamespace
                {
                    [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")]
                    [System.Runtime.Versioning.UnsupportedOSPlatform("linux")]
                    public class MyClass
                    {
                    }
                }
                """,
                expectedCode: """
                  namespace MyNamespace
                  {
                +     [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
                +     [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("linux")]
                      public class MyClass
                      {
                      }
                  }
                """,
                attributesToExclude: null); // null forces using the default list
 
    #endregion
}