Example #1
0
        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);
        }
Example #2
0
        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)}]");
        }
Example #3
0
        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)));
        }
Example #4
0
        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)));
        }
Example #5
0
        public void ParseXBind(string bindSource, string expected)
        {
            var result = XBindExpressionParser.RewriteDocumentPaths(bindSource);

            Assert.AreEqual(expected, result);
        }