diff --git a/ReactiveGenerator.Tests/ReactiveGenerator/ReactiveGeneratorTests.cs b/ReactiveGenerator.Tests/ReactiveGenerator/ReactiveGeneratorTests.cs index 2e5f710..205874f 100644 --- a/ReactiveGenerator.Tests/ReactiveGenerator/ReactiveGeneratorTests.cs +++ b/ReactiveGenerator.Tests/ReactiveGenerator/ReactiveGeneratorTests.cs @@ -1269,4 +1269,297 @@ public partial class RegularClass return TestAndVerify(source); } + + [Fact] + public Task RequiredPropertyTest() + { + var source = @" + [Reactive] + public partial class Person + { + public required partial string Name { get; set; } + public required partial int Age { get; set; } + public partial string? OptionalNickname { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task RequiredPropertyWithReactiveObjectTest() + { + var source = @" + using ReactiveUI; + + [Reactive] + public partial class Person : ReactiveObject + { + public required partial string Name { get; set; } + public required partial DateOnly BirthDate { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task RequiredPropertyWithInheritanceTest() + { + var source = @" + [Reactive] + public abstract partial class Entity + { + public required partial string Id { get; set; } + } + + [Reactive] + public partial class Person : Entity + { + public required partial string Name { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task RequiredPropertyWithMixedModifiersTest() + { + var source = @" + [Reactive] + public partial class BaseClass + { + public required virtual partial string VirtualRequired { get; set; } + } + + [Reactive] + public partial class DerivedClass : BaseClass + { + public required override partial string VirtualRequired { get; set; } + public required partial string LocalRequired { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task AllPropertyModifiersTest() + { + var source = @" + [Reactive] + public partial class Base + { + // Static properties + public static partial string StaticProp { get; set; } + protected static partial string ProtectedStaticProp { get; set; } + + // Virtual and abstract properties + public virtual partial string VirtualProp { get; set; } + public abstract partial string AbstractProp { get; set; } + + // Required properties + public required partial string RequiredProp { get; set; } + + // Mixed modifiers + public required virtual partial string RequiredVirtualProp { get; set; } + } + + [Reactive] + public partial class Derived : Base + { + // New properties (shadowing) + public new partial string VirtualProp { get; set; } + + // Override properties + public override partial string AbstractProp { get; set; } + + // Sealed override properties + public sealed override partial string RequiredVirtualProp { get; set; } + + // Static shadows + public new static partial string StaticProp { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task StaticPropertyTest() + { + var source = @" + [Reactive] + public partial class TestClass + { + public static partial string GlobalConfig { get; set; } + private static partial int Counter { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task NewModifierTest() + { + var source = @" + [Reactive] + public partial class Base + { + public partial string Name { get; set; } + } + + [Reactive] + public partial class Derived : Base + { + public new partial string Name { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task SealedOverrideTest() + { + var source = @" + [Reactive] + public partial class Base + { + public virtual partial string VirtualProp { get; set; } + } + + [Reactive] + public partial class Derived : Base + { + public sealed override partial string VirtualProp { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task MixedModifiersTest() + { + var source = @" + [Reactive] + public partial class TestClass + { + // Static + Required + public static required partial string StaticRequired { get; set; } + + // New + Static + public new static partial string NewStatic { get; set; } + + // Virtual + Required + public virtual required partial string VirtualRequired { get; set; } + + // Override + Sealed + public sealed override partial string SealedOverride { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task AccessorModifiersTest() + { + var source = @" + [Reactive] + public partial class TestClass + { + // Property with private setter + public partial string Name { get; private set; } + + // Protected property with private getter + protected partial string Id { private get; set; } + + // Internal property with protected setter + internal partial string Code { get; protected set; } + + // Public property with protected internal setter + public partial string Key { get; protected internal set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task ModifierOrderingTest() + { + var source = @" + [Reactive] + public partial class Base + { + // Base class properties for override/shadowing + public virtual partial string VirtualProp { get; set; } + protected virtual partial string ProtectedVirtualProp { get; set; } + public static partial string StaticProp { get; set; } + public abstract partial string AbstractProp { get; set; } + } + + [Reactive] + public partial class Derived : Base + { + // Test new modifier comes first + public new partial string VirtualProp { get; set; } + + // Test new + static ordering + public new static partial string StaticProp { get; set; } + + // Test override + sealed + required ordering + public sealed override required partial string ProtectedVirtualProp { get; set; } + + // Test override + required ordering + public override required partial string AbstractProp { get; set; } + + // Test required only + public required partial string RequiredProp { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task InheritanceModifiersTest() + { + var source = @" + [Reactive] + public abstract partial class BaseClass + { + // Virtual property + public virtual partial string VirtualProp { get; set; } + + // Abstract property + public abstract partial string AbstractProp { get; set; } + } + + [Reactive] + public partial class DerivedClass : BaseClass + { + // Override property + public override partial string VirtualProp { get; set; } + + // Sealed override property + public sealed override partial string AbstractProp { get; set; } + }"; + + return TestAndVerify(source); + } + + [Fact] + public Task RequiredModifierTest() + { + var source = @" + [Reactive] + public partial class TestClass + { + // Required property + public required partial string Name { get; set; } + + // Required with virtual + public virtual required partial string VirtualRequired { get; set; } + + // Required with different access levels + protected required partial string ProtectedRequired { get; set; } + private required partial string PrivateRequired { get; set; } + }"; + + return TestAndVerify(source); + } } diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AccessorModifiersTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AccessorModifiersTest.verified.txt new file mode 100644 index 0000000..e31311e --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AccessorModifiersTest.verified.txt @@ -0,0 +1,127 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + }, + { + FileName: TestClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class TestClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: TestClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for TestClass. +/// +public partial class TestClass +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + private static readonly PropertyChangedEventArgs _idChangedEventArgs = new PropertyChangedEventArgs(nameof(Id)); + private static readonly PropertyChangedEventArgs _codeChangedEventArgs = new PropertyChangedEventArgs(nameof(Code)); + private static readonly PropertyChangedEventArgs _keyChangedEventArgs = new PropertyChangedEventArgs(nameof(Key)); + + public partial string Name + { + get => field; + private set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } + + protected partial string Id + { + private get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_idChangedEventArgs); + } + } + } + + internal partial string Code + { + get => field; + protected set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_codeChangedEventArgs); + } + } + } + + public partial string Key + { + get => field; + protected internal set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_keyChangedEventArgs); + } + } + } +} + + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AllPropertyModifiersTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AllPropertyModifiersTest.verified.txt new file mode 100644 index 0000000..4e0ceb7 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.AllPropertyModifiersTest.verified.txt @@ -0,0 +1,228 @@ +{ + Sources: [ + { + FileName: Base.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Base : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Base.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Base. +/// +public partial class Base +{ + private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); + private static readonly PropertyChangedEventArgs _protectedStaticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(ProtectedStaticProp)); + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + private static readonly PropertyChangedEventArgs _requiredPropChangedEventArgs = new PropertyChangedEventArgs(nameof(RequiredProp)); + private static readonly PropertyChangedEventArgs _requiredVirtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(RequiredVirtualProp)); + + public static partial string StaticProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_staticPropChangedEventArgs); + } + } + } + + protected static partial string ProtectedStaticProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_protectedStaticPropChangedEventArgs); + } + } + } + + public virtual partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + public abstract partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } + + public required partial string RequiredProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_requiredPropChangedEventArgs); + } + } + } + + public virtual required partial string RequiredVirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_requiredVirtualPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: Derived.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Derived. +/// +public partial class Derived +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + private static readonly PropertyChangedEventArgs _requiredVirtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(RequiredVirtualProp)); + private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); + + public new partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + public override partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } + + public override sealed partial string RequiredVirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_requiredVirtualPropChangedEventArgs); + } + } + } + + public new static partial string StaticProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_staticPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ClassWithStaticProperties.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ClassWithStaticProperties.verified.txt index e819cae..6d85940 100644 --- a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ClassWithStaticProperties.verified.txt +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ClassWithStaticProperties.verified.txt @@ -66,7 +66,7 @@ public partial class TestClass private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); private static readonly PropertyChangedEventArgs _instancePropChangedEventArgs = new PropertyChangedEventArgs(nameof(InstanceProp)); - public partial string StaticProp + public static partial string StaticProp { get => field; set diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.InheritanceModifiersTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.InheritanceModifiersTest.verified.txt new file mode 100644 index 0000000..703cc3b --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.InheritanceModifiersTest.verified.txt @@ -0,0 +1,144 @@ +{ + Sources: [ + { + FileName: BaseClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class BaseClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: BaseClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for BaseClass. +/// +public partial class BaseClass +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + + public virtual partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + public abstract partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: DerivedClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for DerivedClass. +/// +public partial class DerivedClass +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + + public override partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + public override sealed partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.MixedModifiersTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.MixedModifiersTest.verified.txt new file mode 100644 index 0000000..55d83e7 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.MixedModifiersTest.verified.txt @@ -0,0 +1,127 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + }, + { + FileName: TestClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class TestClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: TestClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for TestClass. +/// +public partial class TestClass +{ + private static readonly PropertyChangedEventArgs _staticRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticRequired)); + private static readonly PropertyChangedEventArgs _newStaticChangedEventArgs = new PropertyChangedEventArgs(nameof(NewStatic)); + private static readonly PropertyChangedEventArgs _virtualRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualRequired)); + private static readonly PropertyChangedEventArgs _sealedOverrideChangedEventArgs = new PropertyChangedEventArgs(nameof(SealedOverride)); + + public static partial string StaticRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_staticRequiredChangedEventArgs); + } + } + } + + public new static partial string NewStatic + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_newStaticChangedEventArgs); + } + } + } + + public virtual required partial string VirtualRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualRequiredChangedEventArgs); + } + } + } + + public override sealed partial string SealedOverride + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_sealedOverrideChangedEventArgs); + } + } + } +} + + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ModifierOrderingTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ModifierOrderingTest.verified.txt new file mode 100644 index 0000000..30d3aa5 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.ModifierOrderingTest.verified.txt @@ -0,0 +1,214 @@ +{ + Sources: [ + { + FileName: Base.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Base : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Base.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Base. +/// +public partial class Base +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _protectedVirtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(ProtectedVirtualProp)); + private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + + public virtual partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + protected virtual partial string ProtectedVirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_protectedVirtualPropChangedEventArgs); + } + } + } + + public static partial string StaticProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_staticPropChangedEventArgs); + } + } + } + + public abstract partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: Derived.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Derived. +/// +public partial class Derived +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); + private static readonly PropertyChangedEventArgs _protectedVirtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(ProtectedVirtualProp)); + private static readonly PropertyChangedEventArgs _abstractPropChangedEventArgs = new PropertyChangedEventArgs(nameof(AbstractProp)); + private static readonly PropertyChangedEventArgs _requiredPropChangedEventArgs = new PropertyChangedEventArgs(nameof(RequiredProp)); + + public new partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } + + public new static partial string StaticProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_staticPropChangedEventArgs); + } + } + } + + public override sealed required partial string ProtectedVirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_protectedVirtualPropChangedEventArgs); + } + } + } + + public override required partial string AbstractProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_abstractPropChangedEventArgs); + } + } + } + + public required partial string RequiredProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_requiredPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NestedClassesWithStaticAndInstanceMembers.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NestedClassesWithStaticAndInstanceMembers.verified.txt index 353c47a..6ed3988 100644 --- a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NestedClassesWithStaticAndInstanceMembers.verified.txt +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NestedClassesWithStaticAndInstanceMembers.verified.txt @@ -47,7 +47,7 @@ public partial class Container private static readonly PropertyChangedEventArgs _staticPropChangedEventArgs = new PropertyChangedEventArgs(nameof(StaticProp)); private static readonly PropertyChangedEventArgs _instancePropChangedEventArgs = new PropertyChangedEventArgs(nameof(InstanceProp)); - public partial string StaticProp + public static partial string StaticProp { get => field; set diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NewModifierTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NewModifierTest.verified.txt new file mode 100644 index 0000000..665e839 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.NewModifierTest.verified.txt @@ -0,0 +1,116 @@ +{ + Sources: [ + { + FileName: Base.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Base : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Base.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Base. +/// +public partial class Base +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + + public partial string Name + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } +} + + }, + { + FileName: Derived.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Derived. +/// +public partial class Derived +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + + public new partial string Name + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredModifierTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredModifierTest.verified.txt new file mode 100644 index 0000000..8910e55 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredModifierTest.verified.txt @@ -0,0 +1,127 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + }, + { + FileName: TestClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class TestClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: TestClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for TestClass. +/// +public partial class TestClass +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + private static readonly PropertyChangedEventArgs _virtualRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualRequired)); + private static readonly PropertyChangedEventArgs _protectedRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(ProtectedRequired)); + private static readonly PropertyChangedEventArgs _privateRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(PrivateRequired)); + + public required partial string Name + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } + + public virtual required partial string VirtualRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualRequiredChangedEventArgs); + } + } + } + + protected required partial string ProtectedRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_protectedRequiredChangedEventArgs); + } + } + } + + private required partial string PrivateRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_privateRequiredChangedEventArgs); + } + } + } +} + + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyTest.verified.txt new file mode 100644 index 0000000..346bb09 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyTest.verified.txt @@ -0,0 +1,113 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: Person.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Person : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Person.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Person. +/// +public partial class Person +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + private static readonly PropertyChangedEventArgs _ageChangedEventArgs = new PropertyChangedEventArgs(nameof(Age)); + private static readonly PropertyChangedEventArgs _optionalNicknameChangedEventArgs = new PropertyChangedEventArgs(nameof(OptionalNickname)); + + public required partial string Name + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } + + public required partial int Age + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_ageChangedEventArgs); + } + } + } + + public partial string? OptionalNickname + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_optionalNicknameChangedEventArgs); + } + } + } +} + + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithInheritanceTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithInheritanceTest.verified.txt new file mode 100644 index 0000000..3f34e72 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithInheritanceTest.verified.txt @@ -0,0 +1,116 @@ +{ + Sources: [ + { + FileName: Entity.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Entity : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Entity.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Entity. +/// +public partial class Entity +{ + private static readonly PropertyChangedEventArgs _idChangedEventArgs = new PropertyChangedEventArgs(nameof(Id)); + + public required partial string Id + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_idChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: Person.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Person. +/// +public partial class Person +{ + private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name)); + + public required partial string Name + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_nameChangedEventArgs); + } + } + } +} + + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithMixedModifiersTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithMixedModifiersTest.verified.txt new file mode 100644 index 0000000..75383c5 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithMixedModifiersTest.verified.txt @@ -0,0 +1,130 @@ +{ + Sources: [ + { + FileName: BaseClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class BaseClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: BaseClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for BaseClass. +/// +public partial class BaseClass +{ + private static readonly PropertyChangedEventArgs _virtualRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualRequired)); + + public virtual required partial string VirtualRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualRequiredChangedEventArgs); + } + } + } +} + + }, + { + FileName: DerivedClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for DerivedClass. +/// +public partial class DerivedClass +{ + private static readonly PropertyChangedEventArgs _virtualRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualRequired)); + private static readonly PropertyChangedEventArgs _localRequiredChangedEventArgs = new PropertyChangedEventArgs(nameof(LocalRequired)); + + public override required partial string VirtualRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualRequiredChangedEventArgs); + } + } + } + + public required partial string LocalRequired + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_localRequiredChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithReactiveObjectTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithReactiveObjectTest.verified.txt new file mode 100644 index 0000000..ca561c2 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.RequiredPropertyWithReactiveObjectTest.verified.txt @@ -0,0 +1,56 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: Person.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using ReactiveUI; + +/// +/// A partial class implementation for Person. +/// +public partial class Person +{ + public required partial string Name + { + get => field; + set => this.RaiseAndSetIfChanged(ref field, value); + } + + public required partial DateOnly BirthDate + { + get => field; + set => this.RaiseAndSetIfChanged(ref field, value); + } +} + + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.SealedOverrideTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.SealedOverrideTest.verified.txt new file mode 100644 index 0000000..5d9fa86 --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.SealedOverrideTest.verified.txt @@ -0,0 +1,116 @@ +{ + Sources: [ + { + FileName: Base.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class Base : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: Base.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Base. +/// +public partial class Base +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + + public virtual partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: Derived.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for Derived. +/// +public partial class Derived +{ + private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp)); + + public override sealed partial string VirtualProp + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_virtualPropChangedEventArgs); + } + } + } +} + + }, + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.StaticPropertyTest.verified.txt b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.StaticPropertyTest.verified.txt new file mode 100644 index 0000000..eebfbbb --- /dev/null +++ b/ReactiveGenerator.Tests/Snapshots/ReactiveGeneratorTests.StaticPropertyTest.verified.txt @@ -0,0 +1,99 @@ +{ + Sources: [ + { + FileName: IgnoreReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class IgnoreReactiveAttribute : Attribute +{ + public IgnoreReactiveAttribute() { } +} + }, + { + FileName: ReactiveAttribute.g.cs, + Source: +// +using System; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] +sealed class ReactiveAttribute : Attribute +{ + public ReactiveAttribute() { } +} + }, + { + FileName: TestClass.INPC.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +public partial class TestClass : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs args) + { + PropertyChanged?.Invoke(this, args); + } +} + + }, + { + FileName: TestClass.ReactiveProperties.g.cs, + Source: +// +#nullable enable + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +/// +/// A partial class implementation for TestClass. +/// +public partial class TestClass +{ + private static readonly PropertyChangedEventArgs _globalConfigChangedEventArgs = new PropertyChangedEventArgs(nameof(GlobalConfig)); + private static readonly PropertyChangedEventArgs _counterChangedEventArgs = new PropertyChangedEventArgs(nameof(Counter)); + + public static partial string GlobalConfig + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_globalConfigChangedEventArgs); + } + } + } + + private static partial int Counter + { + get => field; + set + { + if (!Equals(field, value)) + { + field = value; + OnPropertyChanged(_counterChangedEventArgs); + } + } + } +} + + } + ], + Diagnostics: null +} \ No newline at end of file diff --git a/ReactiveGenerator/ReactiveGenerator.cs b/ReactiveGenerator/ReactiveGenerator.cs index 01f4cff..0c2eec7 100644 --- a/ReactiveGenerator/ReactiveGenerator.cs +++ b/ReactiveGenerator/ReactiveGenerator.cs @@ -21,6 +21,20 @@ public string GetPropertyModifiers() { var modifiers = new List(); + // Get 'new' modifier from syntax if present + if (Property.DeclaringSyntaxReferences.Length > 0) + { + var syntax = Property.DeclaringSyntaxReferences[0].GetSyntax(); + if (syntax is PropertyDeclarationSyntax propertyDeclaration && + propertyDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.NewKeyword))) + { + modifiers.Add("new"); + } + } + + if (Property.IsStatic) + modifiers.Add("static"); + if (Property.IsOverride) modifiers.Add("override"); else if (Property.IsVirtual) @@ -28,6 +42,13 @@ public string GetPropertyModifiers() else if (Property.IsAbstract) modifiers.Add("abstract"); + // sealed only makes sense with override + if (Property.IsSealed && Property.IsOverride) + modifiers.Add("sealed"); + + if (Property.IsRequired) + modifiers.Add("required"); + return string.Join(" ", modifiers); } } @@ -711,11 +732,9 @@ private static void GenerateFieldKeywordProperty( var getterAccessibility = TypeHelper.GetAccessorAccessibility(property.GetMethod); var setterAccessibility = TypeHelper.GetAccessorAccessibility(property.SetMethod); - // Create PropertyInfo to get modifiers var propInfo = new PropertyInfo(property, false, false, false); var modifiers = propInfo.GetPropertyModifiers(); - // Combine modifiers with accessibility and partial var declarationModifiers = new List { propertyAccessibility }; if (!string.IsNullOrEmpty(modifiers)) declarationModifiers.Add(modifiers);