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

Code before:
				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private string? _title;
					// Title 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.Title);
					}
				}
			}
			""";

		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 Title property access
		var allGeneratedCode = string.Join("\n\n", result.GeneratedFiles.Values);
		Assert.Contains("Title", allGeneratedCode, System.StringComparison.Ordinal);
	}

	[Fact]
	public void GenerateBindingToObservablePropertyCollection()
	{
		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 Tag { }

				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private ObservableCollection<Tag> _tags = new();
					// Tags property will be generated by CommunityToolkit.Mvvm
				}

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

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

Code after:

			namespace TestApp
			{
				public class MyViewModel
				{
					[CommunityToolkit.Mvvm.ComponentModel.ObservableProperty]
					private string? _title;
					// Title 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.Title);
					}
				}
			}
			""";

		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, \"Title\")", allGeneratedCode, System.StringComparison.Ordinal);
		// Check that setter assigns to .Title
		Assert.Contains("source.Title = value;", allGeneratedCode, System.StringComparison.Ordinal);
	}

	[Fact]
	public void GenerateBindingToObservablePropertyCollection()
	{
		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 Tag { }