Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ bld/

# Visual Studio 2017 auto generated files
Generated\ Files/
Generated/

# MSTest test Results
[Tt]est[Rr]esult*/
Expand Down
7 changes: 7 additions & 0 deletions Microsoft.Maui-vscode.sln
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITest.Analyzers", "src\Tes
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Maui.Controls.Sample.Embedding", "src\Controls\samples\Controls.Sample.Embedding\Maui.Controls.Sample.Embedding.csproj", "{4ADCBA87-30DB-44F5-85E9-94A4F4132FD9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGen.UnitTests", "src\Controls\tests\SourceGen.UnitTests\SourceGen.UnitTests.csproj", "{A426B2FC-F012-436B-BDD9-BEC0025DB96B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -539,6 +541,10 @@ Global
{4ADCBA87-30DB-44F5-85E9-94A4F4132FD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4ADCBA87-30DB-44F5-85E9-94A4F4132FD9}.Release|Any CPU.Build.0 = Release|Any CPU
{4ADCBA87-30DB-44F5-85E9-94A4F4132FD9}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A426B2FC-F012-436B-BDD9-BEC0025DB96B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A426B2FC-F012-436B-BDD9-BEC0025DB96B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A426B2FC-F012-436B-BDD9-BEC0025DB96B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A426B2FC-F012-436B-BDD9-BEC0025DB96B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -636,6 +642,7 @@ Global
{0048EA9A-D751-4576-A2BB-2A37BFB385A5} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
{DA001142-4777-4EDE-97D5-B1AC08162F99} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C}
{4ADCBA87-30DB-44F5-85E9-94A4F4132FD9} = {E1082E26-D700-4127-9329-66D673FD2D55}
{A426B2FC-F012-436B-BDD9-BEC0025DB96B} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
</Docs>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public XmlnsDefinitionAttribute (string xmlNamespace, string clrNamespace);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string xmlNamespace, string clrNamespace) cil managed" />
<MemberSignature Language="C#" Value="public XmlnsDefinitionAttribute (string xmlNamespace, string target);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(string xmlNamespace, string target) cil managed" />
<MemberSignature Language="DocId" Value="M:Microsoft.Maui.Controls.XmlnsDefinitionAttribute.#ctor(System.String,System.String)" />
<MemberSignature Language="F#" Value="new Microsoft.Maui.Controls.XmlnsDefinitionAttribute : string * string -&gt; Microsoft.Maui.Controls.XmlnsDefinitionAttribute" Usage="new Microsoft.Maui.Controls.XmlnsDefinitionAttribute (xmlNamespace, clrNamespace)" />
<MemberType>Constructor</MemberType>
Expand All @@ -35,11 +35,11 @@
</AssemblyInfo>
<Parameters>
<Parameter Name="xmlNamespace" Type="System.String" />
<Parameter Name="clrNamespace" Type="System.String" />
<Parameter Name="target" Type="System.String" />
</Parameters>
<Docs>
<param name="xmlNamespace">To be added.</param>
<param name="clrNamespace">To be added.</param>
<param name="target">To be added.</param>
</Docs>
</Member>
<Member MemberName="AssemblyName">
Expand Down Expand Up @@ -74,6 +74,22 @@
<Docs>
</Docs>
</Member>
<Member MemberName="Target">
<MemberSignature Language="C#" Value="public string Target { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance string Target" />
<MemberSignature Language="DocId" Value="P:Microsoft.Maui.Controls.XmlnsDefinitionAttribute.Target" />
<MemberSignature Language="F#" Value="member this.ClrNamespace : string" Usage="Microsoft.Maui.Controls.XmlnsDefinitionAttribute.Target" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Microsoft.Maui.Controls.Core</AssemblyName>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
</Docs>
</Member>
<Member MemberName="XmlNamespace">
<MemberSignature Language="C#" Value="public string XmlNamespace { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance string XmlNamespace" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ public IEnumerable<Instruction> ConvertFromString(string value, ILContext contex
yield return Instruction.Create(OpCodes.Ldsfld, bpRef);
}

static bool IsOfAnyType(XmlType xmlType, params string[] types)
{
if (types == null || types.Length == 0)
return false;
if (xmlType == null)
return false;
if (xmlType.NamespaceUri != XamlParser.MauiUri && xmlType.NamespaceUri != XamlParser.MauiGlobalUri)
return false;
if (types.Contains(xmlType.Name))
return true;
return false;
}
public FieldReference GetBindablePropertyFieldReference(string value, ILContext context, ModuleDefinition module, BaseNode node)
{
FieldReference bpRef = null;
Expand All @@ -34,24 +46,18 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
if (parts.Length == 1)
{
var parent = node.Parent?.Parent as IElementNode ?? (node.Parent?.Parent as IListNode)?.Parent as IElementNode;
if ((node.Parent as ElementNode)?.XmlType.NamespaceUri == XamlParser.MauiUri
&& ((node.Parent as ElementNode)?.XmlType.Name == nameof(Setter)
|| (node.Parent as ElementNode)?.XmlType.Name == nameof(PropertyCondition)))
if (IsOfAnyType((node.Parent as ElementNode)?.XmlType, nameof(Setter), nameof(PropertyCondition)))
{
if (parent.XmlType.NamespaceUri == XamlParser.MauiUri &&
(parent.XmlType.Name == nameof(Trigger)
|| parent.XmlType.Name == nameof(DataTrigger)
|| parent.XmlType.Name == nameof(MultiTrigger)
|| parent.XmlType.Name == nameof(Style)))
if (IsOfAnyType(parent.XmlType, nameof(Trigger), nameof(DataTrigger), nameof(MultiTrigger), nameof(Style)))
{
typeName = GetTargetTypeName(parent);
}
else if (parent.XmlType.NamespaceUri == XamlParser.MauiUri && parent.XmlType.Name == nameof(VisualState))
else if (IsOfAnyType(parent.XmlType, nameof(VisualState)))
{
typeName = FindTypeNameForVisualState(parent, node);
}
}
else if ((node.Parent as ElementNode)?.XmlType.NamespaceUri == XamlParser.MauiUri && (node.Parent as ElementNode)?.XmlType.Name == nameof(Trigger))
else if (IsOfAnyType((node.Parent as ElementNode)?.XmlType, nameof(Trigger)))
{
typeName = GetTargetTypeName(node.Parent);
}
Expand Down Expand Up @@ -86,19 +92,19 @@ static string FindTypeNameForVisualState(IElementNode parent, IXmlLineInfo lineI
//1. parent is VisualState, don't check that

//2. check that the VS is in a VSG
if (!(parent.Parent is IElementNode target) || target.XmlType.NamespaceUri != XamlParser.MauiUri || target.XmlType.Name != nameof(VisualStateGroup))
// if (!(parent.Parent is IElementNode target) || target.XmlType.NamespaceUri != XamlParser.MauiUri || target.XmlType.Name != nameof(VisualStateGroup))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if (!(parent.Parent is IElementNode target) || target.XmlType.NamespaceUri != XamlParser.MauiUri || target.XmlType.Name != nameof(VisualStateGroup))

if (!(parent.Parent is IElementNode target) || !IsOfAnyType(target.XmlType, nameof(VisualStateGroup)))
throw new XamlParseException($"Expected {nameof(VisualStateGroup)} but found {parent.Parent}", lineInfo);

//3. if the VSG is in a VSGL, skip that as it could be implicit
if (target.Parent is ListNode
|| ((target.Parent as IElementNode)?.XmlType.NamespaceUri == XamlParser.MauiUri
&& (target.Parent as IElementNode)?.XmlType.Name == nameof(VisualStateGroupList)))
|| IsOfAnyType((target.Parent as IElementNode)?.XmlType, nameof(VisualStateGroupList)))
target = target.Parent.Parent as IElementNode;
else
target = target.Parent as IElementNode;

//4. target is now a Setter in a Style, or a VE
if (target.XmlType.NamespaceUri == XamlParser.MauiUri && target.XmlType.Name == nameof(Setter))
if (IsOfAnyType(target.XmlType, nameof(Setter)))
return ((target?.Parent as IElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
else
return target.XmlType.Name;
Expand Down
3 changes: 2 additions & 1 deletion src/Controls/src/Build.Tasks/ModuleDefinitionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ public static TypeDefinition GetTypeDefinition(this ModuleDefinition module, Xam
{
return cache.GetOrAddTypeDefinition(module, type, x =>
{
var asm = module.Assembly.Name.Name == type.assemblyName
var assemblyName = module.Assembly.Name;
var asm = (assemblyName.Name == type.assemblyName || assemblyName.FullName == type.assemblyName)
? module.Assembly
: module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(type.assemblyName));
var typeDef = asm.MainModule.GetType($"{type.clrNamespace}.{type.typeName}");
Expand Down
2 changes: 1 addition & 1 deletion src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ static bool TryCompileBindingPath(ElementNode node, ILContext context, VariableD
}

if (n.XmlType.Name == nameof(Microsoft.Maui.Controls.DataTemplate)
&& n.XmlType.NamespaceUri == XamlParser.MauiUri)
&& (n.XmlType.NamespaceUri == XamlParser.MauiUri) || n.XmlType.NamespaceUri == XamlParser.MauiGlobalUri)
{
xDataTypeIsInOuterScope = true;
}
Expand Down
56 changes: 30 additions & 26 deletions src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,14 @@ namespace Microsoft.Maui.Controls.Build.Tasks
{
class TypeRefComparer : IEqualityComparer<TypeReference>
{
static string GetAssemblyName(TypeReference typeRef)
{
if (typeRef.Scope is ModuleDefinition md)
return md.Assembly.Name.Name;
if (typeRef.Scope is AssemblyNameReference anr)
return anr.Name;
throw new ArgumentOutOfRangeException(nameof(typeRef));
}

public bool Equals(TypeReference x, TypeReference y)
{
if (x == null)
return y == null;
if (y == null)
return x == null;
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;

//strip the leading `&` as byref typered fullnames have a `&`
//strip the leading `&` as byref typeref fullnames have a `&`
var xname = x.FullName.EndsWith("&", StringComparison.InvariantCulture) ? x.FullName.Substring(0, x.FullName.Length - 1) : x.FullName;
var yname = y.FullName.EndsWith("&", StringComparison.InvariantCulture) ? y.FullName.Substring(0, y.FullName.Length - 1) : y.FullName;
if (xname != yname)
Expand All @@ -34,27 +25,40 @@ public bool Equals(TypeReference x, TypeReference y)
var yasm = GetAssemblyName(y);

//standard types comes from either mscorlib. System.Runtime or netstandard. Assume they are equivalent
if ((xasm.StartsWith("System.Runtime", StringComparison.Ordinal)
|| xasm.StartsWith("System", StringComparison.Ordinal)
|| xasm.StartsWith("mscorlib", StringComparison.Ordinal)
|| xasm.StartsWith("netstandard", StringComparison.Ordinal)
|| xasm.StartsWith("System.Xml", StringComparison.Ordinal))
&& (yasm.StartsWith("System.Runtime", StringComparison.Ordinal)
|| yasm.StartsWith("System", StringComparison.Ordinal)
|| yasm.StartsWith("mscorlib", StringComparison.Ordinal)
|| yasm.StartsWith("netstandard", StringComparison.Ordinal)
|| yasm.StartsWith("System.Xml", StringComparison.Ordinal)))
if (IsSystemAssembly(xasm) && IsSystemAssembly(yasm))
return true;
return xasm == yasm;
}

public int GetHashCode(TypeReference obj)
{
return $"{GetAssemblyName(obj)}//{obj.FullName}".GetHashCode();
var assemblyName = GetAssemblyName(obj);
if (IsSystemAssembly(assemblyName))
return obj.FullName.GetHashCode();
return assemblyName.GetHashCode() ^ obj.FullName.GetHashCode();
}

static string GetAssemblyName(TypeReference typeRef)
{
if (typeRef.Scope is ModuleDefinition md)
return md.Assembly.Name.Name;
if (typeRef.Scope is AssemblyNameReference anr)
return anr.Name;
throw new ArgumentOutOfRangeException(nameof(typeRef));
}

bool IsSystemAssembly(string assemblyName)
{
return assemblyName.StartsWith("System", StringComparison.Ordinal)
|| assemblyName.StartsWith("mscorlib", StringComparison.Ordinal)
|| assemblyName.StartsWith("netstandard", StringComparison.Ordinal)
|| assemblyName.StartsWith("System.Runtime", StringComparison.Ordinal)
|| assemblyName.StartsWith("System.Xml", StringComparison.Ordinal)
|| assemblyName.StartsWith("System.Private.CoreLib", StringComparison.Ordinal);
}

static TypeRefComparer s_default;
public static TypeRefComparer Default => s_default ?? (s_default = new TypeRefComparer());
public static TypeRefComparer Default => s_default ??= new TypeRefComparer();
}

static class TypeReferenceExtensions
Expand Down
2 changes: 1 addition & 1 deletion src/Controls/src/Build.Tasks/XamlCTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ public override bool Execute(out IList<Exception> thrownExceptions)
ILRootNode rootnode = null;
try
{
rootnode = ParseXaml(resource.GetResourceStream(), typeDef);
rootnode = ParseXaml(resource.GetResourceStream(), module, typeDef);
if (rootnode == null)
{
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed.");
Expand Down
35 changes: 32 additions & 3 deletions src/Controls/src/Build.Tasks/XamlTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
Expand Down Expand Up @@ -40,9 +41,23 @@ public bool Execute()

public abstract bool Execute(out IList<Exception> thrownExceptions);

internal static ILRootNode ParseXaml(Stream stream, TypeReference typeReference)
internal static ILRootNode ParseXaml(Stream stream, ModuleDefinition module, TypeReference typeReference)
{
using (var reader = XmlReader.Create(stream))
var allowImplicitXmlns = module.Assembly.CustomAttributes.Any(a =>
a.AttributeType.FullName == typeof(Microsoft.Maui.Controls.Xaml.Internals.AllowImplicitXmlnsDeclarationAttribute).FullName
&& (a.ConstructorArguments.Count == 0 || a.ConstructorArguments[0].Value is bool b && b));

var nsmgr = new XmlNamespaceManager(new NameTable());
if (allowImplicitXmlns)
{
nsmgr.AddNamespace("", XamlParser.DefaultImplicitUri);
foreach (var xmlnsPrefix in XmlTypeExtensions.GetXmlnsPrefixAttributes(module))
nsmgr.AddNamespace(xmlnsPrefix.Prefix, xmlnsPrefix.XmlNamespace);
}

using (var reader = XmlReader.Create(stream,
new XmlReaderSettings { ConformanceLevel = allowImplicitXmlns ? ConformanceLevel.Fragment : ConformanceLevel.Document },
new XmlParserContext(nsmgr.NameTable, nsmgr, null, XmlSpace.None)))
{
while (reader.Read())
{
Expand Down Expand Up @@ -73,8 +88,22 @@ public static bool IsXaml(this EmbeddedResource resource, XamlCache cache, Modul
if (!resource.Name.EndsWith(".xaml", StringComparison.InvariantCulture))
return false;

var allowImplicitXmlns = module.Assembly.CustomAttributes.Any(a =>
a.AttributeType.FullName == typeof(Microsoft.Maui.Controls.Xaml.Internals.AllowImplicitXmlnsDeclarationAttribute).FullName
&& (a.ConstructorArguments.Count == 0 || a.ConstructorArguments[0].Value is bool b && b));

var nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("__f__", XamlParser.MauiUri);
if (allowImplicitXmlns)
{
nsmgr.AddNamespace("", XamlParser.DefaultImplicitUri);
foreach (var xmlnsPrefix in XmlTypeExtensions.GetXmlnsPrefixAttributes(module))
nsmgr.AddNamespace(xmlnsPrefix.Prefix, xmlnsPrefix.XmlNamespace);
}
using (var resourceStream = resource.GetResourceStream())
using (var reader = XmlReader.Create(resourceStream))
using (var reader = XmlReader.Create(resourceStream,
new XmlReaderSettings { ConformanceLevel = allowImplicitXmlns ? ConformanceLevel.Fragment : ConformanceLevel.Document },
new XmlParserContext(nsmgr.NameTable, nsmgr, null, XmlSpace.None)))
{
// Read to the first Element
while (reader.Read() && reader.NodeType != XmlNodeType.Element)
Expand Down
Loading
Loading