Repository: dotnet/maui
File: src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs (C#)

Code before:
				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private string? name;
					// Name property will be generated by CommunityToolkit.Mvvm
				}

				public class TestCode
				{
					public void Test()
					{
						var label = new Label();
						label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name);
					}
				}
			}
			""";

		var result = SourceGenHelpers.Run(source);

		// The binding should be generated successfully with ObservableProperty inference
		Assert.NotNull(result.Binding);

		// Verify the generated interceptor code contains the Name property access
		var allGeneratedCode = string.Join("\n\n", result.GeneratedFiles.Values);
		Assert.Contains("Name", allGeneratedCode, System.StringComparison.Ordinal);

		// Note: There will be compilation errors because Name doesn't actually exist,
		// but the interceptor code itself is generated correctly. In real usage with
		// CommunityToolkit.Mvvm, the property would exist and compile successfully.
	}

	[Fact]
	public void GenerateBindingToObservablePropertyFromUnderscorePrefixedField()
	{
		var source = """
			using Microsoft.Maui.Controls;
			using System.Collections.ObjectModel;

			namespace CommunityToolkit.Mvvm.ComponentModel
			{
				[System.AttributeUsage(System.AttributeTargets.Field)]
				public class ObservablePropertyAttribute : System.Attribute { }
			}

			namespace TestApp
			{
				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private string? _title;

Review comment (bug):
Let's improve the assert to check for the full expected getter and setter: `"source => (source.Name, true)"`, `source.Name = value;`.

I might be wrong about the exact values of the expected generated expressions, so please double check the actual outputs.

Code after:
				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private string? name;
					// Name property will be generated by CommunityToolkit.Mvvm
				}

				public class TestCode
				{
					public void Test()
					{
						var label = new Label();
						label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name);
					}
				}
			}
			""";

		var result = SourceGenHelpers.Run(source);

		// The binding should be generated successfully with ObservableProperty inference
		Assert.NotNull(result.Binding);

		// Verify the generated interceptor code contains the correct getter and setter references
		var allGeneratedCode = string.Join("\n\n", result.GeneratedFiles.Values);
		// Check that the handler contains the property access
		Assert.Contains("new(static source => source, \"Name\")", allGeneratedCode, System.StringComparison.Ordinal);
		// Check that setter assigns to .Name
		Assert.Contains("source.Name = value;", allGeneratedCode, System.StringComparison.Ordinal);

		// Note: There will be compilation errors because Name doesn't actually exist,
		// but the interceptor code itself is generated correctly. In real usage with
		// CommunityToolkit.Mvvm, the property would exist and compile successfully.
	}

	[Fact]
	public void GenerateBindingToObservablePropertyFromUnderscorePrefixedField()
	{
		var source = """
			using Microsoft.Maui.Controls;
			using System.Collections.ObjectModel;

			namespace CommunityToolkit.Mvvm.ComponentModel
			{
				[System.AttributeUsage(System.AttributeTargets.Field)]
				public class ObservablePropertyAttribute : System.Attribute { }
			}

			namespace TestApp
			{
				public class MyViewModel