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
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,17 @@ IEnumerable<Instruction> ProvideValue(TypeReference typeTypeRef, IReadOnlyList<I

for (var i = 0; i < n; i++)
{
var vardef = context.Variables[items[i] as IElementNode];
var node = items[i] as IElementNode;
var vardef = context.Variables[node];
var vardefref = new VariableDefinitionReference(vardef);
context.IL.Append(SetPropertiesVisitor.ProvideValue(vardefref, context, module, node as ElementNode));
if (vardef != vardefref.VariableDefinition)
{
vardef = vardefref.VariableDefinition;
context.Body.Variables.Add(vardef);
context.Variables[node] = vardef;
}

Comment thread
simonrozsival marked this conversation as resolved.
if (typeTypeRef.IsValueType)
{
yield return Instruction.Create(OpCodes.Dup);
Expand Down
60 changes: 32 additions & 28 deletions src/Controls/src/Build.Tasks/CreateObjectVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@ public void Visit(ElementNode node, INode parentNode)
var typeref = Module.ImportReference(node.XmlType.GetTypeReference(Context.Cache, Module, node));
TypeDefinition typedef = typeref.ResolveCached(Context.Cache);

if (typeref.FullName == "Microsoft.Maui.Controls.Xaml.ArrayExtension")
{
var visitor = new SetPropertiesVisitor(Context);
var children = node.Properties.Values.ToList();
children.AddRange(node.CollectionItems);
foreach (var cnode in children)
{
if (cnode is not IElementNode en)
continue;
foreach (var n in en.Properties.Values.ToList())
n.Accept(visitor, cnode);
foreach (var n in en.CollectionItems)
n.Accept(visitor, cnode);
}

var il = new ArrayExtension().ProvideValue(node, Module, Context, out typeref);
var vardef = new VariableDefinition(typeref);
Context.Variables[node] = vardef;
Context.Body.Variables.Add(vardef);

Context.IL.Append(il);
Context.IL.Emit(OpCodes.Stloc, vardef);

//clean the node as it has been fully exhausted
foreach (var prop in node.Properties)
if (!node.SkipProperties.Contains(prop.Key))
node.SkipProperties.Add(prop.Key);
node.CollectionItems.Clear();

return;
}

if (IsXaml2009LanguagePrimitive(node))
{
var vardef = new VariableDefinition(typeref);
Expand Down Expand Up @@ -216,34 +248,6 @@ public void Visit(ElementNode node, INode parentNode)
Context.IL.Emit(OpCodes.Ldloca, vardef);
Context.IL.Emit(OpCodes.Initobj, Module.ImportReference(typedef));
}

if (typeref.FullName == "Microsoft.Maui.Controls.Xaml.ArrayExtension")
{
var visitor = new SetPropertiesVisitor(Context);
foreach (var cnode in node.Properties.Values.ToList())
cnode.Accept(visitor, node);
foreach (var cnode in node.CollectionItems)
cnode.Accept(visitor, node);

markupProvider = new ArrayExtension();

var il = markupProvider.ProvideValue(node, Module, Context, out typeref);

vardef = new VariableDefinition(typeref);
Context.Variables[node] = vardef;
Context.Body.Variables.Add(vardef);

Context.IL.Append(il);
Context.IL.Emit(OpCodes.Stloc, vardef);

//clean the node as it has been fully exhausted
foreach (var prop in node.Properties)
if (!node.SkipProperties.Contains(prop.Key))
node.SkipProperties.Add(prop.Key);
node.CollectionItems.Clear();

return;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Controls/tests/Xaml.UnitTests/XArray.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:Microsoft.Maui.Controls.Xaml.UnitTests;assembly=Microsoft.Maui.Controls.Xaml.UnitTests"
x:Class="Microsoft.Maui.Controls.Xaml.UnitTests.XArray">
<x:Array Type="{x:Type sys:String}" x:Key="array">
<x:Array Type="{x:Type sys:String}" >
<x:String>Hello</x:String>
<x:String>World</x:String>
</x:Array>
Expand Down
24 changes: 21 additions & 3 deletions src/Controls/tests/Xaml.UnitTests/XArray.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using NUnit.Framework;

namespace Microsoft.Maui.Controls.Xaml.UnitTests
Expand Down Expand Up @@ -38,6 +38,24 @@ public void SupportsXArray(bool useCompiledXaml)
Assert.AreEqual("Hello", ((string[])layout.Content)[0]);
Assert.AreEqual("World", ((string[])layout.Content)[1]);
}

[Test]
public void ArrayExtensionNotPresentInGeneratedCode([Values(false)] bool useCompiledXaml)
{
MockCompiler.Compile(typeof(XArray), out var methodDef);
Assert.That(!methodDef.Body.Instructions.Any(instr => InstructionIsArrayExtensionCtor(methodDef, instr)), "This Xaml still generates a new ArrayExtension()");
}

bool InstructionIsArrayExtensionCtor(MethodDefinition methodDef, Mono.Cecil.Cil.Instruction instruction)
{
if (instruction.OpCode != OpCodes.Newobj)
return false;
if (instruction.Operand is not MethodReference methodRef)
return false;
if (!Build.Tasks.TypeRefComparer.Default.Equals(methodRef.DeclaringType, methodDef.Module.ImportReference(typeof(ArrayExtension))))
return false;
return true;
}
}
}
}