File: BindingTransformer.cs
Web Access
Project: src\src\Controls\src\BindingSourceGen\Controls.BindingSourceGen.csproj (Microsoft.Maui.Controls.BindingSourceGen)

namespace Microsoft.Maui.Controls.BindingSourceGen;
 
public interface IBindingInvocationTransformer
{
	BindingInvocationDescription Transform(BindingInvocationDescription BindingInvocationDescription);
}
 
public class ReferenceTypesConditionalAccessTransformer : IBindingInvocationTransformer
{
	public BindingInvocationDescription Transform(BindingInvocationDescription BindingInvocationDescription)
	{
		var path = TransformPath(BindingInvocationDescription);
		return BindingInvocationDescription with { Path = path };
	}
 
	private static EquatableArray<IPathPart> TransformPath(BindingInvocationDescription BindingInvocationDescription)
	{
		var newPath = new List<IPathPart>();
		foreach (var pathPart in BindingInvocationDescription.Path)
		{
			var sourceIsReferenceType = newPath.Count == 0 && !BindingInvocationDescription.SourceType.IsValueType;
			var previousPartIsReferenceType = newPath.Count > 0 && PreviousPartIsReferenceType(newPath.Last());
 
			if (pathPart is not MemberAccess && pathPart is not IndexAccess)
			{
				newPath.Add(pathPart);
			}
			else if (sourceIsReferenceType || previousPartIsReferenceType)
			{
				newPath.Add(new ConditionalAccess(pathPart));
			}
			else
			{
				newPath.Add(pathPart);
			}
		}
 
		return new EquatableArray<IPathPart>(newPath.ToArray());
 
		static bool PreviousPartIsReferenceType(IPathPart previousPathPart) =>
			previousPathPart switch
			{
				MemberAccess memberAccess => !memberAccess.IsValueType,
				IndexAccess indexAccess => !indexAccess.IsValueType,
				ConditionalAccess { Part: var inner } => PreviousPartIsReferenceType(inner),
				_ => false,
			};
	}
}