Repository: dotnet/maui
File: src/Controls/src/SourceGen/ITypeSymbolExtensions.cs (C#)

Code before:
		string propertyName,
		SourceGenContext? context,
		out IPropertySymbol? property,
		out ITypeSymbol? propertyType)
	{
		return TryGetProperty(symbol, propertyName, context, out property, out propertyType, out _);
	}

	/// <summary>
	/// Tries to get a property by name, and if not found, checks if it could be inferred from a RelayCommand method
	/// or an ObservableProperty attribute. Returns the property type if found or inferred.
	/// </summary>
	/// <param name="symbol">The type to search</param>
	/// <param name="propertyName">The name of the property to find</param>
	/// <param name="context">The source generation context</param>
	/// <param name="property">The found property symbol (null if inferred from RelayCommand/ObservableProperty)</param>
	/// <param name="propertyType">The property type (either from the property or inferred)</param>
	/// <param name="isObservableProperty">True if the property was inferred from an ObservableProperty attribute (which is always writable)</param>
	/// <returns>True if property exists or can be inferred</returns>
	public static bool TryGetProperty(
		this ITypeSymbol symbol,
		string propertyName,
		SourceGenContext? context,
		out IPropertySymbol? property,
		out ITypeSymbol? propertyType,
		out bool isObservableProperty)
	{
		isObservableProperty = false;
		property = symbol.GetAllProperties(propertyName, context)
			.FirstOrDefault(p => p.GetMethod != null && !p.GetMethod.IsStatic);

		if (property != null)
		{
			propertyType = property.Type;
			return true;
		}

		// If property not found, check if it could be a RelayCommand-generated property
		// Call the BindingSourceGen extension method directly
		if (symbol.TryGetRelayCommandPropertyType(propertyName, context?.Compilation, out propertyType))
		{
			return true;
		}

		// If property not found, check if it could be an ObservableProperty-generated property
		// Call the BindingSourceGen extension method directly
		if (symbol.TryGetObservablePropertyType(propertyName, context?.Compilation, out propertyType))
		{
			isObservableProperty = true;
			return true;
		}

Review comment (suggestion):
I'm not super happy about `isObservableProperty` leaking out of this method. I would suggest `out bool isAssumedWritable`. Other than the variable name, let's ship it!

Code after:
		string propertyName,
		SourceGenContext? context,
		out IPropertySymbol? property,
		out ITypeSymbol? propertyType)
	{
		return TryGetProperty(symbol, propertyName, context, out property, out propertyType, out _);
	}

	/// <summary>
	/// Tries to get a property by name, and if not found, checks if it could be inferred from a RelayCommand method
	/// or an ObservableProperty attribute. Returns the property type if found or inferred.
	/// </summary>
	/// <param name="symbol">The type to search</param>
	/// <param name="propertyName">The name of the property to find</param>
	/// <param name="context">The source generation context</param>
	/// <param name="property">The found property symbol (null if inferred from RelayCommand/ObservableProperty)</param>
	/// <param name="propertyType">The property type (either from the property or inferred)</param>
	/// <param name="isAssumedWritable">True if the property was inferred from an ObservableProperty attribute (which is always writable)</param>
	/// <returns>True if property exists or can be inferred</returns>
	public static bool TryGetProperty(
		this ITypeSymbol symbol,
		string propertyName,
		SourceGenContext? context,
		out IPropertySymbol? property,
		out ITypeSymbol? propertyType,
		out bool isAssumedWritable)
	{
		isAssumedWritable = false;
		property = symbol.GetAllProperties(propertyName, context)
			.FirstOrDefault(p => p.GetMethod != null && !p.GetMethod.IsStatic);

		if (property != null)
		{
			propertyType = property.Type;
			return true;
		}

		// If property not found, check if it could be a RelayCommand-generated property
		// Call the BindingSourceGen extension method directly
		if (symbol.TryGetRelayCommandPropertyType(propertyName, context?.Compilation, out propertyType))
		{
			return true;
		}

		// If property not found, check if it could be an ObservableProperty-generated property
		// Call the BindingSourceGen extension method directly
		if (symbol.TryGetObservablePropertyType(propertyName, context?.Compilation, out propertyType))
		{
			isAssumedWritable = true;
			return true;
		}