@joebigelow / wix / commits / 5df3b188

Add StandardDirectory conversions

Completes wixtoolset/issues#6416

Rob Mensching committed Apr 6, 2021 at 13:30 UTC 5df3b188583697ca6f3910224e2135e8bacc56f0
2 files changed +154 -1
src/WixToolset.Converters/WixConverter.cs
+62 -1
@@ -12,6 +12,7 @@ namespace WixToolset.Converters
12 using System.Xml;
13 using System.Xml.Linq;
14 using WixToolset.Data;
15 + using WixToolset.Data.WindowsInstaller;
16 using WixToolset.Extensibility.Services;
17
18 /// <summary>
@@ -120,6 +121,7 @@ namespace WixToolset.Converters
121 private static readonly XName ShortcutPropertyElementName = WixNamespace + "ShortcutProperty";
122 private static readonly XName SoftwareTagElementName = WixNamespace + "SoftwareTag";
123 private static readonly XName SoftwareTagRefElementName = WixNamespace + "SoftwareTagRef";
124 + private static readonly XName StandardDirectoryElementName = WixNamespace + "StandardDirectory";
125 private static readonly XName TagElementName = XNamespace.None + "Tag";
126 private static readonly XName TagRefElementName = XNamespace.None + "TagRef";
127 private static readonly XName TextElementName = WixNamespace + "Text";
@@ -468,7 +470,18 @@ namespace WixToolset.Converters
470 {
471 this.ConvertElement(element);
472
471 - this.ConvertNodes(element.Nodes(), level + 1);
473 + var before = element.Nodes().ToList();
474 +
475 + this.ConvertNodes(before, level + 1);
476 +
477 + // If any nodes were added during the processing of the children,
478 + // ensure those added children get processed as well.
479 + var added = element.Nodes().Except(before).ToList();
480 +
481 + if (added.Any())
482 + {
483 + this.ConvertNodes(added, level + 1);
484 + }
485 }
486 }
487 }
@@ -950,6 +963,44 @@ namespace WixToolset.Converters
963 }
964 }
965 }
966 +
967 + var id = element.Attribute("Id")?.Value;
968 +
969 + if (id == "TARGETDIR" &&
970 + this.OnError(ConverterTestType.TargetDirDeprecated, element, "The TARGETDIR directory should not longer be explicitly defined. Remove the Directory element with Id attribute 'TARGETDIR'."))
971 + {
972 + var parentElement = element.Parent;
973 +
974 + element.Remove();
975 +
976 + if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value))
977 + {
978 + parentElement.FirstNode.Remove();
979 + }
980 +
981 + foreach (var child in element.Nodes())
982 + {
983 + parentElement.Add(child);
984 + }
985 +
986 + element.RemoveAll();
987 +
988 + if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value))
989 + {
990 + parentElement.FirstNode.Remove();
991 + }
992 + }
993 + else if (id != null &&
994 + WindowsInstallerStandard.IsStandardDirectory(id) &&
995 + this.OnError(ConverterTestType.DefiningStandardDirectoryDeprecated, element, "Standard directories such as '{0}' should no longer be defined using the Directory element. Use the StandardDirectory element instead.", id))
996 + {
997 + element.Name = StandardDirectoryElementName;
998 +
999 + foreach (var attrib in element.Attributes().Where(a => a.Name.LocalName != "Id").ToList())
1000 + {
1001 + attrib.Remove();
1002 + }
1003 + }
1004 }
1005
1006 private void ConvertFeatureElement(XElement element)
@@ -2254,6 +2305,16 @@ namespace WixToolset.Converters
2305 /// The SoftwareTag element's Type attribute is obsolete.
2306 /// </summary>
2307 SoftwareTagTypeObsolete,
2308 +
2309 + /// <summary>
2310 + /// TARGETDIR directory should not longer be explicitly defined.
2311 + /// </summary>
2312 + TargetDirDeprecated,
2313 +
2314 + /// <summary>
2315 + /// Standard directories should no longer be defined using the Directory element.
2316 + /// </summary>
2317 + DefiningStandardDirectoryDeprecated,
2318 }
2319 }
2320 }
src/test/WixToolsetTest.Converters/DirectoryFixture.cs new
+92
@@ -0,0 +1,92 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolsetTest.Converters
4 +{
5 + using System;
6 + using System.Xml.Linq;
7 + using WixBuildTools.TestSupport;
8 + using WixToolset.Converters;
9 + using WixToolsetTest.Converters.Mocks;
10 + using Xunit;
11 +
12 + public class DirectoryFixture : BaseConverterFixture
13 + {
14 + [Fact]
15 + public void RemoveTargetDir()
16 + {
17 + var parse = String.Join(Environment.NewLine,
18 + "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
19 + "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
20 + " <Fragment>",
21 + " <Directory Id='TARGETDIR' Name='SourceDir'>",
22 + " <!-- Comment -->",
23 + " <Directory Id='RootFolder' Name='Root'>",
24 + " <Directory Id='ChildFolder' Name='Child' />",
25 + " </Directory>",
26 + " </Directory>",
27 + " </Fragment>",
28 + "</Wix>");
29 +
30 + var expected = new[]
31 + {
32 + "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
33 + " <Fragment>",
34 + " <!-- Comment -->",
35 + " <Directory Id=\"RootFolder\" Name=\"Root\">",
36 + " <Directory Id=\"ChildFolder\" Name=\"Child\" />",
37 + " </Directory>",
38 + " </Fragment>",
39 + "</Wix>"
40 + };
41 +
42 + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
43 +
44 + var messaging = new MockMessaging();
45 + var converter = new WixConverter(messaging, 2, null, null);
46 +
47 + var errors = converter.ConvertDocument(document);
48 + Assert.Equal(3, errors);
49 +
50 + var actualLines = UnformattedDocumentLines(document);
51 + WixAssert.CompareLineByLine(expected, actualLines);
52 + }
53 +
54 + [Fact]
55 + public void FixStandardDirectory()
56 + {
57 + var parse = String.Join(Environment.NewLine,
58 + "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
59 + "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
60 + " <Fragment>",
61 + " <Directory Id='TARGETDIR' Name='SourceDir'>",
62 + " <Directory Id='ProgramFilesFolder' Name='PFiles'>",
63 + " <Directory Id='ChildFolder' Name='Child' />",
64 + " </Directory>",
65 + " </Directory>",
66 + " </Fragment>",
67 + "</Wix>");
68 +
69 + var expected = new[]
70 + {
71 + "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
72 + " <Fragment>",
73 + " <StandardDirectory Id=\"ProgramFilesFolder\">",
74 + " <Directory Id=\"ChildFolder\" Name=\"Child\" />",
75 + " </StandardDirectory>",
76 + " </Fragment>",
77 + "</Wix>"
78 + };
79 +
80 + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
81 +
82 + var messaging = new MockMessaging();
83 + var converter = new WixConverter(messaging, 2, null, null);
84 +
85 + var errors = converter.ConvertDocument(document);
86 + Assert.Equal(4, errors);
87 +
88 + var actualLines = UnformattedDocumentLines(document);
89 + WixAssert.CompareLineByLine(expected, actualLines);
90 + }
91 + }
92 +}