diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithIdenticalClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs new file mode 100644 index 0000000..2f7525d --- /dev/null +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -0,0 +1,37 @@ +//HintName: ReactiveUI.SourceGenerators.AccessModifier.g.cs +// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +// +#pragma warning disable +#nullable enable +namespace ReactiveUI.SourceGenerators; + +/// +/// AccessModifier. +/// +internal enum AccessModifier +{ + Public, + Protected, + Internal, + Private, + InternalProtected, + PrivateProtected, + Init, +} + +/// +/// InheritanceModifier. +/// +internal enum InheritanceModifier +{ + None, + Virtual, + Override, + New, +} +#nullable restore +#pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs new file mode 100644 index 0000000..d8b5f0d --- /dev/null +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -0,0 +1,40 @@ +//HintName: ReactiveUI.SourceGenerators.ReactiveAttribute.g.cs +// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; + +// +#pragma warning disable +#nullable enable +namespace ReactiveUI.SourceGenerators; + +/// +/// ReactiveAttribute. +/// +/// +[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] +internal sealed class ReactiveAttribute : Attribute +{ + /// + /// Gets the AccessModifier of the set property. + /// + /// + /// The AccessModifier of the set property. + /// + public AccessModifier SetModifier { get; init; } + + /// + /// Gets the InheritanceModifier of the property. + /// + public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } +} +#nullable restore +#pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#TestNs.TestVM.Properties.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#TestNs.TestVM.Properties.g.verified.cs new file mode 100644 index 0000000..85a5659 --- /dev/null +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithInit#TestNs.TestVM.Properties.g.verified.cs @@ -0,0 +1,26 @@ +//HintName: TestNs.TestVM.Properties.g.cs +// +using ReactiveUI; + +#pragma warning disable +#nullable enable + +namespace TestNs +{ + /// + /// Partial class for the TestVM which contains ReactiveUI Reactive property initialization. + /// + public partial class TestVM + { + /// + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public string MustBeSet + { + get => _mustBeSet; + [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_mustBeSet")] + set => this.RaiseAndSetIfChanged(ref _mustBeSet, value); + } + } +} +#nullable restore +#pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs index 3fe74d1..2f7525d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs @@ -20,6 +20,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs index d2024dc..d8b5f0d 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithNestedClass#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs @@ -30,6 +30,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore \ No newline at end of file diff --git a/src/ReactiveUI.SourceGenerator.Tests/ReactiveUI.SourceGenerators.Tests.csproj b/src/ReactiveUI.SourceGenerator.Tests/ReactiveUI.SourceGenerators.Tests.csproj index a692b2c..36e09a3 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/ReactiveUI.SourceGenerators.Tests.csproj +++ b/src/ReactiveUI.SourceGenerator.Tests/ReactiveUI.SourceGenerators.Tests.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - + 12.0 false true $(NoWarn);CA1812;CA1001 diff --git a/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs b/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs index bd113f4..aafe582 100644 --- a/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs +++ b/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs @@ -245,4 +245,31 @@ public partial class TestInnerClass3 : ReactiveObject // Act: Initialize the helper and run the generator. Assert: Verify the generated code. return TestHelper.TestPass(sourceCode); } + + /// + /// Tests that the source generator correctly generates reactive properties. + /// + /// A task to monitor the async. + [Fact] + public Task FromReactivePropertiesWithInit() + { + // Arrange: Setup the source code that matches the generator input expectations. + const string sourceCode = """ + using System; + using ReactiveUI; + using ReactiveUI.SourceGenerators; + using System.Reactive.Linq; + + namespace TestNs; + + public partial class TestVM : ReactiveObject + { + [Reactive(SetModifier = AccessModifier.Init, UseRequired = true)] + private string _mustBeSet; + } + """; + + // Act: Initialize the helper and run the generator. Assert: Verify the generated code. + return TestHelper.TestPass(sourceCode); + } } diff --git a/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs b/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs index d0b7fcc..95bd765 100644 --- a/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs +++ b/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs @@ -3,6 +3,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -56,11 +57,16 @@ public partial class TestViewModel : ReactiveObject, IActivatableViewModel, IDis [Reactive(Inheritance = InheritanceModifier.Virtual, SetModifier = AccessModifier.Protected)] private string? _name; + [Reactive(SetModifier = AccessModifier.Init, UseRequired = true)] + private string _mustBeSet; + /// /// Initializes a new instance of the class. /// + [SetsRequiredMembers] public TestViewModel() { + MustBeSet = "Test"; this.WhenActivated(disposables => { Console.Out.WriteLine("Activated"); diff --git a/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs b/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs index 5baba36..3de263d 100644 --- a/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs +++ b/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs @@ -39,6 +39,7 @@ internal enum AccessModifier Private, InternalProtected, PrivateProtected, + Init, } /// @@ -155,6 +156,11 @@ internal sealed class ReactiveAttribute : Attribute /// Gets the InheritanceModifier of the property. /// public InheritanceModifier Inheritance { get; init; } + + /// + /// Use Required attribute to indicate that the property is required. + /// + public bool UseRequired { get; init; } } #nullable restore #pragma warning restore diff --git a/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs b/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs index 9908c3e..59ca939 100644 --- a/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs +++ b/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs @@ -20,4 +20,5 @@ internal sealed record PropertyInfo( bool IncludeMemberNotNullOnSetAccessor, EquatableArray ForwardedAttributes, string AccessModifier, - string Inheritance); + string Inheritance, + string UseRequired); diff --git a/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs b/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs index 0f1786b..ab07e43 100644 --- a/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs +++ b/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs @@ -67,14 +67,17 @@ public sealed partial class ReactiveGenerator attributeData.TryGetNamedArgument("SetModifier", out int accessModifierArgument); var accessModifier = accessModifierArgument switch { - 1 => "protected ", - 2 => "internal ", - 3 => "private ", - 4 => "internal protected ", - 5 => "private protected ", - _ => string.Empty, + 1 => "protected set", + 2 => "internal set", + 3 => "private set", + 4 => "internal protected set", + 5 => "private protected set", + 6 => "init", + _ => "set", }; + token.ThrowIfCancellationRequested(); + // Get Inheritance value from the attribute attributeData.TryGetNamedArgument("Inheritance", out int inheritanceArgument); var inheritance = inheritanceArgument switch @@ -87,6 +90,12 @@ public sealed partial class ReactiveGenerator token.ThrowIfCancellationRequested(); + // Get Inheritance value from the attribute + attributeData.TryGetNamedArgument("UseRequired", out bool useRequiredArgument); + var useRequired = useRequiredArgument ? "required " : string.Empty; + + token.ThrowIfCancellationRequested(); + // Get the property type and name var typeNameWithNullabilityAnnotations = fieldSymbol.Type.GetFullyQualifiedNameWithNullabilityAnnotations(); var fieldName = fieldSymbol.Name; @@ -219,7 +228,8 @@ public sealed partial class ReactiveGenerator includeMemberNotNullOnSetAccessor, forwardedAttributesString, accessModifier, - inheritance), + inheritance, + useRequired), builder.ToImmutable()); } @@ -303,11 +313,11 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo) $$""" /// {{propertyAttributes}} - {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} + {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.UseRequired}}{{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; [global::System.Diagnostics.CodeAnalysis.MemberNotNull("{{propertyInfo.FieldName}}")] - {{propertyInfo.AccessModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); + {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); } """; } @@ -316,7 +326,7 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo) $$""" /// {{propertyAttributes}} - {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{propertyInfo.AccessModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); } + {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.UseRequired}}{{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); } """; }