2 using System.Collections.Generic;
6 namespace Tizen.NUI.Xaml.Build.Tasks
8 class ExpandMarkupsVisitor : IXamlNodeVisitor
10 readonly IList<XmlName> skips = new List<XmlName>
13 XmlName.xTypeArguments,
14 XmlName.xFactoryMethod,
19 public ExpandMarkupsVisitor(ILContext context)
24 ILContext Context { get; }
26 public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
27 public bool StopOnDataTemplate => false;
28 public bool StopOnResourceDictionary => false;
29 public bool VisitNodeOnDataTemplate => true;
30 public bool SkipChildren(INode node, INode parentNode) => false;
32 public bool IsResourceDictionary(ElementNode node)
34 var parentVar = Context.Variables[(IElementNode)node];
35 return parentVar.VariableType.FullName == "Tizen.NUI.Binding.ResourceDictionary"
36 || parentVar.VariableType.Resolve().BaseType?.FullName == "Tizen.NUI.Binding.ResourceDictionary";
39 public void Visit(ValueNode node, INode parentNode)
43 public void Visit(MarkupNode markupnode, INode parentNode)
46 if (!TryGetProperyName(markupnode, parentNode, out propertyName))
48 if (skips.Contains(propertyName))
50 if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
52 var markupString = markupnode.MarkupString;
53 var node = ParseExpression(ref markupString, Context, markupnode.NamespaceResolver, markupnode) as IElementNode;
56 ((IElementNode)parentNode).Properties[propertyName] = node;
57 node.Accept(new XamlNodeVisitor((n, parent) => n.Parent = parent), parentNode);
61 public void Visit(ElementNode node, INode parentNode)
65 public void Visit(RootNode node, INode parentNode)
69 public void Visit(ListNode node, INode parentNode)
73 public static bool TryGetProperyName(INode node, INode parentNode, out XmlName name)
75 name = default(XmlName);
76 var parentElement = parentNode as IElementNode;
77 if (parentElement == null)
79 foreach (var kvp in parentElement.Properties)
81 if (kvp.Value != node)
89 static INode ParseExpression(ref string expression, ILContext context, IXmlNamespaceResolver nsResolver,
90 IXmlLineInfo xmlLineInfo)
92 if (expression.StartsWith("{}", StringComparison.Ordinal))
93 return new ValueNode(expression.Substring(2), null);
95 if (expression[expression.Length - 1] != '}')
96 throw new XamlParseException("Markup expression missing its closing tag", xmlLineInfo);
100 if (!MarkupExpressionParser.MatchMarkup(out match, expression, out len))
101 throw new XamlParseException("Error while parsing markup expression", xmlLineInfo);
102 expression = expression.Substring(len).TrimStart();
103 if (expression.Length == 0)
104 throw new XamlParseException("Markup expression not closed", xmlLineInfo);
106 var provider = new XamlServiceProvider(null, null);
107 provider.Add(typeof (ILContextProvider), new ILContextProvider(context));
108 provider.Add(typeof (IXmlNamespaceResolver), nsResolver);
109 provider.Add(typeof (IXmlLineInfoProvider), new XmlLineInfoProvider(xmlLineInfo));
111 return new MarkupExpansionParser().Parse(match, ref expression, provider);
114 class ILContextProvider
116 public ILContextProvider(ILContext context)
121 public ILContext Context { get; }
124 class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser<INode>
128 object IExpressionParser.Parse(string match, ref string remaining, IServiceProvider serviceProvider)
130 return Parse(match, ref remaining, serviceProvider);
133 public INode Parse(string match, ref string remaining, IServiceProvider serviceProvider)
135 var nsResolver = serviceProvider.GetService(typeof (IXmlNamespaceResolver)) as IXmlNamespaceResolver;
136 if (nsResolver == null)
137 throw new ArgumentException();
138 IXmlLineInfo xmlLineInfo = null;
139 var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
140 if (xmlLineInfoProvider != null)
141 xmlLineInfo = xmlLineInfoProvider.XmlLineInfo;
142 var contextProvider = serviceProvider.GetService(typeof (ILContextProvider)) as ILContextProvider;
144 var split = match.Split(':');
145 if (split.Length > 2)
146 throw new ArgumentException();
149 if (split.Length == 2)
160 var namespaceuri = nsResolver.LookupNamespace(prefix) ?? "";
161 if (!string.IsNullOrEmpty(prefix) && string.IsNullOrEmpty(namespaceuri))
162 throw new XamlParseException($"Undeclared xmlns prefix '{prefix}'", xmlLineInfo);
163 //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
167 type = new XmlType(namespaceuri, name + "Extension", null);
168 type.GetTypeReference(contextProvider.Context.Module, null);
170 catch (XamlParseException)
172 type = new XmlType(namespaceuri, name, null);
176 throw new NotSupportedException();
178 node = xmlLineInfo == null
179 ? new ElementNode(type, "", nsResolver)
180 : new ElementNode(type, "", nsResolver, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
182 if (remaining.StartsWith("}", StringComparison.Ordinal))
184 remaining = remaining.Substring(1);
190 while ((piece = GetNextPiece(ref remaining, out next)) != null)
191 HandleProperty(piece, serviceProvider, ref remaining, next != '=');
196 protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
198 var nsResolver = serviceProvider.GetService(typeof(IXmlNamespaceResolver)) as IXmlNamespaceResolver;
201 var name = new XmlName(node.NamespaceURI, prop);
202 node.Properties[name] = value as INode ?? new ValueNode(strValue, nsResolver);
204 else //ContentProperty
205 node.CollectionItems.Add(value as INode ?? new ValueNode(strValue, nsResolver));