diff options
author | cpuwzd <30509574+cpuwzd@users.noreply.github.com> | 2023-12-12 09:49:36 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-12 14:49:36 +0000 |
commit | 34132d843795595ccda8cbd5329e290c23b5dbce (patch) | |
tree | 7b7fd2a3ea956a75163712d57d802cacd1815efc | |
parent | 5f23086a29aac7f0cbbe3b2e3d2f980d15e447c7 (diff) | |
download | wix-34132d843795595ccda8cbd5329e290c23b5dbce.tar.gz wix-34132d843795595ccda8cbd5329e290c23b5dbce.tar.bz2 wix-34132d843795595ccda8cbd5329e290c23b5dbce.zip |
Resolve issues with inner text
Fixes wixtoolset/issues#7739
-rw-r--r-- | src/wix/WixToolset.Converters/WixConverter.cs | 382 | ||||
-rw-r--r-- | src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs | 341 |
2 files changed, 625 insertions, 98 deletions
diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs index 178b90be..3fea4498 100644 --- a/src/wix/WixToolset.Converters/WixConverter.cs +++ b/src/wix/WixToolset.Converters/WixConverter.cs | |||
@@ -1033,17 +1033,18 @@ namespace WixToolset.Converters | |||
1033 | using (var lab = new ConversionLab(element)) | 1033 | using (var lab = new ConversionLab(element)) |
1034 | { | 1034 | { |
1035 | var xConditions = element.Elements(ConditionElementName).ToList(); | 1035 | var xConditions = element.Elements(ConditionElementName).ToList(); |
1036 | var comments = new List<XNode>(); | 1036 | var collector = new InnerContentCollector(); |
1037 | var conditions = new List<KeyValuePair<string, string>>(); | 1037 | var conditions = new List<KeyValuePair<string, string>>(); |
1038 | 1038 | ||
1039 | foreach (var xCondition in xConditions) | 1039 | foreach (var xCondition in xConditions) |
1040 | { | 1040 | { |
1041 | var action = UppercaseFirstChar(xCondition.Attribute("Action")?.Value); | 1041 | var action = UppercaseFirstChar(xCondition.Attribute("Action")?.Value); |
1042 | |||
1042 | if (!String.IsNullOrEmpty(action) && | 1043 | if (!String.IsNullOrEmpty(action) && |
1043 | TryGetInnerText(xCondition, out var text, out comments, comments) && | 1044 | collector.CollectInnerTextAndCommentsForAttributeValue(xCondition, out string value) && |
1044 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}Condition' attribute instead.", xCondition.Name.LocalName, action)) | 1045 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}Condition' attribute instead.", xCondition.Name.LocalName, action)) |
1045 | { | 1046 | { |
1046 | conditions.Add(new KeyValuePair<string, string>(action, text)); | 1047 | conditions.Add(new KeyValuePair<string, string>(action, value)); |
1047 | } | 1048 | } |
1048 | } | 1049 | } |
1049 | 1050 | ||
@@ -1062,7 +1063,7 @@ namespace WixToolset.Converters | |||
1062 | } | 1063 | } |
1063 | 1064 | ||
1064 | lab.RemoveOrphanTextNodes(); | 1065 | lab.RemoveOrphanTextNodes(); |
1065 | lab.AddCommentsAsSiblings(comments); | 1066 | lab.AddCommentsAsSiblings(collector.Comments); |
1066 | } | 1067 | } |
1067 | } | 1068 | } |
1068 | 1069 | ||
@@ -1080,15 +1081,17 @@ namespace WixToolset.Converters | |||
1080 | var xCondition = element.Element(ConditionElementName); | 1081 | var xCondition = element.Element(ConditionElementName); |
1081 | if (xCondition != null) | 1082 | if (xCondition != null) |
1082 | { | 1083 | { |
1083 | if (TryGetInnerText(xCondition, out var text, out var comments) && | 1084 | var collector = new InnerContentCollector(); |
1085 | |||
1086 | if (collector.CollectInnerTextAndCommentsForAttributeValue(xCondition, out string value) && | ||
1084 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) | 1087 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) |
1085 | { | 1088 | { |
1086 | using (var lab = new ConversionLab(element)) | 1089 | using (var lab = new ConversionLab(element)) |
1087 | { | 1090 | { |
1088 | xCondition.Remove(); | 1091 | xCondition.Remove(); |
1089 | element.Add(new XAttribute("Condition", text)); | 1092 | element.Add(new XAttribute("Condition", value)); |
1090 | lab.RemoveOrphanTextNodes(); | 1093 | lab.RemoveOrphanTextNodes(); |
1091 | lab.AddCommentsAsSiblings(comments); | 1094 | lab.AddCommentsAsSiblings(collector.Comments); |
1092 | } | 1095 | } |
1093 | } | 1096 | } |
1094 | } | 1097 | } |
@@ -1191,16 +1194,18 @@ namespace WixToolset.Converters | |||
1191 | if (xCondition != null) | 1194 | if (xCondition != null) |
1192 | { | 1195 | { |
1193 | var level = xCondition.Attribute("Level")?.Value; | 1196 | var level = xCondition.Attribute("Level")?.Value; |
1197 | var collector = new InnerContentCollector(); | ||
1198 | |||
1194 | if (!String.IsNullOrEmpty(level) && | 1199 | if (!String.IsNullOrEmpty(level) && |
1195 | TryGetInnerText(xCondition, out var text, out var comments) && | 1200 | collector.CollectInnerTextAndCommentsForAttributeValue(xCondition, out string value) && |
1196 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Level' element instead.", xCondition.Name.LocalName)) | 1201 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Level' element instead.", xCondition.Name.LocalName)) |
1197 | { | 1202 | { |
1198 | using (var lab = new ConversionLab(xCondition)) | 1203 | using (var lab = new ConversionLab(xCondition)) |
1199 | { | 1204 | { |
1200 | lab.ReplaceTargetElement(new XElement(LevelElementName, | 1205 | lab.ReplaceTargetElement(new XElement(LevelElementName, |
1201 | new XAttribute("Value", level), | 1206 | new XAttribute("Value", level), |
1202 | new XAttribute("Condition", text))); | 1207 | new XAttribute("Condition", value))); |
1203 | lab.AddCommentsAsSiblings(comments); | 1208 | lab.AddCommentsAsSiblings(collector.Comments); |
1204 | } | 1209 | } |
1205 | } | 1210 | } |
1206 | } | 1211 | } |
@@ -1235,17 +1240,23 @@ namespace WixToolset.Converters | |||
1235 | private void ConvertLaunchConditionElement(XElement element) | 1240 | private void ConvertLaunchConditionElement(XElement element) |
1236 | { | 1241 | { |
1237 | var message = element.Attribute("Message")?.Value; | 1242 | var message = element.Attribute("Message")?.Value; |
1243 | var collector = new InnerContentCollector(); | ||
1238 | 1244 | ||
1239 | if (!String.IsNullOrEmpty(message) && | 1245 | if (!String.IsNullOrEmpty(message) && |
1240 | TryGetInnerText(element, out var text, out var comments) && | 1246 | collector.CollectInnerTextWithTrailingWhitespaceAndCommentsForAttributeValue(element, out string value) && |
1241 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", element.Name.LocalName)) | 1247 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", element.Name.LocalName)) |
1242 | { | 1248 | { |
1249 | if (String.IsNullOrWhiteSpace(value)) | ||
1250 | { | ||
1251 | value = String.Empty; | ||
1252 | } | ||
1253 | |||
1243 | using (var lab = new ConversionLab(element)) | 1254 | using (var lab = new ConversionLab(element)) |
1244 | { | 1255 | { |
1245 | lab.ReplaceTargetElement(new XElement(LaunchElementName, | 1256 | lab.ReplaceTargetElement(new XElement(LaunchElementName, |
1246 | new XAttribute("Condition", text), | 1257 | new XAttribute("Condition", value), |
1247 | new XAttribute("Message", message))); | 1258 | new XAttribute("Message", message))); |
1248 | lab.AddCommentsAsSiblings(comments); | 1259 | lab.AddCommentsAsSiblings(collector.Comments); |
1249 | } | 1260 | } |
1250 | } | 1261 | } |
1251 | } | 1262 | } |
@@ -1290,7 +1301,8 @@ namespace WixToolset.Converters | |||
1290 | var xCondition = element.Element(ConditionElementName); | 1301 | var xCondition = element.Element(ConditionElementName); |
1291 | if (xCondition != null) | 1302 | if (xCondition != null) |
1292 | { | 1303 | { |
1293 | if (TryGetInnerText(xCondition, out var text, out var comments) && | 1304 | var collector = new InnerContentCollector(); |
1305 | if (collector.CollectInnerTextAndCommentsForAttributeValue(xCondition, out string value) && | ||
1294 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) | 1306 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) |
1295 | { | 1307 | { |
1296 | using (var lab = new ConversionLab(xCondition)) | 1308 | using (var lab = new ConversionLab(xCondition)) |
@@ -1299,9 +1311,9 @@ namespace WixToolset.Converters | |||
1299 | } | 1311 | } |
1300 | using (var lab = new ConversionLab(element)) | 1312 | using (var lab = new ConversionLab(element)) |
1301 | { | 1313 | { |
1302 | element.Add(new XAttribute("Condition", text)); | 1314 | element.Add(new XAttribute("Condition", value)); |
1303 | lab.RemoveOrphanTextNodes(); | 1315 | lab.RemoveOrphanTextNodes(); |
1304 | lab.AddCommentsAsSiblings(comments); | 1316 | lab.AddCommentsAsSiblings(collector.Comments); |
1305 | } | 1317 | } |
1306 | } | 1318 | } |
1307 | } | 1319 | } |
@@ -1669,33 +1681,35 @@ namespace WixToolset.Converters | |||
1669 | 1681 | ||
1670 | private void ConvertPublishElement(XElement element) | 1682 | private void ConvertPublishElement(XElement element) |
1671 | { | 1683 | { |
1672 | if (TryGetInnerText(element, out var text, out var comments) && | 1684 | var collector = new InnerContentCollector(); |
1685 | |||
1686 | if (collector.CollectInnerTextAndCommentsForAttributeValue(element, out string value) && | ||
1673 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", element.Name.LocalName)) | 1687 | this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", element.Name.LocalName)) |
1674 | { | 1688 | { |
1675 | using (var lab = new ConversionLab(element)) | 1689 | using (var lab = new ConversionLab(element)) |
1676 | { | 1690 | { |
1677 | if ("1" == text) | 1691 | if ("1" == value) |
1678 | { | 1692 | { |
1679 | this.OnInformation(ConverterTestType.PublishConditionOneUnnecessary, element, "Adding Condition='1' on {0} elements is no longer necessary. Remove the Condition attribute.", element.Name.LocalName); | 1693 | this.OnInformation(ConverterTestType.PublishConditionOneUnnecessary, element, "Adding Condition='1' on {0} elements is no longer necessary. Remove the Condition attribute.", element.Name.LocalName); |
1680 | } | 1694 | } |
1681 | else | 1695 | else |
1682 | { | 1696 | { |
1683 | element.Add(new XAttribute("Condition", text)); | 1697 | element.Add(new XAttribute("Condition", value)); |
1684 | } | 1698 | } |
1685 | 1699 | ||
1686 | lab.RemoveOrphanTextNodes(); | 1700 | lab.RemoveOrphanTextNodes(); |
1687 | lab.AddCommentsAsSiblings(comments); | 1701 | lab.AddCommentsAsSiblings(collector.Comments); |
1688 | } | 1702 | } |
1689 | } | 1703 | } |
1690 | 1704 | ||
1691 | var evnt = element.Attribute("Event")?.Value; | 1705 | var eventName = element.Attribute("Event")?.Value; |
1692 | var value = element.Attribute("Value")?.Value; | 1706 | var eventValue = element.Attribute("Value")?.Value; |
1693 | 1707 | ||
1694 | if (evnt?.Equals("DoAction", StringComparison.OrdinalIgnoreCase) == true | 1708 | if (eventName?.Equals("DoAction", StringComparison.OrdinalIgnoreCase) == true |
1695 | && value?.StartsWith("WixUI", StringComparison.OrdinalIgnoreCase) == true | 1709 | && eventValue?.StartsWith("WixUI", StringComparison.OrdinalIgnoreCase) == true |
1696 | && this.OnInformation(ConverterTestType.CustomActionIdsIncludePlatformSuffix, element, "Custom action ids have changed in WiX v4 extensions to support platform-specific custom actions. For more information, see https://wixtoolset.org/docs/fourthree/#converting-custom-wixui-dialog-sets.")) | 1710 | && this.OnInformation(ConverterTestType.CustomActionIdsIncludePlatformSuffix, element, "Custom action ids have changed in WiX v4 extensions to support platform-specific custom actions. For more information, see https://wixtoolset.org/docs/fourthree/#converting-custom-wixui-dialog-sets.")) |
1697 | { | 1711 | { |
1698 | element.Attribute("Value").Value = value + "_$(sys.BUILDARCHSHORT)"; | 1712 | element.Attribute("Value").Value = eventValue + "_$(sys.BUILDARCHSHORT)"; |
1699 | } | 1713 | } |
1700 | } | 1714 | } |
1701 | 1715 | ||
@@ -1982,8 +1996,9 @@ namespace WixToolset.Converters | |||
1982 | } | 1996 | } |
1983 | 1997 | ||
1984 | var xScript = xCustomAction.Attribute("Script"); | 1998 | var xScript = xCustomAction.Attribute("Script"); |
1999 | var collector = new InnerContentCollector(); | ||
1985 | 2000 | ||
1986 | if (xScript != null && TryGetInnerText(xCustomAction, out var scriptText, out var comments)) | 2001 | if (xScript != null && collector.CollectInnerTextWithTrailingWhitespaceAndCommentsForScriptFile(xCustomAction, out string value)) |
1987 | { | 2002 | { |
1988 | if (this.OnInformation(ConverterTestType.InnerTextDeprecated, xCustomAction, "Using {0} element text is deprecated. Extract the text to a file and use the 'ScriptSourceFile' attribute to reference it.", xCustomAction.Name.LocalName)) | 2003 | if (this.OnInformation(ConverterTestType.InnerTextDeprecated, xCustomAction, "Using {0} element text is deprecated. Extract the text to a file and use the 'ScriptSourceFile' attribute to reference it.", xCustomAction.Name.LocalName)) |
1989 | { | 2004 | { |
@@ -1992,12 +2007,12 @@ namespace WixToolset.Converters | |||
1992 | var ext = (xScript.Value == "jscript") ? ".js" : (xScript.Value == "vbscript") ? ".vbs" : ".txt"; | 2007 | var ext = (xScript.Value == "jscript") ? ".js" : (xScript.Value == "vbscript") ? ".vbs" : ".txt"; |
1993 | 2008 | ||
1994 | var scriptFile = Path.Combine(scriptFolder, id + ext); | 2009 | var scriptFile = Path.Combine(scriptFolder, id + ext); |
1995 | File.WriteAllText(scriptFile, scriptText); | 2010 | File.WriteAllText(scriptFile, value); |
1996 | 2011 | ||
1997 | RemoveChildren(xCustomAction); | 2012 | RemoveChildren(xCustomAction); |
1998 | xCustomAction.Add(new XAttribute("ScriptSourceFile", scriptFile)); | 2013 | xCustomAction.Add(new XAttribute("ScriptSourceFile", scriptFile)); |
1999 | 2014 | ||
2000 | if (comments.Any()) | 2015 | if (collector.Comments.Any()) |
2001 | { | 2016 | { |
2002 | var remainingNodes = xCustomAction.NodesAfterSelf().ToList(); | 2017 | var remainingNodes = xCustomAction.NodesAfterSelf().ToList(); |
2003 | var replacementNodes = remainingNodes.Where(e => XmlNodeType.Text != e.NodeType); | 2018 | var replacementNodes = remainingNodes.Where(e => XmlNodeType.Text != e.NodeType); |
@@ -2005,7 +2020,7 @@ namespace WixToolset.Converters | |||
2005 | { | 2020 | { |
2006 | node.Remove(); | 2021 | node.Remove(); |
2007 | } | 2022 | } |
2008 | foreach (var comment in comments) | 2023 | foreach (var comment in collector.Comments) |
2009 | { | 2024 | { |
2010 | xCustomAction.Add(comment); | 2025 | xCustomAction.Add(comment); |
2011 | xCustomAction.Add("\n"); | 2026 | xCustomAction.Add("\n"); |
@@ -2144,24 +2159,23 @@ namespace WixToolset.Converters | |||
2144 | 2159 | ||
2145 | private void ConvertInnerTextToAttribute(XElement element, string attributeName) | 2160 | private void ConvertInnerTextToAttribute(XElement element, string attributeName) |
2146 | { | 2161 | { |
2147 | if (TryGetInnerText(element, out var text, out var comments)) | 2162 | var collector = new InnerContentCollector(); |
2163 | |||
2164 | if (collector.CollectInnerTextAndCommentsForAttributeValue(element, out string value)) | ||
2148 | { | 2165 | { |
2149 | // If the target attribute already exists, error if we have anything more than whitespace. | 2166 | // If the target attribute already exists, error if we have anything more than whitespace. |
2150 | var attribute = element.Attribute(attributeName); | 2167 | var attribute = element.Attribute(attributeName); |
2151 | if (attribute != null) | 2168 | if (attribute != null) |
2152 | { | 2169 | { |
2153 | if (!String.IsNullOrWhiteSpace(text)) | 2170 | this.OnError(ConverterTestType.InnerTextDeprecated, attribute, "Using {0} element text is deprecated. Remove the element's text and use only the '{1}' attribute. See the conversion FAQ for more information: https://wixtoolset.org/docs/fourthree/faqs/#converting-packages", element.Name.LocalName, attributeName); |
2154 | { | ||
2155 | this.OnError(ConverterTestType.InnerTextDeprecated, attribute, "Using {0} element text is deprecated. Remove the element's text and use only the '{1}' attribute. See the conversion FAQ for more information: https://wixtoolset.org/docs/fourthree/faqs/#converting-packages", element.Name.LocalName, attributeName); | ||
2156 | } | ||
2157 | } | 2171 | } |
2158 | else if (this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}' attribute instead.", element.Name.LocalName, attributeName)) | 2172 | else if (this.OnInformation(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}' attribute instead.", element.Name.LocalName, attributeName)) |
2159 | { | 2173 | { |
2160 | using (var lab = new ConversionLab(element)) | 2174 | using (var lab = new ConversionLab(element)) |
2161 | { | 2175 | { |
2162 | lab.RemoveOrphanTextNodes(); | 2176 | lab.RemoveOrphanTextNodes(); |
2163 | element.Add(new XAttribute(attributeName, text)); | 2177 | element.Add(new XAttribute(attributeName, value)); |
2164 | lab.AddCommentsAsSiblings(comments); | 2178 | lab.AddCommentsAsSiblings(collector.Comments); |
2165 | } | 2179 | } |
2166 | } | 2180 | } |
2167 | } | 2181 | } |
@@ -2854,42 +2868,6 @@ namespace WixToolset.Converters | |||
2854 | } | 2868 | } |
2855 | } | 2869 | } |
2856 | 2870 | ||
2857 | private static bool TryGetInnerText(XElement element, out string value, out List<XNode> comments) | ||
2858 | { | ||
2859 | return TryGetInnerText(element, out value, out comments, new List<XNode>()); | ||
2860 | } | ||
2861 | |||
2862 | private static bool TryGetInnerText(XElement element, out string value, out List<XNode> comments, List<XNode> initialComments) | ||
2863 | { | ||
2864 | value = null; | ||
2865 | comments = null; | ||
2866 | var found = false; | ||
2867 | |||
2868 | var nodes = element.Nodes().ToList(); | ||
2869 | comments = initialComments; | ||
2870 | var nonCommentNodes = new List<XNode>(); | ||
2871 | |||
2872 | foreach (var node in nodes) | ||
2873 | { | ||
2874 | if (XmlNodeType.Comment == node.NodeType) | ||
2875 | { | ||
2876 | comments.Add(node); | ||
2877 | } | ||
2878 | else | ||
2879 | { | ||
2880 | nonCommentNodes.Add(node); | ||
2881 | } | ||
2882 | } | ||
2883 | |||
2884 | if (nonCommentNodes.Any() && nonCommentNodes.All(e => e.NodeType == XmlNodeType.Text || e.NodeType == XmlNodeType.CDATA)) | ||
2885 | { | ||
2886 | value = String.Join(String.Empty, nonCommentNodes.Cast<XText>().Select(TrimTextValue)); | ||
2887 | found = true; | ||
2888 | } | ||
2889 | |||
2890 | return found; | ||
2891 | } | ||
2892 | |||
2893 | private static bool IsTextNode(XNode node, out XText text) | 2871 | private static bool IsTextNode(XNode node, out XText text) |
2894 | { | 2872 | { |
2895 | text = null; | 2873 | text = null; |
@@ -2910,22 +2888,6 @@ namespace WixToolset.Converters | |||
2910 | } | 2888 | } |
2911 | } | 2889 | } |
2912 | 2890 | ||
2913 | private static string TrimTextValue(XText text) | ||
2914 | { | ||
2915 | var value = text.Value; | ||
2916 | |||
2917 | if (String.IsNullOrEmpty(value)) | ||
2918 | { | ||
2919 | return String.Empty; | ||
2920 | } | ||
2921 | else if (text.NodeType == XmlNodeType.CDATA && String.IsNullOrWhiteSpace(value)) | ||
2922 | { | ||
2923 | return " "; | ||
2924 | } | ||
2925 | |||
2926 | return value.Trim(); | ||
2927 | } | ||
2928 | |||
2929 | private static void RemoveChildren(XElement element) | 2891 | private static void RemoveChildren(XElement element) |
2930 | { | 2892 | { |
2931 | var nodes = element.Nodes().ToList(); | 2893 | var nodes = element.Nodes().ToList(); |
@@ -2975,6 +2937,250 @@ namespace WixToolset.Converters | |||
2975 | return true; | 2937 | return true; |
2976 | } | 2938 | } |
2977 | 2939 | ||
2940 | // This class encapsulates methods for extraving text and comments from XElements. Multiple calls can be made to the collection | ||
2941 | // methods to processs multiple XElements. The Comments property is used to extract the list of comments accumulated during the collection process. | ||
2942 | private class InnerContentCollector | ||
2943 | { | ||
2944 | public InnerContentCollector() | ||
2945 | { | ||
2946 | this.Comments = new List<XNode>(); | ||
2947 | } | ||
2948 | |||
2949 | public List<XNode> Comments { get; private set; } | ||
2950 | |||
2951 | public bool CollectInnerTextAndCommentsForAttributeValue(XElement element, out string collectedText) | ||
2952 | { | ||
2953 | char[] whitespaceChars = { ' ', '\t', '\r', '\n' }; | ||
2954 | var nodes = element.Nodes().ToList(); | ||
2955 | var inWhitespace = false; | ||
2956 | var cDataFound = false; | ||
2957 | var sb = new StringBuilder(); | ||
2958 | |||
2959 | foreach (var node in nodes) | ||
2960 | { | ||
2961 | if (XmlNodeType.Comment == node.NodeType) | ||
2962 | { | ||
2963 | this.Comments.Add(node); | ||
2964 | } | ||
2965 | else if (XmlNodeType.CDATA == node.NodeType || XmlNodeType.Text == node.NodeType) | ||
2966 | { | ||
2967 | var isCData = XmlNodeType.CDATA == node.NodeType; | ||
2968 | |||
2969 | if (isCData) | ||
2970 | { | ||
2971 | cDataFound = true; | ||
2972 | } | ||
2973 | |||
2974 | var text = node is XText xtext ? xtext.Value : String.Empty; | ||
2975 | var nodeSB = new StringBuilder(); | ||
2976 | |||
2977 | foreach (var c in text) | ||
2978 | { | ||
2979 | char? emit = c; | ||
2980 | |||
2981 | // Replace contiguous whitespace with a single space. | ||
2982 | if (' ' == c || '\r' == c || '\n' == c || '\t' == c) | ||
2983 | { | ||
2984 | if (!inWhitespace) | ||
2985 | { | ||
2986 | inWhitespace = true; | ||
2987 | emit = ' '; | ||
2988 | } | ||
2989 | else | ||
2990 | { | ||
2991 | emit = null; | ||
2992 | } | ||
2993 | } | ||
2994 | else | ||
2995 | { | ||
2996 | inWhitespace = false; | ||
2997 | } | ||
2998 | |||
2999 | if (emit.HasValue) | ||
3000 | { | ||
3001 | nodeSB.Append(emit); | ||
3002 | } | ||
3003 | } | ||
3004 | |||
3005 | text = nodeSB.ToString().Trim(whitespaceChars); | ||
3006 | sb.Append(text); | ||
3007 | } | ||
3008 | } | ||
3009 | var found = false; | ||
3010 | collectedText = sb.ToString(); | ||
3011 | |||
3012 | if (0 < collectedText.Length) | ||
3013 | { | ||
3014 | found = true; | ||
3015 | } | ||
3016 | |||
3017 | collectedText = collectedText.Trim(whitespaceChars); | ||
3018 | |||
3019 | if (cDataFound) | ||
3020 | { | ||
3021 | found = true; | ||
3022 | |||
3023 | if (0 == collectedText.Length) | ||
3024 | { | ||
3025 | collectedText = " "; | ||
3026 | } | ||
3027 | } | ||
3028 | |||
3029 | return found; | ||
3030 | } | ||
3031 | |||
3032 | public bool CollectInnerTextWithTrailingWhitespaceAndCommentsForAttributeValue(XElement element, out string collectedText) | ||
3033 | { | ||
3034 | char[] whitespaceChars = { ' ', '\t', '\r', '\n' }; | ||
3035 | var nodes = element.Nodes().ToList(); | ||
3036 | var inWhitespace = false; | ||
3037 | var cDataFound = false; | ||
3038 | var whitespaceFound = false; | ||
3039 | var sb = new StringBuilder(); | ||
3040 | |||
3041 | foreach (var node in nodes) | ||
3042 | { | ||
3043 | if (XmlNodeType.Comment == node.NodeType) | ||
3044 | { | ||
3045 | this.Comments.Add(node); | ||
3046 | } | ||
3047 | else if (XmlNodeType.CDATA == node.NodeType || XmlNodeType.Text == node.NodeType) | ||
3048 | { | ||
3049 | var isCData = XmlNodeType.CDATA == node.NodeType; | ||
3050 | |||
3051 | if (isCData) | ||
3052 | { | ||
3053 | cDataFound = true; | ||
3054 | } | ||
3055 | |||
3056 | var text = node is XText xtext ? xtext.Value : String.Empty; | ||
3057 | var nodeSB = new StringBuilder(); | ||
3058 | |||
3059 | foreach (var c in text) | ||
3060 | { | ||
3061 | char? emit = c; | ||
3062 | |||
3063 | // Replace contiguous whitespace with a single space. | ||
3064 | if (' ' == c || '\r' == c || '\n' == c || '\t' == c) | ||
3065 | { | ||
3066 | if (!inWhitespace) | ||
3067 | { | ||
3068 | inWhitespace = true; | ||
3069 | whitespaceFound = true; | ||
3070 | emit = ' '; | ||
3071 | } | ||
3072 | else | ||
3073 | { | ||
3074 | emit = null; | ||
3075 | } | ||
3076 | } | ||
3077 | else | ||
3078 | { | ||
3079 | inWhitespace = false; | ||
3080 | } | ||
3081 | |||
3082 | if (emit.HasValue) | ||
3083 | { | ||
3084 | nodeSB.Append(emit); | ||
3085 | } | ||
3086 | } | ||
3087 | |||
3088 | text = nodeSB.ToString(); | ||
3089 | |||
3090 | if (0 < text.Length) | ||
3091 | { | ||
3092 | text = text.Trim(whitespaceChars); | ||
3093 | |||
3094 | if (0 == text.Length) | ||
3095 | { | ||
3096 | text = " "; | ||
3097 | } | ||
3098 | } | ||
3099 | |||
3100 | sb.Append(text); | ||
3101 | } | ||
3102 | } | ||
3103 | var found = false; | ||
3104 | collectedText = sb.ToString(); | ||
3105 | |||
3106 | if (0 < collectedText.Length) | ||
3107 | { | ||
3108 | found = true; | ||
3109 | } | ||
3110 | |||
3111 | collectedText = collectedText.Trim(whitespaceChars); | ||
3112 | |||
3113 | if (whitespaceFound) | ||
3114 | { | ||
3115 | found = true; | ||
3116 | } | ||
3117 | |||
3118 | if (cDataFound) | ||
3119 | { | ||
3120 | found = true; | ||
3121 | |||
3122 | if (0 == collectedText.Length) | ||
3123 | { | ||
3124 | collectedText = " "; | ||
3125 | } | ||
3126 | } | ||
3127 | |||
3128 | return found; | ||
3129 | } | ||
3130 | |||
3131 | public bool CollectInnerTextWithTrailingWhitespaceAndCommentsForScriptFile(XElement element, out string collectedText) | ||
3132 | { | ||
3133 | var value = String.Empty; | ||
3134 | char[] whitespaceChars = { ' ', '\t', '\r', '\n' }; | ||
3135 | var nodes = element.Nodes().ToList(); | ||
3136 | var cDataFound = false; | ||
3137 | var sb = new StringBuilder(); | ||
3138 | |||
3139 | foreach (var node in nodes) | ||
3140 | { | ||
3141 | if (XmlNodeType.Comment == node.NodeType) | ||
3142 | { | ||
3143 | this.Comments.Add(node); | ||
3144 | } | ||
3145 | else if (XmlNodeType.CDATA == node.NodeType || XmlNodeType.Text == node.NodeType) | ||
3146 | { | ||
3147 | var isCData = XmlNodeType.CDATA == node.NodeType; | ||
3148 | |||
3149 | if (isCData) | ||
3150 | { | ||
3151 | cDataFound = true; | ||
3152 | } | ||
3153 | |||
3154 | var text = node is XText xtext ? xtext.Value.Trim(whitespaceChars) : String.Empty; | ||
3155 | sb.Append(text); | ||
3156 | } | ||
3157 | } | ||
3158 | |||
3159 | var found = false; | ||
3160 | |||
3161 | collectedText = sb.ToString(); | ||
3162 | |||
3163 | if (0 < collectedText.Length) | ||
3164 | { | ||
3165 | found = true; | ||
3166 | } | ||
3167 | |||
3168 | collectedText = collectedText.Trim(whitespaceChars); | ||
3169 | |||
3170 | if (cDataFound) | ||
3171 | { | ||
3172 | found = true; | ||
3173 | |||
3174 | if (0 == collectedText.Length) | ||
3175 | { | ||
3176 | collectedText = " "; | ||
3177 | } | ||
3178 | } | ||
3179 | |||
3180 | return found; | ||
3181 | } | ||
3182 | } | ||
3183 | |||
2978 | /// <summary> | 3184 | /// <summary> |
2979 | /// Converter test types. These are used to condition error messages down to warnings. | 3185 | /// Converter test types. These are used to condition error messages down to warnings. |
2980 | /// </summary> | 3186 | /// </summary> |
diff --git a/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs index e3563c60..f9b60673 100644 --- a/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs +++ b/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs | |||
@@ -21,8 +21,8 @@ namespace WixToolsetTest.Converters | |||
21 | " <UI>", | 21 | " <UI>", |
22 | " <Dialog Id='Dlg1'>", | 22 | " <Dialog Id='Dlg1'>", |
23 | " <Control Id='Control1'>", | 23 | " <Control Id='Control1'>", |
24 | " <Condition Action='disable'>x=y</Condition>", | 24 | " <Condition Action='disable'>$(var.x)=$(var.y)</Condition>", |
25 | " <Condition Action='hide'>a<>b</Condition>", | 25 | " <Condition Action='hide'>$(var.a)<>$(var.b)</Condition>", |
26 | " </Control>", | 26 | " </Control>", |
27 | " </Dialog>", | 27 | " </Dialog>", |
28 | " </UI>", | 28 | " </UI>", |
@@ -35,7 +35,7 @@ namespace WixToolsetTest.Converters | |||
35 | " <Fragment>", | 35 | " <Fragment>", |
36 | " <UI>", | 36 | " <UI>", |
37 | " <Dialog Id=\"Dlg1\">", | 37 | " <Dialog Id=\"Dlg1\">", |
38 | " <Control Id=\"Control1\" DisableCondition=\"x=y\" HideCondition=\"a<>b\" />", | 38 | " <Control Id=\"Control1\" DisableCondition=\"$(var.x)=$(var.y)\" HideCondition=\"$(var.a)<>$(var.b)\" />", |
39 | " </Dialog>", | 39 | " </Dialog>", |
40 | " </UI>", | 40 | " </UI>", |
41 | " </Fragment>", | 41 | " </Fragment>", |
@@ -64,8 +64,8 @@ namespace WixToolsetTest.Converters | |||
64 | " <UI>", | 64 | " <UI>", |
65 | " <Dialog Id='Dlg1'>", | 65 | " <Dialog Id='Dlg1'>", |
66 | " <Control Id='Control1'>", | 66 | " <Control Id='Control1'>", |
67 | " <Condition Action='hide'>x=y</Condition>", | 67 | " <Condition Action='hide'>$(var.x)=$(var.y)</Condition>", |
68 | " <Condition Action='hide'>a<>b</Condition>", | 68 | " <Condition Action='hide'>$(var.a)<>$(var.b)</Condition>", |
69 | " </Control>", | 69 | " </Control>", |
70 | " </Dialog>", | 70 | " </Dialog>", |
71 | " </UI>", | 71 | " </UI>", |
@@ -78,7 +78,7 @@ namespace WixToolsetTest.Converters | |||
78 | " <Fragment>", | 78 | " <Fragment>", |
79 | " <UI>", | 79 | " <UI>", |
80 | " <Dialog Id=\"Dlg1\">", | 80 | " <Dialog Id=\"Dlg1\">", |
81 | " <Control Id=\"Control1\" HideCondition=\"(x=y) OR (a<>b)\" />", | 81 | " <Control Id=\"Control1\" HideCondition=\"($(var.x)=$(var.y)) OR ($(var.a)<>$(var.b))\" />", |
82 | " </Dialog>", | 82 | " </Dialog>", |
83 | " </UI>", | 83 | " </UI>", |
84 | " </Fragment>", | 84 | " </Fragment>", |
@@ -107,8 +107,8 @@ namespace WixToolsetTest.Converters | |||
107 | " <UI>", | 107 | " <UI>", |
108 | " <Dialog Id='Dlg1'>", | 108 | " <Dialog Id='Dlg1'>", |
109 | " <Control Id='Control1'>", | 109 | " <Control Id='Control1'>", |
110 | " <Condition Action='disable'><!-- Comment 1 -->x=y</Condition>", | 110 | " <Condition Action='disable'><!-- Comment 1 -->$(var.x)=$(var.y)</Condition>", |
111 | " <Condition Action='hide'><!-- Comment 2 -->a<>b</Condition>", | 111 | " <Condition Action='hide'><!-- Comment 2 -->$(var.a)<>$(var.b)</Condition>", |
112 | " </Control>", | 112 | " </Control>", |
113 | " </Dialog>", | 113 | " </Dialog>", |
114 | " </UI>", | 114 | " </UI>", |
@@ -123,7 +123,91 @@ namespace WixToolsetTest.Converters | |||
123 | " <Dialog Id=\"Dlg1\">", | 123 | " <Dialog Id=\"Dlg1\">", |
124 | " <!-- Comment 1 -->", | 124 | " <!-- Comment 1 -->", |
125 | " <!-- Comment 2 -->", | 125 | " <!-- Comment 2 -->", |
126 | " <Control Id=\"Control1\" DisableCondition=\"x=y\" HideCondition=\"a<>b\" />", | 126 | " <Control Id=\"Control1\" DisableCondition=\"$(var.x)=$(var.y)\" HideCondition=\"$(var.a)<>$(var.b)\" />", |
127 | " </Dialog>", | ||
128 | " </UI>", | ||
129 | " </Fragment>", | ||
130 | "</Wix>" | ||
131 | }; | ||
132 | |||
133 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
134 | |||
135 | var messaging = new MockMessaging(); | ||
136 | var converter = new WixConverter(messaging, 2, null, null); | ||
137 | |||
138 | var errors = converter.ConvertDocument(document); | ||
139 | Assert.Equal(4, errors); | ||
140 | |||
141 | var actualLines = UnformattedDocumentLines(document); | ||
142 | WixAssert.CompareLineByLine(expected, actualLines); | ||
143 | } | ||
144 | |||
145 | [Fact] | ||
146 | public void DemonstrateTheHandlingOfQuotedBackslashesInInnerText() | ||
147 | { | ||
148 | var parse = String.Join(Environment.NewLine, | ||
149 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
150 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
151 | " <Fragment>", | ||
152 | " <UI>", | ||
153 | " <Dialog Id='Dlg1'>", | ||
154 | " <Control Id='Control1'>", | ||
155 | " <Condition Action='hide'>\"\\\"=$(var.separator)</Condition>", | ||
156 | " </Control>", | ||
157 | " </Dialog>", | ||
158 | " </UI>", | ||
159 | " </Fragment>", | ||
160 | "</Wix>"); | ||
161 | |||
162 | var expected = new[] | ||
163 | { | ||
164 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
165 | " <Fragment>", | ||
166 | " <UI>", | ||
167 | " <Dialog Id=\"Dlg1\">", | ||
168 | " <Control Id=\"Control1\" HideCondition=\""\\"=$(var.separator)\" />", | ||
169 | " </Dialog>", | ||
170 | " </UI>", | ||
171 | " </Fragment>", | ||
172 | "</Wix>" | ||
173 | }; | ||
174 | |||
175 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
176 | |||
177 | var messaging = new MockMessaging(); | ||
178 | var converter = new WixConverter(messaging, 2, null, null); | ||
179 | |||
180 | var errors = converter.ConvertDocument(document); | ||
181 | |||
182 | var actualLines = UnformattedDocumentLines(document); | ||
183 | WixAssert.CompareLineByLine(expected, actualLines); | ||
184 | } | ||
185 | |||
186 | [Fact] | ||
187 | public void FixControlConditionWithStringConstants() | ||
188 | { | ||
189 | var parse = String.Join(Environment.NewLine, | ||
190 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
191 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
192 | " <Fragment>", | ||
193 | " <UI>", | ||
194 | " <Dialog Id='Dlg1'>", | ||
195 | " <Control Id='Control1'>", | ||
196 | " <Condition Action='hide'>\"x\"=$(var.y)</Condition>", | ||
197 | " <Condition Action='hide'>\"x's\"=$(var.y)</Condition>", | ||
198 | " </Control>", | ||
199 | " </Dialog>", | ||
200 | " </UI>", | ||
201 | " </Fragment>", | ||
202 | "</Wix>"); | ||
203 | |||
204 | var expected = new[] | ||
205 | { | ||
206 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
207 | " <Fragment>", | ||
208 | " <UI>", | ||
209 | " <Dialog Id=\"Dlg1\">", | ||
210 | " <Control Id=\"Control1\" HideCondition=\"("x"=$(var.y)) OR ("x's"=$(var.y))\" />", | ||
127 | " </Dialog>", | 211 | " </Dialog>", |
128 | " </UI>", | 212 | " </UI>", |
129 | " </Fragment>", | 213 | " </Fragment>", |
@@ -306,6 +390,78 @@ namespace WixToolsetTest.Converters | |||
306 | } | 390 | } |
307 | 391 | ||
308 | [Fact] | 392 | [Fact] |
393 | public void FixMultilineComponentCondition() | ||
394 | { | ||
395 | var parse = String.Join(Environment.NewLine, | ||
396 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
397 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
398 | " <Fragment>", | ||
399 | " <Component Id='Comp1' Directory='ApplicationFolder'>", | ||
400 | " <Condition>1<2</Condition>", | ||
401 | " </Component>", | ||
402 | " </Fragment>", | ||
403 | "</Wix>"); | ||
404 | |||
405 | var expected = new[] | ||
406 | { | ||
407 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
408 | " <Fragment>", | ||
409 | " <Component Id=\"Comp1\" Directory=\"ApplicationFolder\" Condition=\"1<2\" />", | ||
410 | " </Fragment>", | ||
411 | "</Wix>" | ||
412 | }; | ||
413 | |||
414 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
415 | |||
416 | var messaging = new MockMessaging(); | ||
417 | var converter = new WixConverter(messaging, 2, null, null); | ||
418 | |||
419 | var errors = converter.ConvertDocument(document); | ||
420 | Assert.Equal(3, errors); | ||
421 | |||
422 | var actualLines = UnformattedDocumentLines(document); | ||
423 | WixAssert.CompareLineByLine(expected, actualLines); | ||
424 | } | ||
425 | |||
426 | [Fact] | ||
427 | public void FixMultilineComponentConditionWithComment() | ||
428 | { | ||
429 | var parse = String.Join(Environment.NewLine, | ||
430 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
431 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
432 | " <Fragment>", | ||
433 | " <Component Id='Comp1' Directory='ApplicationFolder'>", | ||
434 | " <Condition>", | ||
435 | " <!-- Comment -->", | ||
436 | " 1<2 OR ", | ||
437 | " 4<3", | ||
438 | " </Condition>", | ||
439 | " </Component>", | ||
440 | " </Fragment>", | ||
441 | "</Wix>"); | ||
442 | var expected = new[] | ||
443 | { | ||
444 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
445 | " <Fragment>", | ||
446 | " <!-- Comment -->", | ||
447 | " <Component Id=\"Comp1\" Directory=\"ApplicationFolder\" Condition=\"1<2 OR 4<3\" />", | ||
448 | " </Fragment>", | ||
449 | "</Wix>" | ||
450 | }; | ||
451 | |||
452 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
453 | |||
454 | var messaging = new MockMessaging(); | ||
455 | var converter = new WixConverter(messaging, 2, null, null); | ||
456 | |||
457 | var errors = converter.ConvertDocument(document); | ||
458 | Assert.Equal(3, errors); | ||
459 | |||
460 | var actualLines = UnformattedDocumentLines(document); | ||
461 | WixAssert.CompareLineByLine(expected, actualLines); | ||
462 | } | ||
463 | |||
464 | [Fact] | ||
309 | public void FixEmptyCondition() | 465 | public void FixEmptyCondition() |
310 | { | 466 | { |
311 | var parse = String.Join(Environment.NewLine, | 467 | var parse = String.Join(Environment.NewLine, |
@@ -481,6 +637,90 @@ namespace WixToolsetTest.Converters | |||
481 | } | 637 | } |
482 | 638 | ||
483 | [Fact] | 639 | [Fact] |
640 | public void FixMultilineFeatureCondition() | ||
641 | { | ||
642 | var parse = String.Join(Environment.NewLine, | ||
643 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
644 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
645 | " <Fragment>", | ||
646 | " <Feature Id='ShellExtensionFeature' Level='0' InstallDefault='local' >", | ||
647 | " <Condition Level='1'>", | ||
648 | " (NOT Installed AND NOT PERUSER) OR", | ||
649 | " (Installed AND ZOS_SHELL_EXTENSION_INSTALLLED)", | ||
650 | " </Condition>", | ||
651 | " <ComponentGroupRef Id='ShellExtComponents' />", | ||
652 | " </Feature>", | ||
653 | " </Fragment>", | ||
654 | "</Wix>"); | ||
655 | |||
656 | var expected = new[] | ||
657 | { | ||
658 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
659 | " <Fragment>", | ||
660 | " <Feature Id=\"ShellExtensionFeature\" Level=\"0\" InstallDefault=\"local\">", | ||
661 | " <Level Value=\"1\" Condition=\"(NOT Installed AND NOT PERUSER) OR (Installed AND ZOS_SHELL_EXTENSION_INSTALLLED)\" />", | ||
662 | " <ComponentGroupRef Id=\"ShellExtComponents\" />", | ||
663 | " </Feature>", | ||
664 | " </Fragment>", | ||
665 | "</Wix>" | ||
666 | }; | ||
667 | |||
668 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
669 | |||
670 | var messaging = new MockMessaging(); | ||
671 | var converter = new WixConverter(messaging, 2, null, null); | ||
672 | |||
673 | var errors = converter.ConvertDocument(document); | ||
674 | Assert.Equal(3, errors); | ||
675 | |||
676 | var actualLines = UnformattedDocumentLines(document); | ||
677 | WixAssert.CompareLineByLine(expected, actualLines); | ||
678 | } | ||
679 | |||
680 | [Fact] | ||
681 | public void FixMultilineFeatureConditionWithComment() | ||
682 | { | ||
683 | var parse = String.Join(Environment.NewLine, | ||
684 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
685 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
686 | " <Fragment>", | ||
687 | " <Feature Id='ShellExtensionFeature' Level='0' InstallDefault='local' >", | ||
688 | " <Condition Level='1'>", | ||
689 | " <!-- Comment -->", | ||
690 | " (NOT Installed AND NOT PERUSER) OR", | ||
691 | " (Installed AND ZOS_SHELL_EXTENSION_INSTALLLED)", | ||
692 | " </Condition>", | ||
693 | " <ComponentGroupRef Id='ShellExtComponents' />", | ||
694 | " </Feature>", | ||
695 | " </Fragment>", | ||
696 | "</Wix>"); | ||
697 | |||
698 | var expected = new[] | ||
699 | { | ||
700 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
701 | " <Fragment>", | ||
702 | " <Feature Id=\"ShellExtensionFeature\" Level=\"0\" InstallDefault=\"local\">", | ||
703 | " <!-- Comment -->", | ||
704 | " <Level Value=\"1\" Condition=\"(NOT Installed AND NOT PERUSER) OR (Installed AND ZOS_SHELL_EXTENSION_INSTALLLED)\" />", | ||
705 | " <ComponentGroupRef Id=\"ShellExtComponents\" />", | ||
706 | " </Feature>", | ||
707 | " </Fragment>", | ||
708 | "</Wix>" | ||
709 | }; | ||
710 | |||
711 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
712 | |||
713 | var messaging = new MockMessaging(); | ||
714 | var converter = new WixConverter(messaging, 2, null, null); | ||
715 | |||
716 | var errors = converter.ConvertDocument(document); | ||
717 | Assert.Equal(3, errors); | ||
718 | |||
719 | var actualLines = UnformattedDocumentLines(document); | ||
720 | WixAssert.CompareLineByLine(expected, actualLines); | ||
721 | } | ||
722 | |||
723 | [Fact] | ||
484 | public void FixLaunchConditionInFragment() | 724 | public void FixLaunchConditionInFragment() |
485 | { | 725 | { |
486 | var parse = String.Join(Environment.NewLine, | 726 | var parse = String.Join(Environment.NewLine, |
@@ -519,7 +759,7 @@ namespace WixToolsetTest.Converters | |||
519 | } | 759 | } |
520 | 760 | ||
521 | [Fact] | 761 | [Fact] |
522 | public void FixLaunchConditionWithComment() | 762 | public void FixLaunchConditionInFragmentWithComment() |
523 | { | 763 | { |
524 | var parse = String.Join(Environment.NewLine, | 764 | var parse = String.Join(Environment.NewLine, |
525 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | 765 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", |
@@ -559,6 +799,87 @@ namespace WixToolsetTest.Converters | |||
559 | } | 799 | } |
560 | 800 | ||
561 | [Fact] | 801 | [Fact] |
802 | public void FixMultilineLaunchConditionInFragment() | ||
803 | { | ||
804 | var parse = String.Join(Environment.NewLine, | ||
805 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
806 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
807 | " <Fragment>", | ||
808 | " <Condition Message='Stop the install'>", | ||
809 | " 1<2 OR ", | ||
810 | " 4<3", | ||
811 | " </Condition>", | ||
812 | " <Condition Message='Do not stop'>", | ||
813 | " 1=2", | ||
814 | " </Condition>", | ||
815 | " </Fragment>", | ||
816 | "</Wix>"); | ||
817 | |||
818 | var expected = new[] | ||
819 | { | ||
820 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
821 | " <Fragment>", | ||
822 | " <Launch Condition=\"1<2 OR 4<3\" Message=\"Stop the install\" />", | ||
823 | " <Launch Condition=\"1=2\" Message=\"Do not stop\" />", | ||
824 | " </Fragment>", | ||
825 | "</Wix>" | ||
826 | }; | ||
827 | |||
828 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
829 | |||
830 | var messaging = new MockMessaging(); | ||
831 | var converter = new WixConverter(messaging, 2, null, null); | ||
832 | |||
833 | var errors = converter.ConvertDocument(document); | ||
834 | Assert.Equal(4, errors); | ||
835 | |||
836 | var actualLines = UnformattedDocumentLines(document); | ||
837 | WixAssert.CompareLineByLine(expected, actualLines); | ||
838 | } | ||
839 | |||
840 | [Fact] | ||
841 | public void FixMultilineLaunchConditionInFragmentWithComment() | ||
842 | { | ||
843 | var parse = String.Join(Environment.NewLine, | ||
844 | "<?xml version=\"1.0\" encoding=\"utf-16\"?>", | ||
845 | "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>", | ||
846 | " <Fragment>", | ||
847 | " <Condition Message='Stop the install'>", | ||
848 | " <!-- Comment 1 -->", | ||
849 | " 1<2 OR", | ||
850 | " 4<3", | ||
851 | " </Condition>", | ||
852 | " <Condition Message='Do not stop'>", | ||
853 | " <!-- Comment 2 -->1=2", | ||
854 | " </Condition>", | ||
855 | " </Fragment>", | ||
856 | "</Wix>"); | ||
857 | |||
858 | var expected = new[] | ||
859 | { | ||
860 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
861 | " <Fragment>", | ||
862 | " <!-- Comment 1 -->", | ||
863 | " <Launch Condition=\"1<2 OR 4<3\" Message=\"Stop the install\" />", | ||
864 | " <!-- Comment 2 -->", | ||
865 | " <Launch Condition=\"1=2\" Message=\"Do not stop\" />", | ||
866 | " </Fragment>", | ||
867 | "</Wix>" | ||
868 | }; | ||
869 | |||
870 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
871 | |||
872 | var messaging = new MockMessaging(); | ||
873 | var converter = new WixConverter(messaging, 2, null, null); | ||
874 | |||
875 | var errors = converter.ConvertDocument(document); | ||
876 | Assert.Equal(4, errors); | ||
877 | |||
878 | var actualLines = UnformattedDocumentLines(document); | ||
879 | WixAssert.CompareLineByLine(expected, actualLines); | ||
880 | } | ||
881 | |||
882 | [Fact] | ||
562 | public void FixLaunchConditionInProduct() | 883 | public void FixLaunchConditionInProduct() |
563 | { | 884 | { |
564 | var parse = String.Join(Environment.NewLine, | 885 | var parse = String.Join(Environment.NewLine, |