summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2017-01-25 14:47:27 +0100
committerKangho Hur <kangho.hur@samsung.com>2017-03-24 13:14:23 +0900
commitc247c695cbd8613d5603ccbada92051a9ea7dbf8 (patch)
tree61ffc2f8687576377ebe71c73d74001589b9f2af
parentacf4a77b5a71900463f1e31cad1dab5e9593451e (diff)
downloadxamarin-forms-c247c695cbd8613d5603ccbada92051a9ea7dbf8.tar.gz
xamarin-forms-c247c695cbd8613d5603ccbada92051a9ea7dbf8.tar.bz2
xamarin-forms-c247c695cbd8613d5603ccbada92051a9ea7dbf8.zip
[Xaml[C]] Do not instantiate DataTemplate Content at parsing time (#683)
* [Xaml] rename VisitChildrenFirst * [Xaml] rework SkipChildren in XamlNode * [Xaml] fix 45179 * fix
-rw-r--r--Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs17
-rw-r--r--Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs18
-rw-r--r--Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs18
-rw-r--r--Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs18
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs17
-rw-r--r--Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs22
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs13
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml14
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml.cs55
-rw-r--r--Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs28
-rw-r--r--Xamarin.Forms.Xaml/CreateValuesVisitor.cs18
-rw-r--r--Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs18
-rw-r--r--Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs18
-rw-r--r--Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs2
-rw-r--r--Xamarin.Forms.Xaml/NamescopingVisitor.cs18
-rw-r--r--Xamarin.Forms.Xaml/PruneIgnoredNodesVisitor.cs15
-rw-r--r--Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs18
-rw-r--r--Xamarin.Forms.Xaml/XamlNode.cs123
-rw-r--r--Xamarin.Forms.Xaml/XamlNodeVisitor.cs24
20 files changed, 229 insertions, 258 deletions
diff --git a/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs
index c684e512..b73926fd 100644
--- a/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs
@@ -21,20 +21,11 @@ namespace Xamarin.Forms.Build.Tasks
ModuleDefinition Module { get; }
- public bool VisitChildrenFirst
- {
- get { return true; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs b/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
index e647f6c2..ff83de7a 100644
--- a/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
@@ -24,20 +24,10 @@ namespace Xamarin.Forms.Build.Tasks
ILContext Context { get; }
- public bool VisitChildrenFirst
- {
- get { return true; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return false; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => false;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => true;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs b/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs
index 1839cf7b..9a5b7444 100644
--- a/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetFieldVisitor.cs
@@ -13,20 +13,10 @@ namespace Xamarin.Forms.Build.Tasks
public ILContext Context { get; }
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs
index d810bd80..1c776ab8 100644
--- a/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs
@@ -16,20 +16,10 @@ namespace Xamarin.Forms.Build.Tasks
ILContext Context { get; }
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
index c93c14f2..2c4ddbd6 100644
--- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
@@ -37,8 +37,9 @@ namespace Xamarin.Forms.Build.Tasks
public ILContext Context { get; }
public bool StopOnResourceDictionary { get; }
- public bool VisitChildrenFirst { get; } = true;
- public bool StopOnDataTemplate { get; } = true;
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => true;
+ public bool VisitNodeOnDataTemplate => true;
ModuleDefinition Module { get; }
@@ -88,6 +89,11 @@ namespace Xamarin.Forms.Build.Tasks
if ((propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) && skips.Contains(propertyName))
return;
+ if (propertyName == XmlName._CreateContent) {
+ SetDataTemplate((IElementNode)parentNode, node, Context, node);
+ return;
+ }
+
//if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
var vardef = Context.Variables[node];
var vardefref = new VariableDefinitionReference(vardef);
@@ -114,11 +120,8 @@ namespace Xamarin.Forms.Build.Tasks
return;
if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
return;
-
- if (propertyName == XmlName._CreateContent)
- SetDataTemplate((IElementNode)parentNode, node, Context, node);
- else
- Context.IL.Append(SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node));
+
+ Context.IL.Append(SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node));
}
else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode)
{
diff --git a/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs
index f046efcb..c5be1fbd 100644
--- a/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetResourcesVisitor.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections;
-using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -20,26 +19,15 @@ namespace Xamarin.Forms.Build.Tasks
ModuleDefinition Module { get; }
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
XmlName propertyName;
- if (!SetPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
- {
+ if (!SetPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName)) {
if (!IsCollectionItem(node, parentNode))
return;
string contentProperty;
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs
index 03ebaaf9..1120a033 100644
--- a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27863.xaml.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Xamarin.Forms;
using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
@@ -22,6 +23,18 @@ namespace Xamarin.Forms.Xaml.UnitTests
[TestFixture]
class Tests
{
+ [SetUp]
+ public void Setup()
+ {
+ Device.PlatformServices = new MockPlatformServices();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Device.PlatformServices = null;
+ }
+
[TestCase(true)]
[TestCase(false)]
public void DataTemplateInResourceDictionaries (bool useCompiledXaml)
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs
index 2482e9f0..507073d7 100644
--- a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz27968.xaml.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Xamarin.Forms;
using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
@@ -26,6 +27,18 @@ namespace Xamarin.Forms.Xaml.UnitTests
[TestFixture]
class Tests
{
+ [SetUp]
+ public void Setup()
+ {
+ Device.PlatformServices = new MockPlatformServices();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Device.PlatformServices = null;
+ }
+
[TestCase(true)]
[TestCase(false)]
public void BaseClassIdentifiersAreValidForResources (bool useCompiledXaml)
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml
new file mode 100644
index 00000000..a89aa295
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz45179">
+ <ContentPage.Resources>
+ <ResourceDictionary>
+ <DataTemplate x:Key="dt0">
+ <local:Bz45179_0/>
+ </DataTemplate>
+ </ResourceDictionary>
+ </ContentPage.Resources>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml.cs
new file mode 100644
index 00000000..1dbdb44d
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz45179.xaml.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public class Bz45179_0 : ContentView {
+ public static int creator_count;
+ public Bz45179_0()
+ {
+ creator_count++;
+ }
+
+ }
+ public partial class Bz45179 : ContentPage
+ {
+ public Bz45179()
+ {
+ InitializeComponent();
+ }
+
+ public Bz45179(bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [SetUp]
+ public void Setup()
+ {
+ Device.PlatformServices = new MockPlatformServices();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ Device.PlatformServices = null;
+ }
+
+ [TestCase(true)]
+ [TestCase(false)]
+ public void DTDoNotInstantiateTheirContent(bool useCompiledXaml)
+ {
+ Bz45179_0.creator_count = 0;
+ Assume.That(Bz45179_0.creator_count, Is.EqualTo(0));
+ var page = new Bz45179(useCompiledXaml);
+ Assert.That(Bz45179_0.creator_count, Is.EqualTo(0));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
index 154ba023..879ea3b0 100644
--- a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
+++ b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs
@@ -35,15 +35,10 @@ namespace Xamarin.Forms.Xaml
HydratationContext Context { get; }
- public bool VisitChildrenFirst {
- get { return true; }
- }
-
- public bool StopOnDataTemplate {
- get { return true; }
- }
-
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => true;
public bool StopOnResourceDictionary { get; }
+ public bool VisitNodeOnDataTemplate => true;
public void Visit(ValueNode node, INode parentNode)
{
@@ -81,6 +76,15 @@ namespace Xamarin.Forms.Xaml
public void Visit(ElementNode node, INode parentNode)
{
+ var propertyName = XmlName.Empty;
+ if (TryGetPropertyName(node, parentNode, out propertyName) && propertyName == XmlName._CreateContent){
+ var s0 = Values[parentNode];
+ if (s0 is ElementTemplate) {
+ SetTemplate(s0 as ElementTemplate, node);
+ return;
+ }
+ }
+
var value = Values [node];
var parentElement = parentNode as IElementNode;
var markupExtension = value as IMarkupExtension;
@@ -96,7 +100,7 @@ namespace Xamarin.Forms.Xaml
value = valueProvider.ProvideValue(serviceProvider);
}
- XmlName propertyName = XmlName.Empty;
+ propertyName = XmlName.Empty;
//Simplify ListNodes with single elements
var pList = parentNode as ListNode;
@@ -113,11 +117,7 @@ namespace Xamarin.Forms.Xaml
return;
var source = Values [parentNode];
-
- if (propertyName == XmlName._CreateContent && source is ElementTemplate)
- SetTemplate(source as ElementTemplate, node);
- else
- SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
+ SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
} else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) {
// Collection element, implicit content, or implicit collection element.
string contentProperty;
diff --git a/Xamarin.Forms.Xaml/CreateValuesVisitor.cs b/Xamarin.Forms.Xaml/CreateValuesVisitor.cs
index 817b62c8..b4f9213a 100644
--- a/Xamarin.Forms.Xaml/CreateValuesVisitor.cs
+++ b/Xamarin.Forms.Xaml/CreateValuesVisitor.cs
@@ -23,20 +23,10 @@ namespace Xamarin.Forms.Xaml
HydratationContext Context { get; }
- public bool VisitChildrenFirst
- {
- get { return true; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs b/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs
index 81893506..282b7da4 100644
--- a/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs
+++ b/Xamarin.Forms.Xaml/ExpandMarkupsVisitor.cs
@@ -28,20 +28,10 @@ namespace Xamarin.Forms.Xaml
HydratationContext Context { get; }
- public bool VisitChildrenFirst
- {
- get { return true; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return false; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
+ public bool StopOnDataTemplate => false;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => true;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs
index a3f12109..509d54e8 100644
--- a/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs
+++ b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs
@@ -20,20 +20,10 @@ namespace Xamarin.Forms.Xaml
get { return Context.Values; }
}
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs
index 703fc206..34f1c569 100644
--- a/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs
+++ b/Xamarin.Forms.Xaml/MarkupExtensions/StaticResourceExtension.cs
@@ -34,7 +34,7 @@ namespace Xamarin.Forms.Xaml
}
if (resource == null && (Application.Current == null || Application.Current.Resources == null ||
!Application.Current.Resources.TryGetMergedValue(Key, out resource)))
- throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
+ throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
var bp = valueProvider.TargetProperty as BindableProperty;
var pi = valueProvider.TargetProperty as PropertyInfo;
diff --git a/Xamarin.Forms.Xaml/NamescopingVisitor.cs b/Xamarin.Forms.Xaml/NamescopingVisitor.cs
index 0651d045..ec9b9851 100644
--- a/Xamarin.Forms.Xaml/NamescopingVisitor.cs
+++ b/Xamarin.Forms.Xaml/NamescopingVisitor.cs
@@ -14,20 +14,10 @@ namespace Xamarin.Forms.Xaml
Dictionary<INode, object> Values { get; set; }
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return false; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => false;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => true;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/PruneIgnoredNodesVisitor.cs b/Xamarin.Forms.Xaml/PruneIgnoredNodesVisitor.cs
index 95ddb20f..92badecd 100644
--- a/Xamarin.Forms.Xaml/PruneIgnoredNodesVisitor.cs
+++ b/Xamarin.Forms.Xaml/PruneIgnoredNodesVisitor.cs
@@ -5,17 +5,10 @@ namespace Xamarin.Forms.Xaml
{
class PruneIgnoredNodesVisitor : IXamlNodeVisitor
{
- public bool StopOnDataTemplate {
- get { return false; }
- }
-
- public bool StopOnResourceDictionary {
- get { return false; }
- }
-
- public bool VisitChildrenFirst {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => false;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => true;
public void Visit(ElementNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs b/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs
index a7da3b98..5ee3bc3e 100644
--- a/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs
+++ b/Xamarin.Forms.Xaml/RegisterXNamesVisitor.cs
@@ -12,20 +12,10 @@ namespace Xamarin.Forms.Xaml
Dictionary<INode, object> Values { get; }
- public bool VisitChildrenFirst
- {
- get { return false; }
- }
-
- public bool StopOnDataTemplate
- {
- get { return true; }
- }
-
- public bool StopOnResourceDictionary
- {
- get { return false; }
- }
+ public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
+ public bool StopOnDataTemplate => true;
+ public bool StopOnResourceDictionary => false;
+ public bool VisitNodeOnDataTemplate => false;
public void Visit(ValueNode node, INode parentNode)
{
diff --git a/Xamarin.Forms.Xaml/XamlNode.cs b/Xamarin.Forms.Xaml/XamlNode.cs
index 752f3845..eccf2075 100644
--- a/Xamarin.Forms.Xaml/XamlNode.cs
+++ b/Xamarin.Forms.Xaml/XamlNode.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -7,36 +6,30 @@ using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Xaml
{
- internal interface INode
+ interface INode
{
List<string> IgnorablePrefixes { get; set; }
-
IXmlNamespaceResolver NamespaceResolver { get; }
-
INode Parent { get; set; }
void Accept(IXamlNodeVisitor visitor, INode parentNode);
INode Clone();
}
- internal interface IValueNode : INode
+ interface IValueNode : INode
{
}
- internal interface IElementNode : INode, IListNode
+ interface IElementNode : INode, IListNode
{
Dictionary<XmlName, INode> Properties { get; }
-
List<XmlName> SkipProperties { get; }
-
INameScope Namescope { get; }
-
XmlType XmlType { get; }
-
string NamespaceURI { get; }
}
- internal interface IListNode : INode
+ interface IListNode : INode
{
List<INode> CollectionItems { get; }
}
@@ -56,7 +49,7 @@ namespace Xamarin.Forms.Xaml
public IList<XmlType> TypeArguments { get; }
}
- internal abstract class BaseNode : IXmlLineInfo, INode
+ abstract class BaseNode : IXmlLineInfo, INode
{
protected BaseNode(IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
{
@@ -66,27 +59,19 @@ namespace Xamarin.Forms.Xaml
}
public IXmlNamespaceResolver NamespaceResolver { get; }
-
- public abstract void Accept(IXamlNodeVisitor visitor, INode parentNode);
-
public INode Parent { get; set; }
-
public List<string> IgnorablePrefixes { get; set; }
-
- public bool HasLineInfo()
- {
- return LineNumber >= 0 && LinePosition >= 0;
- }
-
public int LineNumber { get; set; }
-
public int LinePosition { get; set; }
+ public bool HasLineInfo() => LineNumber >= 0 && LinePosition >= 0;
+
+ public abstract void Accept(IXamlNodeVisitor visitor, INode parentNode);
public abstract INode Clone();
}
[DebuggerDisplay("{Value}")]
- internal class ValueNode : BaseNode, IValueNode
+ class ValueNode : BaseNode, IValueNode
{
public ValueNode(object value, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
: base(namespaceResolver, linenumber, lineposition)
@@ -101,19 +86,15 @@ namespace Xamarin.Forms.Xaml
visitor.Visit(this, parentNode);
}
- public override INode Clone()
- {
- return new ValueNode(Value, NamespaceResolver, LineNumber, LinePosition) {
- IgnorablePrefixes = IgnorablePrefixes
- };
- }
+ public override INode Clone() => new ValueNode(Value, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
}
[DebuggerDisplay("{MarkupString}")]
- internal class MarkupNode : BaseNode, IValueNode
+ class MarkupNode : BaseNode, IValueNode
{
- public MarkupNode(string markupString, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
- int lineposition = -1)
+ public MarkupNode(string markupString, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
: base(namespaceResolver, linenumber, lineposition)
{
MarkupString = markupString;
@@ -126,15 +107,13 @@ namespace Xamarin.Forms.Xaml
visitor.Visit(this, parentNode);
}
- public override INode Clone()
- {
- return new MarkupNode(MarkupString, NamespaceResolver, LineNumber, LinePosition) {
- IgnorablePrefixes = IgnorablePrefixes
- };
- }
+ public override INode Clone() => new MarkupNode(MarkupString, NamespaceResolver, LineNumber, LinePosition) {
+ IgnorablePrefixes = IgnorablePrefixes
+ };
}
- internal class ElementNode : BaseNode, IValueNode, IElementNode
+ [DebuggerDisplay("{XmlType.Name}")]
+ class ElementNode : BaseNode, IValueNode, IElementNode
{
public ElementNode(XmlType type, string namespaceURI, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
int lineposition = -1)
@@ -148,48 +127,48 @@ namespace Xamarin.Forms.Xaml
}
public Dictionary<XmlName, INode> Properties { get; }
-
public List<XmlName> SkipProperties { get; }
-
public List<INode> CollectionItems { get; }
-
public XmlType XmlType { get; }
-
public string NamespaceURI { get; }
-
public INameScope Namescope { get; set; }
public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
{
- if (!visitor.VisitChildrenFirst)
+ if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
visitor.Visit(this, parentNode);
- if ((!visitor.StopOnDataTemplate || !IsDataTemplate(this, parentNode)) &&
- (!visitor.StopOnResourceDictionary || !IsResourceDictionary(this, parentNode)))
- {
+
+ if (!SkipChildren(visitor, parentNode)) {
foreach (var node in Properties.Values.ToList())
node.Accept(visitor, this);
foreach (var node in CollectionItems)
node.Accept(visitor, this);
}
- if (visitor.VisitChildrenFirst)
+
+ if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
visitor.Visit(this, parentNode);
+
}
- internal static bool IsDataTemplate(INode node, INode parentNode)
+ bool IsDataTemplate(INode parentNode)
{
var parentElement = parentNode as IElementNode;
INode createContent;
- if (parentElement != null && parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
- createContent == node)
+ if (parentElement != null &&
+ parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
+ createContent == this)
return true;
return false;
}
- internal static bool IsResourceDictionary(INode node, INode parentNode)
- {
- var enode = node as ElementNode;
- return enode.XmlType.Name == "ResourceDictionary";
- }
+ bool IsResourceDictionary() => XmlType.Name == "ResourceDictionary";
+
+ protected bool SkipChildren(IXamlNodeVisitor visitor, INode parentNode) =>
+ (visitor.StopOnDataTemplate && IsDataTemplate(parentNode)) ||
+ (visitor.StopOnResourceDictionary && IsResourceDictionary());
+
+ protected bool SkipVisitNode(IXamlNodeVisitor visitor, INode parentNode) =>
+ !visitor.VisitNodeOnDataTemplate && IsDataTemplate(parentNode);
public override INode Clone()
{
@@ -206,7 +185,7 @@ namespace Xamarin.Forms.Xaml
}
}
- internal abstract class RootNode : ElementNode
+ abstract class RootNode : ElementNode
{
protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver) : base(xmlType, xmlType.NamespaceUri, nsResolver)
{
@@ -214,40 +193,39 @@ namespace Xamarin.Forms.Xaml
public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
{
- if (!visitor.VisitChildrenFirst)
+ if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
visitor.Visit(this, parentNode);
- if ((!visitor.StopOnDataTemplate || !IsDataTemplate(this, parentNode)) &&
- (!visitor.StopOnResourceDictionary || !IsResourceDictionary(this, parentNode)))
- {
+
+ if (!SkipChildren(visitor, parentNode)) {
foreach (var node in Properties.Values.ToList())
node.Accept(visitor, this);
foreach (var node in CollectionItems)
node.Accept(visitor, this);
}
- if (visitor.VisitChildrenFirst)
+
+ if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
visitor.Visit(this, parentNode);
}
}
- internal class ListNode : BaseNode, IListNode, IValueNode
+ class ListNode : BaseNode, IListNode, IValueNode
{
- public ListNode(IList<INode> nodes, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
- int lineposition = -1) : base(namespaceResolver, linenumber, lineposition)
+ public ListNode(IList<INode> nodes, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
+ : base(namespaceResolver, linenumber, lineposition)
{
CollectionItems = nodes.ToList();
}
public XmlName XmlName { get; set; }
-
public List<INode> CollectionItems { get; set; }
public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
{
- if (!visitor.VisitChildrenFirst)
+ if (visitor.VisitingMode == TreeVisitingMode.TopDown)
visitor.Visit(this, parentNode);
foreach (var node in CollectionItems)
node.Accept(visitor, this);
- if (visitor.VisitChildrenFirst)
+ if (visitor.VisitingMode == TreeVisitingMode.BottomUp)
visitor.Visit(this, parentNode);
}
@@ -262,12 +240,11 @@ namespace Xamarin.Forms.Xaml
}
}
- internal static class INodeExtensions
+ static class INodeExtensions
{
public static bool SkipPrefix(this INode node, string prefix)
{
- do
- {
+ do {
if (node.IgnorablePrefixes != null && node.IgnorablePrefixes.Contains(prefix))
return true;
node = node.Parent;
diff --git a/Xamarin.Forms.Xaml/XamlNodeVisitor.cs b/Xamarin.Forms.Xaml/XamlNodeVisitor.cs
index e0b1db32..874a5fbd 100644
--- a/Xamarin.Forms.Xaml/XamlNodeVisitor.cs
+++ b/Xamarin.Forms.Xaml/XamlNodeVisitor.cs
@@ -2,12 +2,11 @@
namespace Xamarin.Forms.Xaml
{
- internal interface IXamlNodeVisitor
+ interface IXamlNodeVisitor
{
- bool VisitChildrenFirst { get; }
-
+ TreeVisitingMode VisitingMode { get; }
bool StopOnDataTemplate { get; }
-
+ bool VisitNodeOnDataTemplate { get; }
bool StopOnResourceDictionary { get; }
void Visit(ValueNode node, INode parentNode);
@@ -17,22 +16,27 @@ namespace Xamarin.Forms.Xaml
void Visit(ListNode node, INode parentNode);
}
- internal class XamlNodeVisitor : IXamlNodeVisitor
+ enum TreeVisitingMode {
+ TopDown,
+ BottomUp
+ }
+
+ class XamlNodeVisitor : IXamlNodeVisitor
{
readonly Action<INode, INode> action;
- public XamlNodeVisitor(Action<INode, INode> action, bool visitChildrenFirst = false, bool stopOnDataTemplate = false)
+ public XamlNodeVisitor(Action<INode, INode> action, TreeVisitingMode visitingMode = TreeVisitingMode.TopDown, bool stopOnDataTemplate = false, bool visitNodeOnDataTemplate = true)
{
this.action = action;
- VisitChildrenFirst = visitChildrenFirst;
+ VisitingMode = visitingMode;
StopOnDataTemplate = stopOnDataTemplate;
+ VisitNodeOnDataTemplate = visitNodeOnDataTemplate;
}
- public bool VisitChildrenFirst { get; }
-
+ public TreeVisitingMode VisitingMode { get; }
public bool StopOnDataTemplate { get; }
-
public bool StopOnResourceDictionary { get; private set; }
+ public bool VisitNodeOnDataTemplate { get; }
public void Visit(ValueNode node, INode parentNode)
{