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 b30d4d5..1756eef 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
@@ -21,5 +21,16 @@ internal enum AccessModifier
InternalProtected,
PrivateProtected,
}
+
+///
+/// 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.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperiesWithAttributes#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
index bd89c3c..3fde86e 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
@@ -25,6 +25,11 @@ internal sealed class ReactiveAttribute : Attribute
/// The AccessModifier of the set property.
///
public AccessModifier SetModifier { get; init; }
+
+ ///
+ /// Gets the InheritanceModifier of the property.
+ ///
+ public InheritanceModifier Inheritance { 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 b30d4d5..1756eef 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
@@ -21,5 +21,16 @@ internal enum AccessModifier
InternalProtected,
PrivateProtected,
}
+
+///
+/// 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.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactiveProperties#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
index bd89c3c..3fde86e 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
@@ -25,6 +25,11 @@ internal sealed class ReactiveAttribute : Attribute
/// The AccessModifier of the set property.
///
public AccessModifier SetModifier { get; init; }
+
+ ///
+ /// Gets the InheritanceModifier of the property.
+ ///
+ public InheritanceModifier Inheritance { 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 b30d4d5..1756eef 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
@@ -21,5 +21,16 @@ internal enum AccessModifier
InternalProtected,
PrivateProtected,
}
+
+///
+/// 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.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAccess#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
index bd89c3c..3fde86e 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
@@ -25,6 +25,11 @@ internal sealed class ReactiveAttribute : Attribute
/// The AccessModifier of the set property.
///
public AccessModifier SetModifier { get; init; }
+
+ ///
+ /// Gets the InheritanceModifier of the property.
+ ///
+ public InheritanceModifier Inheritance { 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
new file mode 100644
index 0000000..1756eef
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs
@@ -0,0 +1,36 @@
+//HintName: ReactiveUI.SourceGenerators.AccessModifier.g.cs
+// Copyright (c) 2024 .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,
+}
+
+///
+/// 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.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
new file mode 100644
index 0000000..3fde86e
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
@@ -0,0 +1,35 @@
+//HintName: ReactiveUI.SourceGenerators.ReactiveAttribute.g.cs
+// Copyright (c) 2024 .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; }
+}
+#nullable restore
+#pragma warning restore
\ No newline at end of file
diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#TestVM.Properties.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#TestVM.Properties.g.verified.cs
new file mode 100644
index 0000000..265a551
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesWithAttributesAccessAndInheritance#TestVM.Properties.g.verified.cs
@@ -0,0 +1,23 @@
+//HintName: 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]
+ [global::System.Runtime.Serialization.DataMemberAttribute()]
+ [global::System.Text.Json.Serialization.JsonIncludeAttribute()]
+ public string? Name { get => _name; set => this.RaiseAndSetIfChanged(ref _name, value); }
+ }
+}
+#nullable restore
+#pragma warning restore
\ No newline at end of file
diff --git a/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs b/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs
index 454a53d..3b7899c 100644
--- a/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs
+++ b/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs
@@ -109,5 +109,39 @@ public partial class TestVM : ReactiveObject
return VerifyGenerator(driver);
}
+ ///
+ /// Froms the reactive properties with attributes and access and inheritance.
+ ///
+ /// A task to monitor the async.
+ [Fact]
+ public Task FromReactivePropertiesWithAttributesAccessAndInheritance()
+ {
+ // Arrange: Setup the source code that matches the generator input expectations.
+ const string sourceCode = @"
+ using System;
+ using System.Runtime.Serialization;
+ using System.Text.Json.Serialization;
+ using ReactiveUI;
+ using ReactiveUI.SourceGenerators;
+ using System.Reactive.Linq;
+
+ namespace TestNs;
+
+ public partial class TestVM : ReactiveObject
+ {
+ [property: JsonInclude]
+ [DataMember]
+ [Reactive(Inheritance = InheritanceModifier.Virtual, SetModifier = AccessModifier.Protected)]
+ private string? _name;
+ }
+ ";
+
+ // Act: Initialize the helper and run the generator.
+ var driver = TestHelper.TestPass(sourceCode);
+
+ // Assert: Verify the generated code.
+ return VerifyGenerator(driver);
+ }
+
private SettingsTask VerifyGenerator(GeneratorDriver driver) => Verify(driver).UseDirectory(TestHelper.VerifiedFilePath()).ScrubLinesContaining("[global::System.CodeDom.Compiler.GeneratedCode(\"");
}
diff --git a/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs b/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs
index 37b31aa..eb453ea 100644
--- a/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs
+++ b/src/ReactiveUI.SourceGenerators.Execute/TestViewModel.cs
@@ -51,6 +51,11 @@ public partial class TestViewModel : ReactiveObject, IActivatableViewModel, IDis
[Reactive]
private string _myStringProperty = "test";
+ [property: JsonInclude]
+ [DataMember]
+ [Reactive(Inheritance = InheritanceModifier.Virtual, SetModifier = AccessModifier.Protected)]
+ private string? _name;
+
///
/// Initializes a new instance of the class.
///
diff --git a/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs b/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs
index 418bd0c..5baba36 100644
--- a/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs
+++ b/src/ReactiveUI.SourceGenerators/AttributeDefinitions.cs
@@ -40,6 +40,17 @@ internal enum AccessModifier
InternalProtected,
PrivateProtected,
}
+
+ ///
+ /// InheritanceModifier.
+ ///
+ internal enum InheritanceModifier
+ {
+ None,
+ Virtual,
+ Override,
+ New,
+ }
#nullable restore
#pragma warning restore
""";
@@ -105,6 +116,12 @@ internal sealed class ReactiveCommandAttribute : Attribute
public const string ReactiveAttributeType = "ReactiveUI.SourceGenerators.ReactiveAttribute";
+ ///
+ /// Gets the reactive attribute.
+ ///
+ ///
+ /// The reactive attribute.
+ ///
public static string ReactiveAttribute => $$"""
// Copyright (c) {{DateTime.Now.Year}} .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
@@ -133,6 +150,11 @@ internal sealed class ReactiveAttribute : Attribute
/// The AccessModifier of the set property.
///
public AccessModifier SetModifier { get; init; }
+
+ ///
+ /// Gets the InheritanceModifier of the property.
+ ///
+ public InheritanceModifier Inheritance { get; init; }
}
#nullable restore
#pragma warning restore
diff --git a/src/ReactiveUI.SourceGenerators/ObservableAsProperty/ObservableAsPropertyGenerator{FromField}.Execute.cs b/src/ReactiveUI.SourceGenerators/ObservableAsProperty/ObservableAsPropertyGenerator{FromField}.Execute.cs
index b4aaa58..f49f68b 100644
--- a/src/ReactiveUI.SourceGenerators/ObservableAsProperty/ObservableAsPropertyGenerator{FromField}.Execute.cs
+++ b/src/ReactiveUI.SourceGenerators/ObservableAsProperty/ObservableAsPropertyGenerator{FromField}.Execute.cs
@@ -55,6 +55,16 @@ public sealed partial class ObservableAsPropertyGenerator
// Get the can PropertyName member, if any
attributeData.TryGetNamedArgument("ReadOnly", out bool? isReadonly);
+ // Get Inheritance value from the attribute
+ attributeData.TryGetNamedArgument("Inheritance", out int? inheritanceArgument);
+ var inheritance = inheritanceArgument switch
+ {
+ 1 => " virtual",
+ 2 => " override",
+ 3 => " new",
+ _ => string.Empty,
+ };
+
token.ThrowIfCancellationRequested();
// Get the property type and name
@@ -198,7 +208,8 @@ public sealed partial class ObservableAsPropertyGenerator
isReferenceTypeOrUnconstraindTypeParameter,
includeMemberNotNullOnSetAccessor,
forwardedPropertyAttributes,
- isReadonly == false ? string.Empty : "readonly"),
+ isReadonly == false ? string.Empty : "readonly",
+ inheritance),
builder.ToImmutable());
}
diff --git a/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs b/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs
index 140be3b..bcb7c1a 100644
--- a/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs
+++ b/src/ReactiveUI.SourceGenerators/Reactive/Models/PropertyInfo.cs
@@ -24,4 +24,5 @@ internal sealed record PropertyInfo(
bool IsReferenceTypeOrUnconstrainedTypeParameter,
bool IncludeMemberNotNullOnSetAccessor,
EquatableArray ForwardedAttributes,
- string AccessModifier);
+ string AccessModifier,
+ string Inheritance);
diff --git a/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs b/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs
index cc95503..169228d 100644
--- a/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs
+++ b/src/ReactiveUI.SourceGenerators/Reactive/ReactiveGenerator.Execute.cs
@@ -63,16 +63,25 @@ public sealed partial class ReactiveGenerator
token.ThrowIfCancellationRequested();
// Get AccessModifier enum value from the attribute
- attributeData.TryGetNamedArgument("SetModifier", out int? accessModifierArgument);
+ attributeData.TryGetNamedArgument("SetModifier", out int accessModifierArgument);
var accessModifier = accessModifierArgument switch
{
- 0 => "public",
- 1 => "protected",
- 2 => "internal",
- 3 => "private",
- 4 => "internal protected",
- 5 => "private protected",
- _ => "public",
+ 1 => "protected ",
+ 2 => "internal ",
+ 3 => "private ",
+ 4 => "internal protected ",
+ 5 => "private protected ",
+ _ => string.Empty,
+ };
+
+ // Get Inheritance value from the attribute
+ attributeData.TryGetNamedArgument("Inheritance", out int inheritanceArgument);
+ var inheritance = inheritanceArgument switch
+ {
+ 1 => " virtual",
+ 2 => " override",
+ 3 => " new",
+ _ => string.Empty,
};
token.ThrowIfCancellationRequested();
@@ -214,7 +223,8 @@ public sealed partial class ReactiveGenerator
isReferenceTypeOrUnconstraindTypeParameter,
includeMemberNotNullOnSetAccessor,
forwardedAttributesString,
- accessModifier),
+ accessModifier,
+ inheritance),
builder.ToImmutable());
}
@@ -268,12 +278,6 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
return string.Empty;
}
- var setModifier = propertyInfo.AccessModifier + " ";
- if (setModifier == "public ")
- {
- setModifier = string.Empty;
- }
-
var propertyAttributes = string.Join("\n ", AttributeDefinitions.ExcludeFromCodeCoverage.Concat(propertyInfo.ForwardedAttributes));
if (propertyInfo.IncludeMemberNotNullOnSetAccessor)
@@ -282,11 +286,11 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
$$"""
///
{{propertyAttributes}}
- {{propertyInfo.TargetVisibility}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}}
+ {{propertyInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}}
{
get => {{propertyInfo.FieldName}};
[global::System.Diagnostics.CodeAnalysis.MemberNotNull("{{propertyInfo.FieldName}}")]
- {{setModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value);
+ {{propertyInfo.AccessModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value);
}
""";
}
@@ -295,7 +299,7 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
$$"""
///
{{propertyAttributes}}
- {{propertyInfo.TargetVisibility}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{setModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); }
+ {{propertyInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{propertyInfo.AccessModifier}}set => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); }
""";
}