diff --git a/src/Controls/src/Xaml/XamlServiceProvider.cs b/src/Controls/src/Xaml/XamlServiceProvider.cs index 1c2b24f96dc4..dec1a464528d 100644 --- a/src/Controls/src/Xaml/XamlServiceProvider.cs +++ b/src/Controls/src/Xaml/XamlServiceProvider.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Reflection; using System.Xml; using Microsoft.Maui.Controls.Internals; @@ -29,7 +31,7 @@ internal XamlServiceProvider(INode node, HydrationContext context) IValueConverterProvider = new ValueConverterProvider(); if (node is IElementNode elementNode) - Add(typeof(IXamlDataTypeProvider), new XamlDataTypeProvider(elementNode)); + Add(typeof(IXamlDataTypeProvider), new XamlDataTypeProvider(elementNode, context)); } public XamlServiceProvider() => IValueConverterProvider = new ValueConverterProvider(); @@ -268,8 +270,15 @@ public string LookupNamespace(string prefix) class XamlDataTypeProvider : IXamlDataTypeProvider { - public XamlDataTypeProvider(IElementNode node) + [RequiresUnreferencedCode("XamlDataTypeProvider is not trim and AOT-compatible.")] +#if !NETSTANDARD + [RequiresDynamicCode("XamlDataTypeProvider is not trim and AOT-compatible.")] +#endif + public XamlDataTypeProvider(IElementNode node, HydrationContext context) { + Context = context; + + static IElementNode GetParent(IElementNode node) { return node switch @@ -289,6 +298,21 @@ static bool IsBindingContextBinding(IElementNode node) return false; } + static bool IsBindingBaseProperty(IElementNode node, HydrationContext context) + { + if ( ApplyPropertiesVisitor.TryGetPropertyName(node, node.Parent, out XmlName name) + && node.Parent is IElementNode parent + && XamlParser.GetElementType(parent.XmlType, + new XmlLineInfo(((IXmlLineInfo)node).LineNumber, ((IXmlLineInfo)node).LinePosition), + context.RootElement.GetType().Assembly, out var xpe) is Type parentType + && parentType.GetRuntimeProperties().FirstOrDefault(p => p.Name == name.LocalName) is PropertyInfo propertyInfo + && propertyInfo.PropertyType == typeof(BindingBase)) + { + return true; + } + return false; + } + INode dataTypeNode = null; IElementNode n = node as IElementNode; @@ -305,17 +329,21 @@ static bool IsBindingContextBinding(IElementNode node) while (n != null) { + if (n != skipNode && n.Properties.TryGetValue(XmlName.xDataType, out dataTypeNode)) { break; } - + if (IsBindingBaseProperty(n, context)) + { + break; + } n = GetParent(n); } if (dataTypeNode is ValueNode valueNode) BindingDataType = valueNode.Value as string; - } public string BindingDataType { get; } + public HydrationContext Context { get; } } -} \ No newline at end of file +} diff --git a/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj b/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj index 4ded530f749a..010872642b99 100644 --- a/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj +++ b/src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj @@ -6,7 +6,7 @@ Microsoft.Maui.Controls.Xaml.UnitTests 4 $(NoWarn);0672;0219;0414;CS0436;CS0618 - $(WarningsNotAsErrors);XC0618;XC0022,XC0023 + $(WarningsNotAsErrors);XC0618;XC0022;XC0023 false true diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/BuildWarningsUtilities.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/BuildWarningsUtilities.cs index ab8111cf9770..a430865f00af 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/BuildWarningsUtilities.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/Utilities/BuildWarningsUtilities.cs @@ -454,6 +454,30 @@ public static void AssertWarnings(this List actualWarnings, Lis }, } }, + new WarningsPerFile + { + File = "src/Controls/src/Xaml/XamlServiceProvider.cs", + WarningsPerCode = new List + { + new WarningsPerCode + { + Code = "IL2026", + Messages = new List + { + "Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(INode,HydrationContext): Using member 'Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(IElementNode,HydrationContext)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. XamlDataTypeProvider is not trim and AOT-compatible.", + } + }, + new WarningsPerCode + { + Code = "IL3050", + Messages = new List + { + "Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(INode,HydrationContext): Using member 'Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(IElementNode,HydrationContext)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. XamlDataTypeProvider is not trim and AOT-compatible.", + } + }, + + } + }, }; #region Utility methods for generating the list of expected warnings