diff --git a/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#ReactiveUI.SourceGenerators.AccessModifier.g.verified.cs
new file mode 100644
index 0000000..2f7525d
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#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.FromReactivePropertiesCalledValue#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#ReactiveUI.SourceGenerators.ReactiveAttribute.g.verified.cs
new file mode 100644
index 0000000..a13d64c
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#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 | AttributeTargets.Property, 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.FromReactivePropertiesCalledValue#TestNs.TestVM.Properties.g.verified.cs b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#TestNs.TestVM.Properties.g.verified.cs
new file mode 100644
index 0000000..c8b969d
--- /dev/null
+++ b/src/ReactiveUI.SourceGenerator.Tests/REACTIVE/ReactiveGeneratorTests.FromReactivePropertiesCalledValue#TestNs.TestVM.Properties.g.verified.cs
@@ -0,0 +1,27 @@
+//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 Value
+ {
+ get => value;
+ [global::System.Diagnostics.CodeAnalysis.MemberNotNull("this.value")]
+ set => this.RaiseAndSetIfChanged(ref this.value, 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 c87c702..5ac107b 100644
--- a/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs
+++ b/src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveGeneratorTests.cs
@@ -41,6 +41,33 @@ public partial class TestVM : ReactiveObject
return TestHelper.TestPass(sourceCode);
}
+ ///
+ /// Tests that the source generator correctly generates reactive properties.
+ ///
+ /// A task to monitor the async.
+ [Fact]
+ public Task FromReactivePropertiesCalledValue()
+ {
+ // 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]
+ private string value = string.Empty;
+ }
+ """;
+
+ // 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.
///
diff --git a/src/ReactiveUI.SourceGenerators.Execute/TestClassOAPH_VM.cs b/src/ReactiveUI.SourceGenerators.Execute/TestClassOAPH_VM.cs
index f24c8cb..bbfc266 100644
--- a/src/ReactiveUI.SourceGenerators.Execute/TestClassOAPH_VM.cs
+++ b/src/ReactiveUI.SourceGenerators.Execute/TestClassOAPH_VM.cs
@@ -19,6 +19,11 @@ public partial class TestClassOAPH_VM : ReactiveObject
[Reactive]
private bool _reactiveTestField;
+ [Reactive]
+#pragma warning disable SX1309 // Field names should begin with underscore
+ private string value = string.Empty;
+#pragma warning restore SX1309 // Field names should begin with underscore
+
///
/// Initializes a new instance of the class.
///
diff --git a/src/ReactiveUI.SourceGenerators.Roslyn/Reactive/ReactiveGenerator.Execute.cs b/src/ReactiveUI.SourceGenerators.Roslyn/Reactive/ReactiveGenerator.Execute.cs
index f6537f1..2037c33 100644
--- a/src/ReactiveUI.SourceGenerators.Roslyn/Reactive/ReactiveGenerator.Execute.cs
+++ b/src/ReactiveUI.SourceGenerators.Roslyn/Reactive/ReactiveGenerator.Execute.cs
@@ -304,6 +304,12 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
return string.Empty;
}
+ var fieldName = propertyInfo.FieldName;
+ if (propertyInfo.FieldName == "value")
+ {
+ fieldName = "this.value";
+ }
+
var fieldSyntax = string.Empty;
var partialModifier = propertyInfo.IsProperty ? "partial " : string.Empty;
if (propertyInfo.IsProperty)
@@ -318,13 +324,13 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
return
$$"""
{{fieldSyntax}}
- ///
+ ///
{{propertyAttributes}}
{{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{partialModifier}}{{propertyInfo.UseRequired}}{{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}}
{
get => {{propertyInfo.FieldName}};
- [global::System.Diagnostics.CodeAnalysis.MemberNotNull("{{propertyInfo.FieldName}}")]
- {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value);
+ [global::System.Diagnostics.CodeAnalysis.MemberNotNull("{{fieldName}}")]
+ {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{fieldName}}, value);
}
""";
}
@@ -332,9 +338,9 @@ private static string GetPropertySyntax(PropertyInfo propertyInfo)
return
$$"""
{{fieldSyntax}}
- ///
+ ///
{{propertyAttributes}}
- {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{partialModifier}}{{propertyInfo.UseRequired}}{{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{propertyInfo.FieldName}}, value); }
+ {{propertyInfo.TargetInfo.TargetVisibility}}{{propertyInfo.Inheritance}} {{partialModifier}}{{propertyInfo.UseRequired}}{{propertyInfo.TypeNameWithNullabilityAnnotations}} {{propertyInfo.PropertyName}} { get => {{propertyInfo.FieldName}}; {{propertyInfo.AccessModifier}} => this.RaiseAndSetIfChanged(ref {{fieldName}}, value); }
""";
}
}