public void Generate()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  public partial class C
  { 
    [AutoNotify] private int ip2;
  }
");

            tb.AssertNoDiagnostics();
            tb.FileEqual("C.INPC.cs",
                         @"#nullable enable
using Melville.INPC;
public partial class C: Melville.INPC.IExternalNotifyPropertyChanged 
{
    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;
    void Melville.INPC.IExternalNotifyPropertyChanged.OnPropertyChanged(string propertyName)
    {
        this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
    }
    public int Ip2
    {
        get => this.ip2;
        set
        {
            this.ip2 = value;
            ((Melville.INPC.IExternalNotifyPropertyChanged)this).OnPropertyChanged(""Ip2"");
        }
    }
}
");
        }
        public void GenericVariable()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  using System.Collections.Generic;
  public partial class C
  {
    [AutoNotify] private List<int> ints;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "System.Collections.Generic.List<int>");
        }
        public void ClassImplementsOnPropertyChanged()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public partial class ImplementInheritedINPC
    {
        protected void OnPropertyChanged(string property) {}
        [AutoNotify] private int y;
    }");

            tb.FileContains("ImplementInheritedINPC.INPC.cs",
                            "public partial class ImplementInheritedINPC \r\n{");
        }
        public void DoNotTouchUnmarkedClass()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  public partial class C
  { 
     private int intProp,ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.NoSuchFile("C.INPC.cs");
        }
        public void UseFullyQualifiedAttribute()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  public partial class C
  { 
     private int intProp;
     [Melville.INPC.AutoNotify] private int ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "public int Ip2");
        }
        public void MultipleVarsPerDecl()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  public partial class C
  { 
    [AutoNotify] private int intProp,ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "public int IntProp");
            tb.FileContains("C.INPC.cs", "public int Ip2");
        }
        public void IncludeAttribute()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  using System.Collections.Generic;
  public partial class C
  {
    [AutoNotify(Attributes=""[NewProp(1)]"")]private int integer;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "[NewProp(1)]\r\n    public int Integer");
            tb.FileDoesNotContain("C.INPC.cs", "[AutoNotify]");
        }
        public void GetFilter()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  using System.Collections.Generic;
  public partial class C
  {
    [AutoNotify] private int integer;
    private int IntegerGetFilter(int i) => i;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "=> this.IntegerGetFilter(this.integer);");
        }
        public void ClassWithGenericConstraint()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public interface IInt{}
  public partial class C<T> where T: IInt
  {
    [AutoNotify] private int integer;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs",
                            "public partial class C<T>: Melville.INPC.IExternalNotifyPropertyChanged where T: IInt");
        }
        public void UseExistingNotifyMethod()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
  public partial class C
  { 
     public void OnPropertyChanged(string name){}
     private int intProp;
     [Melville.INPC.AutoNotifyAttribute] private int ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileDoesNotContain("C.INPC.cs", "IExternalNotifyPropertyChange");
        }
        public void AllowExplicitAttribute()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
  public partial class C
  { 
     private int intProp;
     [Melville.INPC.AutoNotifyAttribute] private int ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "public int Ip2");
            tb.FileDoesNotContain("C.INPC.cs", "public int IntProp");
        }
        public void PropegateToReadOnlyPropertyImpl(string propDecl)
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public partial class ImplementInheritedINPC
    {
        protected void OnPropertyChanged(string property) {}
        [AutoNotify] private int y;
        " + propDecl + @"
    }");

            tb.FileContains("ImplementInheritedINPC.INPC.cs",
                            @"OnPropertyChanged(""FindY"");");
        }
        public void DoNotPropegateOtherCalls()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public partial class ImplementInheritedINPC
    {
        protected void OnPropertyChanged(string property) {}
        [AutoNotify] private int y;
        private ImplementInheritedINPC other;
        [AutoNotify] public int FindY {get {return other?.Y;}}
    }");

            tb.FileDoesNotContain("ImplementInheritedINPC.INPC.cs",
                                  @"OnPropertyChanged(""FindY"");");
        }
        public void ClassMustBePartial()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
namespace NM
{
  public class C
  { 
    [AutoNotify] private int intProp;
  }
}");

            tb.AssertDiagnosticCount(1);
        }
        public void MultipleWrappingClasses()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public partial class C
  {
    public partial class D{ 
    [AutoNotify] private int intProp,ip2;
  }}");

            tb.AssertNoDiagnostics();
            tb.FileContains("D.INPC.cs", "public partial class C");
            tb.FileContains("D.INPC.cs",
                            "public partial class D: Melville.INPC.IExternalNotifyPropertyChanged");
        }
        public void Nullable()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  using System.Collections.Generic;
  public partial class C
  {
    [AutoNotify] private int? intProp;
    [AutoNotify] private string? stringProp;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "int? IntProp");
            tb.FileContains("C.INPC.cs", "string? StringProp");
        }
        public void DoNotTouchClassWithWrongAttribute()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
  namespace A2 {
   public class AutoNotifyAttribute : Attribute{}
}
  public partial class C
  { 
     [A2.AutoNotify] private int intProp,ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.NoSuchFile("C.INPC.cs");
        }
        void DoNotTouchUnmarkedField()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  public partial class C
  { 
     private int intProp;
     [AutoNotify] private int ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "public int Ip2");
            tb.FileDoesNotContain("C.INPC.cs", "public int IntProp");
        }
        public void InheritsFromAnotherGeneratedType()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
    public partial class ParentINPC
    {
        [AutoNotify] private int x;
    }
    public partial class ImplementInheritedINPC: ParentINPC
    {
        [AutoNotify] private int y;
    }");

            tb.FileContains("ImplementInheritedINPC.INPC.cs",
                            "public partial class ImplementInheritedINPC \r\n{");
        }
        public void ElaborateMarkedClass()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
  [AutoNotify]
  public partial class C
  { 
     private int intProp,ip2;
  }");

            tb.AssertNoDiagnostics();
            tb.FileDoesNotContain("C.INPC.cs", "AutoNotify");
            tb.FileContains("C.INPC.cs",
                            "void Melville.INPC.IExternalNotifyPropertyChanged.OnPropertyChanged(string propertyName)");
        }
        public void AmbigiousFileNames()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"using Melville.INPC;
  public partial class C
  {
    [AutoNotify] private int? intProp;
  }
  public partial class C<T>: C {
     [AutoNotify] private T tProp;
  }");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "int? IntProp");
            tb.FileContains("C.INPC.1.cs", "T TProp");
        }
        public void ImplementCustomInterface()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          $@"
  public interface INot:INotifyPropertyChanged{{
     public void OnPropertyChanged(string name);  
  }}
  public partial class C:INot
  {{ 
     private int intProp;
     [Melville.INPC.AutoNotifyAttribute] private int ip2;
  }}");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "void INot.OnPropertyChanged(string");
            tb.FileDoesNotContain("C.INPC.cs", "IExternalNotifyPropertyChange");
        }
        public void OnPropertyChanged(string methodDecl, string included, string excluded)
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          $@"
using Melville.INPC;
namespace NM
{{
  public class C
  {{ 
    {methodDecl}
    [AutoNotify] private int ip;
  }}
}}");

            tb.FileContains("C.INPC.cs", included);
            tb.FileDoesNotContain("C.INPC.cs", excluded);
        }
        public void UseInheritedInterfaceMethod()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          $@" namespace NS {{
    public interface I {{ void OnPropertyChanged(string name);}}
  public class A: I {{
             void I.OnPropertyChanged(string name){{}}
            }}
  public partial class C: A
  {{ 
     private int intProp;
     [Melville.INPC.AutoNotifyAttribute] private int ip2;
  }}}}");

            tb.AssertNoDiagnostics();
            tb.FileDoesNotContain("C.INPC.cs", "IExternalNotifyPropertyChange");
            tb.FileContains("C.INPC.cs", "((NS.I)this).OnPropertyChanged");
        }
        public void MultipleNameSpaces()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          @"
using Melville.INPC;
namespace Outer{
namespace NM
{
  public partial class C
  { 
    [AutoNotify] private int intProp,ip2;
  }
}
}");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "namespace Outer");
            tb.FileContains("C.INPC.cs", "namespace NM");
        }
        public void RespectExistingCustomInterfaceIImplementation()
        {
            var tb = new GeneratorTestBed(new INPCGenerator(),
                                          $@"namespace NS {{
  public interface INot:INotifyPropertyChanged{{
     void OnPropertyChanged(string name);  
  }}
  public partial class C:INot
  {{ 
     void INot.OnPropertyChanged(string name){{}}
     private int intProp;
     [Melville.INPC.AutoNotifyAttribute] private int ip2;
  }}}}");

            tb.AssertNoDiagnostics();
            tb.FileContains("C.INPC.cs", "((NS.INot)this).OnPropertyChanged(\"Ip2\")");
            tb.FileDoesNotContain("C.INPC.cs", "void NS.INot.OnPropertyChanged(string");
            tb.FileDoesNotContain("C.INPC.cs", "IExternalNotifyPropertyChange");
        }