public void When_PathRewrite(string contextName, string inputExpression, string expectedOutput) { bool IsStaticMethod(string name) { switch (name) { case "Static.MyFunction": return(true); case "System.String.Format": return(true); case "MyNameSpace.Static2.MyFunction": return(true); case "MyNameSpace.Static2.MyProperty": return(true); } return(false); } var output = XBindExpressionParser.Rewrite(contextName, inputExpression, IsStaticMethod); Assert.AreEqual(expectedOutput, output); }
public void When_PathParse(string inputExpression, params string[] output) { bool IsStaticMethod(string name) { switch (name) { case "Static.TestFunction": case "Static.TestFunction2": case "global::Static.TestFunction2": case "Static.TestFunction3": case "System.String.Format": case "MyNameSpace.Static2.MyFunction": return(true); } return(false); } var props = XBindExpressionParser.ParseProperties(inputExpression, IsStaticMethod); Assert.IsTrue(output.SequenceEqual(props), $"Expected [{string.Join(";", output)}], got [{string.Join(";", props)}]"); }
private XmlReader ApplyIgnorables(string file) { var adjusted = File.ReadAllText(file); var document = new XmlDocument(); document.LoadXml(adjusted); var(ignorables, shouldCreateIgnorable) = FindIgnorables(document); var conditionals = FindConditionals(document); shouldCreateIgnorable |= conditionals.ExcludedConditionals.Count > 0; var hasxBind = adjusted.Contains("{x:Bind", StringComparison.Ordinal); if (ignorables == null && !shouldCreateIgnorable && !hasxBind) { // No need to modify file return(XmlReader.Create(file)); } var originalIgnorables = ignorables?.Value ?? ""; var ignoredNs = originalIgnorables.Split(' '); var newIgnored = ignoredNs .Except(_includeXamlNamespaces) .Concat(_excludeXamlNamespaces.Where(n => document.DocumentElement.GetNamespaceOfPrefix(n).HasValue())) .Concat(conditionals.ExcludedConditionals.Select(a => a.LocalName)) .ToArray(); var newIgnoredFlat = newIgnored.JoinBy(" "); if (ignorables != null) { ignorables.Value = newIgnoredFlat; this.Log().InfoFormat("Ignorable XAML namespaces: {0} for {1}", ignorables.Value, file); // change the namespaces using textreplace, to keep the formatting and have proper // line/position reporting. adjusted = adjusted .Replace( "Ignorable=\"{0}\"".InvariantCultureFormat(originalIgnorables), "Ignorable=\"{0}\"".InvariantCultureFormat(ignorables.Value) ) .TrimEnd("\r\n"); } else { // No existing Ignorable node, create one var targetLine = File.ReadLines(file, Encoding.UTF8).First(l => !l.Trim().StartsWith("<!") && !l.IsNullOrWhiteSpace()); if (targetLine.EndsWith(">")) { targetLine = targetLine.TrimEnd(">"); } var mcName = document.DocumentElement .Attributes .Cast <XmlAttribute>() .FirstOrDefault(a => a.Prefix == "xmlns" && a.Value == "http://schemas.openxmlformats.org/markup-compatibility/2006") ?.LocalName; var mcString = ""; if (mcName == null) { mcName = "mc"; mcString = " xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\""; } var replacement = "{0}{1} {2}:Ignorable=\"{3}\"".InvariantCultureFormat(targetLine, mcString, mcName, newIgnoredFlat); adjusted = ReplaceFirst( adjusted, targetLine, replacement ) .TrimEnd("\r\n"); } // Replace the ignored namespaces with unique urns so that same urn that are placed in Ignored attribute // are ignored independently. foreach (var n in newIgnored) { adjusted = adjusted .Replace( "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix(n)), "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, Guid.NewGuid()) ); } // Put all the included namespaces in the same default namespace, so that the properties get their // DeclaringType properly set. foreach (var n in _includeXamlNamespaces) { var originalPrefix = document.DocumentElement.GetNamespaceOfPrefix(n); if (!originalPrefix.StartsWith("using:")) { adjusted = adjusted .Replace( "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix(n)), "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix("")) ); } } foreach (var includedCond in conditionals.IncludedConditionals) { var valueSplit = includedCond.Value.Split('?'); // Strip the conditional part, so the namespace can be parsed correctly by the Xaml reader adjusted = adjusted .Replace( includedCond.OuterXml, "{0}=\"{1}\"".InvariantCultureFormat(includedCond.Name, valueSplit[0]) ); } if (hasxBind) { // Apply replacements to avoid having issues with the XAML parser which does not // support quotes in positional markup extensions parameters. // Note that the UWP preprocessor does not need to apply those replacements as the // x:Bind expressions are being removed during the first phase and replaced by "connections". adjusted = XBindExpressionParser.RewriteDocumentPaths(adjusted); } return(XmlReader.Create(new StringReader(adjusted))); }
private XmlReader ApplyIgnorables(string file) { var adjusted = File.ReadAllText(file); var document = new XmlDocument(); document.LoadXml(adjusted); var ignorables = FindIgnorables(document); if (ignorables != null) { var originalIgnorables = ignorables.Value; var ignoredNs = ignorables.Value.Split(' '); var newIgnored = ignoredNs .Except(_includeXamlNamespaces) .Concat(_excludeXamlNamespaces.Where(n => document.DocumentElement.GetNamespaceOfPrefix(n).HasValue())) .ToArray(); ignorables.Value = newIgnored.JoinBy(" "); this.Log().InfoFormat("Ignorable XAML namespaces: {0} for {1}", ignorables.Value, file); // change the namespaces using textreplace, to keep the formatting and have proper // line/position reporting. adjusted = adjusted.Replace( "Ignorable=\"{0}\"".InvariantCultureFormat(originalIgnorables), "Ignorable=\"{0}\"".InvariantCultureFormat(ignorables.Value) ) .TrimEnd("\r\n"); // Replace the ignored namespaces with unique urns so that same urn that are placed in Ignored attribute // are ignored independently. foreach (var n in newIgnored) { adjusted = adjusted .Replace( "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix(n)), "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, Guid.NewGuid()) ); } // Put all the included namespaces in the same default namespace, so that the properties get their // DeclaringType properly set. foreach (var n in _includeXamlNamespaces) { var originalPrefix = document.DocumentElement.GetNamespaceOfPrefix(n); if (!originalPrefix.StartsWith("using:")) { adjusted = adjusted .Replace( "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix(n)), "xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix("")) ); } } } if (adjusted.Contains("{x:Bind", StringComparison.Ordinal)) { // Apply replacements to avoid having issues with the XAML parser which does not // support quotes in positional markup extensions parameters. // Note that the UWP preprocessor does not need to apply those replacements as the // x:Bind expressions are being removed during the first phase and replaced by "connections". adjusted = XBindExpressionParser.RewriteDocumentPaths(adjusted); } return(XmlReader.Create(new StringReader(adjusted))); }
public void ParseXBind(string bindSource, string expected) { var result = XBindExpressionParser.RewriteDocumentPaths(bindSource); Assert.AreEqual(expected, result); }