aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2019-05-15 16:21:14 -0700
committerRob Mensching <rob@firegiant.com>2019-10-20 01:06:43 -0700
commit70d459c39d1716b2d26ffcbd2c4037d646b9ec37 (patch)
tree2c04b4940d64b99bea85cf00823a66697d344301
parent14fdc9113bdc7270fb33e06990081988eb099ba9 (diff)
downloadwix-70d459c39d1716b2d26ffcbd2c4037d646b9ec37.tar.gz
wix-70d459c39d1716b2d26ffcbd2c4037d646b9ec37.tar.bz2
wix-70d459c39d1716b2d26ffcbd2c4037d646b9ec37.zip
Extract common converters code to Converters repo and use that instead
-rw-r--r--nuget.config1
-rw-r--r--src/test/WixToolsetTest.WixCop/ConverterFixture.cs554
-rw-r--r--src/wixcop/CommandLine/ConvertCommand.cs5
-rw-r--r--src/wixcop/Converter.cs629
-rw-r--r--src/wixcop/WixCop.csproj2
5 files changed, 5 insertions, 1186 deletions
diff --git a/nuget.config b/nuget.config
index e8a0cc92..3fb7b617 100644
--- a/nuget.config
+++ b/nuget.config
@@ -2,6 +2,7 @@
2<configuration> 2<configuration>
3 <packageSources> 3 <packageSources>
4 <clear /> 4 <clear />
5 <add key="wixtoolset-converters" value="https://ci.appveyor.com/nuget/wixtoolset-converters" />
5 <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" /> 6 <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" />
6 <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" /> 7 <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" />
7 <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" /> 8 <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" />
diff --git a/src/test/WixToolsetTest.WixCop/ConverterFixture.cs b/src/test/WixToolsetTest.WixCop/ConverterFixture.cs
deleted file mode 100644
index ceac07d6..00000000
--- a/src/test/WixToolsetTest.WixCop/ConverterFixture.cs
+++ /dev/null
@@ -1,554 +0,0 @@
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
3namespace WixToolsetTest.WixCop
4{
5 using System;
6 using System.IO;
7 using System.Text;
8 using System.Xml.Linq;
9 using WixToolset.Data;
10 using WixToolset.Extensibility;
11 using WixToolset.Extensibility.Services;
12 using WixToolset.Tools.WixCop;
13 using Xunit;
14
15 public class ConverterFixture
16 {
17 private static readonly XNamespace Wix4Namespace = "http://wixtoolset.org/schemas/v4/wxs";
18
19 [Fact]
20 public void EnsuresDeclaration()
21 {
22 var parse = String.Join(Environment.NewLine,
23 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
24 " <Fragment />",
25 "</Wix>");
26
27 var expected = String.Join(Environment.NewLine,
28 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
29 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
30 " <Fragment />",
31 "</Wix>");
32
33 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
34
35 var messaging = new DummyMessaging();
36 var converter = new Converter(messaging, 2, null, null);
37
38 var errors = converter.ConvertDocument(document);
39
40 var actual = UnformattedDocumentString(document);
41
42 Assert.Equal(1, errors);
43 Assert.Equal(expected, actual);
44 }
45
46 [Fact]
47 public void EnsuresUtf8Declaration()
48 {
49 var parse = String.Join(Environment.NewLine,
50 "<?xml version='1.0'?>",
51 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
52 " <Fragment />",
53 "</Wix>");
54
55 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
56
57 var messaging = new DummyMessaging();
58 var converter = new Converter(messaging, 4, null, null);
59
60 var errors = converter.ConvertDocument(document);
61
62 Assert.Equal(1, errors);
63 Assert.Equal("1.0", document.Declaration.Version);
64 Assert.Equal("utf-8", document.Declaration.Encoding);
65 }
66
67 [Fact]
68 public void CanFixWhitespace()
69 {
70 var parse = String.Join(Environment.NewLine,
71 "<?xml version='1.0' encoding='utf-8'?>",
72 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
73 " <Fragment>",
74 " <Property Id='Prop'",
75 " Value='Val'>",
76 " </Property>",
77 " </Fragment>",
78 "</Wix>");
79
80 var expected = String.Join(Environment.NewLine,
81 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
82 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
83 " <Fragment>",
84 " <Property Id=\"Prop\" Value=\"Val\" />",
85 " </Fragment>",
86 "</Wix>");
87
88 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
89
90 var messaging = new DummyMessaging();
91 var converter = new Converter(messaging, 4, null, null);
92
93 var errors = converter.ConvertDocument(document);
94
95 var actual = UnformattedDocumentString(document);
96
97 Assert.Equal(expected, actual);
98 Assert.Equal(4, errors);
99 }
100
101 [Fact]
102 public void CanPreserveNewLines()
103 {
104 var parse = String.Join(Environment.NewLine,
105 "<?xml version='1.0' encoding='utf-8'?>",
106 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
107 " <Fragment>",
108 "",
109 " <Property Id='Prop' Value='Val' />",
110 "",
111 " </Fragment>",
112 "</Wix>");
113
114 var expected = String.Join(Environment.NewLine,
115 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
116 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
117 " <Fragment>",
118 "",
119 " <Property Id=\"Prop\" Value=\"Val\" />",
120 "",
121 " </Fragment>",
122 "</Wix>");
123
124 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
125
126 var messaging = new DummyMessaging();
127 var converter = new Converter(messaging, 4, null, null);
128
129 var conversions = converter.ConvertDocument(document);
130
131 var actual = UnformattedDocumentString(document);
132
133 Assert.Equal(expected, actual);
134 Assert.Equal(3, conversions);
135 }
136
137 [Fact]
138 public void CanConvertWithNewLineAtEndOfFile()
139 {
140 var parse = String.Join(Environment.NewLine,
141 "<?xml version='1.0' encoding='utf-8'?>",
142 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
143 " <Fragment>",
144 "",
145 " <Property Id='Prop' Value='Val' />",
146 "",
147 " </Fragment>",
148 "</Wix>",
149 "");
150
151 var expected = String.Join(Environment.NewLine,
152 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
153 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
154 " <Fragment>",
155 "",
156 " <Property Id=\"Prop\" Value=\"Val\" />",
157 "",
158 " </Fragment>",
159 "</Wix>",
160 "");
161
162 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
163
164 var messaging = new DummyMessaging();
165 var converter = new Converter(messaging, 4, null, null);
166
167 var conversions = converter.ConvertDocument(document);
168
169 var actual = UnformattedDocumentString(document);
170
171 Assert.Equal(expected, actual);
172 Assert.Equal(3, conversions);
173 }
174
175 [Fact]
176 public void CanFixCdataWhitespace()
177 {
178 var parse = String.Join(Environment.NewLine,
179 "<?xml version='1.0' encoding='utf-8'?>",
180 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
181 " <Fragment>",
182 " <Property Id='Prop'>",
183 " <![CDATA[1<2]]>",
184 " </Property>",
185 " </Fragment>",
186 "</Wix>");
187
188 var expected = String.Join(Environment.NewLine,
189 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
190 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
191 " <Fragment>",
192 " <Property Id=\"Prop\"><![CDATA[1<2]]></Property>",
193 " </Fragment>",
194 "</Wix>");
195
196 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
197
198 var messaging = new DummyMessaging();
199 var converter = new Converter(messaging, 2, null, null);
200
201 var errors = converter.ConvertDocument(document);
202
203 var actual = UnformattedDocumentString(document);
204
205 Assert.Equal(expected, actual);
206 Assert.Equal(2, errors);
207 }
208
209 [Fact]
210 public void CanFixCdataWithWhitespace()
211 {
212 var parse = String.Join(Environment.NewLine,
213 "<?xml version='1.0' encoding='utf-8'?>",
214 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
215 " <Fragment>",
216 " <Property Id='Prop'>",
217 " <![CDATA[",
218 " 1<2",
219 " ]]>",
220 " </Property>",
221 " </Fragment>",
222 "</Wix>");
223
224 var expected = String.Join(Environment.NewLine,
225 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
226 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
227 " <Fragment>",
228 " <Property Id=\"Prop\"><![CDATA[1<2]]></Property>",
229 " </Fragment>",
230 "</Wix>");
231
232 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
233
234 var messaging = new DummyMessaging();
235 var converter = new Converter(messaging, 2, null, null);
236
237 var errors = converter.ConvertDocument(document);
238
239 var actual = UnformattedDocumentString(document);
240
241 Assert.Equal(expected, actual);
242 Assert.Equal(2, errors);
243 }
244
245 [Fact]
246 public void CanConvertMainNamespace()
247 {
248 var parse = String.Join(Environment.NewLine,
249 "<?xml version='1.0' encoding='utf-8'?>",
250 "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
251 " <Fragment />",
252 "</Wix>");
253
254 var expected = String.Join(Environment.NewLine,
255 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
256 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
257 " <Fragment />",
258 "</Wix>");
259
260 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
261
262 var messaging = new DummyMessaging();
263 var converter = new Converter(messaging, 2, null, null);
264
265 var errors = converter.ConvertDocument(document);
266
267 var actual = UnformattedDocumentString(document);
268
269 Assert.Equal(1, errors);
270 //Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace());
271 Assert.Equal(expected, actual);
272 }
273
274 [Fact]
275 public void CanConvertNamedMainNamespace()
276 {
277 var parse = String.Join(Environment.NewLine,
278 "<?xml version='1.0' encoding='utf-8'?>",
279 "<w:Wix xmlns:w='http://schemas.microsoft.com/wix/2006/wi'>",
280 " <w:Fragment />",
281 "</w:Wix>");
282
283 var expected = String.Join(Environment.NewLine,
284 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
285 "<w:Wix xmlns:w=\"http://wixtoolset.org/schemas/v4/wxs\">",
286 " <w:Fragment />",
287 "</w:Wix>");
288
289 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
290
291 var messaging = new DummyMessaging();
292 var converter = new Converter(messaging, 2, null, null);
293
294 var errors = converter.ConvertDocument(document);
295
296 var actual = UnformattedDocumentString(document);
297
298 Assert.Equal(1, errors);
299 Assert.Equal(expected, actual);
300 Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w"));
301 }
302
303 [Fact]
304 public void CanConvertNonWixDefaultNamespace()
305 {
306 var parse = String.Join(Environment.NewLine,
307 "<?xml version='1.0' encoding='utf-8'?>",
308 "<w:Wix xmlns:w='http://schemas.microsoft.com/wix/2006/wi' xmlns='http://schemas.microsoft.com/wix/UtilExtension'>",
309 " <w:Fragment>",
310 " <Test />",
311 " </w:Fragment>",
312 "</w:Wix>");
313
314 var expected = String.Join(Environment.NewLine,
315 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
316 "<w:Wix xmlns:w=\"http://wixtoolset.org/schemas/v4/wxs\" xmlns=\"http://wixtoolset.org/schemas/v4/wxs/util\">",
317 " <w:Fragment>",
318 " <Test />",
319 " </w:Fragment>",
320 "</w:Wix>");
321
322 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
323
324 var messaging = new DummyMessaging();
325 var converter = new Converter(messaging, 2, null, null);
326
327 var errors = converter.ConvertDocument(document);
328
329 var actual = UnformattedDocumentString(document);
330
331 Assert.Equal(expected, actual);
332 Assert.Equal(2, errors);
333 Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w"));
334 Assert.Equal("http://wixtoolset.org/schemas/v4/wxs/util", document.Root.GetDefaultNamespace());
335 }
336
337 [Fact]
338 public void CanConvertExtensionNamespace()
339 {
340 var parse = String.Join(Environment.NewLine,
341 "<?xml version='1.0' encoding='utf-8'?>",
342 "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi' xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>",
343 " <Fragment />",
344 "</Wix>");
345
346 var expected = String.Join(Environment.NewLine,
347 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
348 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\" xmlns:util=\"http://wixtoolset.org/schemas/v4/wxs/util\">",
349 " <Fragment />",
350 "</Wix>");
351
352 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
353
354 var messaging = new DummyMessaging();
355 var converter = new Converter(messaging, 2, null, null);
356
357 var errors = converter.ConvertDocument(document);
358
359 var actual = UnformattedDocumentString(document);
360
361 Assert.Equal(2, errors);
362 Assert.Equal(expected, actual);
363 Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace());
364 }
365
366 [Fact]
367 public void CanConvertMissingNamespace()
368 {
369 var parse = String.Join(Environment.NewLine,
370 "<?xml version='1.0' encoding='utf-8'?>",
371 "<Wix>",
372 " <Fragment />",
373 "</Wix>");
374
375 var expected = String.Join(Environment.NewLine,
376 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
377 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
378 " <Fragment />",
379 "</Wix>");
380
381 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
382
383 var messaging = new DummyMessaging();
384 var converter = new Converter(messaging, 2, null, null);
385
386 var errors = converter.ConvertDocument(document);
387
388 var actual = UnformattedDocumentString(document);
389
390 Assert.Equal(1, errors);
391 Assert.Equal(expected, actual);
392 Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace());
393 }
394
395 [Fact]
396 public void CanConvertAnonymousFile()
397 {
398 var parse = String.Join(Environment.NewLine,
399 "<?xml version='1.0' encoding='utf-8'?>",
400 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
401 " <File Source='path\\to\\foo.txt' />",
402 "</Wix>");
403
404 var expected = String.Join(Environment.NewLine,
405 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
406 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
407 " <File Id=\"foo.txt\" Source=\"path\\to\\foo.txt\" />",
408 "</Wix>");
409
410 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
411
412 var messaging = new DummyMessaging();
413 var converter = new Converter(messaging, 2, null, null);
414
415 var errors = converter.ConvertDocument(document);
416
417 var actual = UnformattedDocumentString(document);
418
419 Assert.Equal(1, errors);
420 Assert.Equal(expected, actual);
421 }
422
423 [Fact]
424 public void CanConvertShortNameDirectoryWithoutName()
425 {
426 var parse = String.Join(Environment.NewLine,
427 "<?xml version='1.0' encoding='utf-8'?>",
428 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
429 " <Directory ShortName='iamshort' />",
430 "</Wix>");
431
432 var expected = String.Join(Environment.NewLine,
433 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
434 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
435 " <Directory Name=\"iamshort\" />",
436 "</Wix>");
437
438 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
439
440 var messaging = new DummyMessaging();
441 var converter = new Converter(messaging, 2, null, null);
442
443 var errors = converter.ConvertDocument(document);
444
445 var actual = UnformattedDocumentString(document);
446
447 Assert.Equal(1, errors);
448 Assert.Equal(expected, actual);
449 }
450
451 [Fact]
452 public void CanConvertSuppressSignatureValidationNo()
453 {
454 var parse = String.Join(Environment.NewLine,
455 "<?xml version='1.0' encoding='utf-8'?>",
456 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
457 " <MsiPackage SuppressSignatureValidation='no' />",
458 "</Wix>");
459
460 var expected = String.Join(Environment.NewLine,
461 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
462 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
463 " <MsiPackage EnableSignatureValidation=\"yes\" />",
464 "</Wix>");
465
466 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
467
468 var messaging = new DummyMessaging();
469 var converter = new Converter(messaging, 2, null, null);
470
471 var errors = converter.ConvertDocument(document);
472
473 var actual = UnformattedDocumentString(document);
474
475 Assert.Equal(1, errors);
476 Assert.Equal(expected, actual);
477 }
478
479 [Fact]
480 public void CanConvertSuppressSignatureValidationYes()
481 {
482 var parse = String.Join(Environment.NewLine,
483 "<?xml version='1.0' encoding='utf-8'?>",
484 "<Wix xmlns='http://wixtoolset.org/schemas/v4/wxs'>",
485 " <Payload SuppressSignatureValidation='yes' />",
486 "</Wix>");
487
488 var expected = String.Join(Environment.NewLine,
489 "<?xml version=\"1.0\" encoding=\"utf-16\"?>",
490 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
491 " <Payload />",
492 "</Wix>");
493
494 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
495
496 var messaging = new DummyMessaging();
497 var converter = new Converter(messaging, 2, null, null);
498
499 var errors = converter.ConvertDocument(document);
500
501 var actual = UnformattedDocumentString(document);
502
503 Assert.Equal(1, errors);
504 Assert.Equal(expected, actual);
505 }
506
507 private static string UnformattedDocumentString(XDocument document)
508 {
509 var sb = new StringBuilder();
510
511 using (var writer = new StringWriter(sb))
512 {
513 document.Save(writer, SaveOptions.DisableFormatting);
514 }
515
516 return sb.ToString();
517 }
518
519 private class DummyMessaging : IMessaging
520 {
521 public bool EncounteredError { get; set; }
522
523 public int LastErrorNumber { get; set; }
524
525 public bool ShowVerboseMessages { get; set; }
526
527 public bool SuppressAllWarnings { get; set; }
528
529 public bool WarningsAsError { get; set; }
530
531 public void ElevateWarningMessage(int warningNumber)
532 {
533 }
534
535 public string FormatMessage(Message message) => String.Empty;
536
537 public void SetListener(IMessageListener listener)
538 {
539 }
540
541 public void SuppressWarningMessage(int warningNumber)
542 {
543 }
544
545 public void Write(Message message)
546 {
547 }
548
549 public void Write(string message, bool verbose = false)
550 {
551 }
552 }
553 }
554}
diff --git a/src/wixcop/CommandLine/ConvertCommand.cs b/src/wixcop/CommandLine/ConvertCommand.cs
index c65652ab..a9a110fe 100644
--- a/src/wixcop/CommandLine/ConvertCommand.cs
+++ b/src/wixcop/CommandLine/ConvertCommand.cs
@@ -6,6 +6,7 @@ namespace WixToolset.Tools.WixCop.CommandLine
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.IO; 7 using System.IO;
8 using System.Xml; 8 using System.Xml;
9 using WixToolset.Converters;
9 using WixToolset.Extensibility.Data; 10 using WixToolset.Extensibility.Data;
10 using WixToolset.Extensibility.Services; 11 using WixToolset.Extensibility.Services;
11 12
@@ -75,7 +76,7 @@ namespace WixToolset.Tools.WixCop.CommandLine
75 } 76 }
76 77
77 var messaging = this.ServiceProvider.GetService<IMessaging>(); 78 var messaging = this.ServiceProvider.GetService<IMessaging>();
78 var converter = new Converter(messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); 79 var converter = new Wix3Converter(messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors);
79 80
80 var errors = this.InspectSubDirectories(converter, Path.GetFullPath(".")); 81 var errors = this.InspectSubDirectories(converter, Path.GetFullPath("."));
81 82
@@ -131,7 +132,7 @@ namespace WixToolset.Tools.WixCop.CommandLine
131 /// </summary> 132 /// </summary>
132 /// <param name="directory">The directory whose sub-directories will be inspected.</param> 133 /// <param name="directory">The directory whose sub-directories will be inspected.</param>
133 /// <returns>The number of errors that were found.</returns> 134 /// <returns>The number of errors that were found.</returns>
134 private int InspectSubDirectories(Converter converter, string directory) 135 private int InspectSubDirectories(Wix3Converter converter, string directory)
135 { 136 {
136 var errors = 0; 137 var errors = 0;
137 138
diff --git a/src/wixcop/Converter.cs b/src/wixcop/Converter.cs
deleted file mode 100644
index 37016c19..00000000
--- a/src/wixcop/Converter.cs
+++ /dev/null
@@ -1,629 +0,0 @@
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
3namespace WixToolset.Tools.WixCop
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.IO;
9 using System.Linq;
10 using System.Text;
11 using System.Xml;
12 using System.Xml.Linq;
13 using WixToolset.Data;
14 using WixToolset.Extensibility.Services;
15 using WixToolset.Tools.Core;
16
17 /// <summary>
18 /// WiX source code converter.
19 /// </summary>
20 public class Converter
21 {
22 private const char XDocumentNewLine = '\n'; // XDocument normalizes "\r\n" to just "\n".
23 private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs";
24
25 private static readonly XName DirectoryElementName = WixNamespace + "Directory";
26 private static readonly XName FileElementName = WixNamespace + "File";
27 private static readonly XName ExePackageElementName = WixNamespace + "ExePackage";
28 private static readonly XName MsiPackageElementName = WixNamespace + "MsiPackage";
29 private static readonly XName MspPackageElementName = WixNamespace + "MspPackage";
30 private static readonly XName MsuPackageElementName = WixNamespace + "MsuPackage";
31 private static readonly XName PayloadElementName = WixNamespace + "Payload";
32 private static readonly XName CustomActionElementName = WixNamespace + "CustomAction";
33 private static readonly XName PropertyElementName = WixNamespace + "Property";
34 private static readonly XName WixElementWithoutNamespaceName = XNamespace.None + "Wix";
35
36 private static readonly Dictionary<string, XNamespace> OldToNewNamespaceMapping = new Dictionary<string, XNamespace>()
37 {
38 { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" },
39 { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" },
40 { "http://schemas.microsoft.com/wix/DependencyExtension", "http://wixtoolset.org/schemas/v4/wxs/dependency" },
41 { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" },
42 { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" },
43 { "http://schemas.microsoft.com/wix/GamingExtension", "http://wixtoolset.org/schemas/v4/wxs/gaming" },
44 { "http://schemas.microsoft.com/wix/IIsExtension", "http://wixtoolset.org/schemas/v4/wxs/iis" },
45 { "http://schemas.microsoft.com/wix/MsmqExtension", "http://wixtoolset.org/schemas/v4/wxs/msmq" },
46 { "http://schemas.microsoft.com/wix/NetFxExtension", "http://wixtoolset.org/schemas/v4/wxs/netfx" },
47 { "http://schemas.microsoft.com/wix/PSExtension", "http://wixtoolset.org/schemas/v4/wxs/powershell" },
48 { "http://schemas.microsoft.com/wix/SqlExtension", "http://wixtoolset.org/schemas/v4/wxs/sql" },
49 { "http://schemas.microsoft.com/wix/TagExtension", "http://wixtoolset.org/schemas/v4/wxs/tag" },
50 { "http://schemas.microsoft.com/wix/UtilExtension", "http://wixtoolset.org/schemas/v4/wxs/util" },
51 { "http://schemas.microsoft.com/wix/VSExtension", "http://wixtoolset.org/schemas/v4/wxs/vs" },
52 { "http://wixtoolset.org/schemas/thmutil/2010", "http://wixtoolset.org/schemas/v4/thmutil" },
53 { "http://schemas.microsoft.com/wix/2009/Lux", "http://wixtoolset.org/schemas/v4/lux" },
54 { "http://schemas.microsoft.com/wix/2006/wi", "http://wixtoolset.org/schemas/v4/wxs" },
55 { "http://schemas.microsoft.com/wix/2006/localization", "http://wixtoolset.org/schemas/v4/wxl" },
56 { "http://schemas.microsoft.com/wix/2006/libraries", "http://wixtoolset.org/schemas/v4/wixlib" },
57 { "http://schemas.microsoft.com/wix/2006/objects", "http://wixtoolset.org/schemas/v4/wixobj" },
58 { "http://schemas.microsoft.com/wix/2006/outputs", "http://wixtoolset.org/schemas/v4/wixout" },
59 { "http://schemas.microsoft.com/wix/2007/pdbs", "http://wixtoolset.org/schemas/v4/wixpdb" },
60 { "http://schemas.microsoft.com/wix/2003/04/actions", "http://wixtoolset.org/schemas/v4/wi/actions" },
61 { "http://schemas.microsoft.com/wix/2006/tables", "http://wixtoolset.org/schemas/v4/wi/tables" },
62 { "http://schemas.microsoft.com/wix/2006/WixUnit", "http://wixtoolset.org/schemas/v4/wixunit" },
63 };
64
65 private readonly Dictionary<XName, Action<XElement>> ConvertElementMapping;
66
67 /// <summary>
68 /// Instantiate a new Converter class.
69 /// </summary>
70 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
71 /// <param name="errorsAsWarnings">Test errors to display as warnings.</param>
72 /// <param name="ignoreErrors">Test errors to ignore.</param>
73 public Converter(IMessaging messaging, int indentationAmount, IEnumerable<string> errorsAsWarnings = null, IEnumerable<string> ignoreErrors = null)
74 {
75 this.ConvertElementMapping = new Dictionary<XName, Action<XElement>>
76 {
77 { Converter.DirectoryElementName, this.ConvertDirectoryElement },
78 { Converter.FileElementName, this.ConvertFileElement },
79 { Converter.ExePackageElementName, this.ConvertSuppressSignatureValidation },
80 { Converter.MsiPackageElementName, this.ConvertSuppressSignatureValidation },
81 { Converter.MspPackageElementName, this.ConvertSuppressSignatureValidation },
82 { Converter.MsuPackageElementName, this.ConvertSuppressSignatureValidation },
83 { Converter.PayloadElementName, this.ConvertSuppressSignatureValidation },
84 { Converter.CustomActionElementName, this.ConvertCustomActionElement },
85 { Converter.PropertyElementName, this.ConvertPropertyElement },
86 { Converter.WixElementWithoutNamespaceName, this.ConvertWixElementWithoutNamespace },
87 };
88
89 this.Messaging = messaging;
90
91 this.IndentationAmount = indentationAmount;
92
93 this.ErrorsAsWarnings = new HashSet<ConverterTestType>(this.YieldConverterTypes(errorsAsWarnings));
94
95 this.IgnoreErrors = new HashSet<ConverterTestType>(this.YieldConverterTypes(ignoreErrors));
96 }
97
98 private int Errors { get; set; }
99
100 private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; }
101
102 private HashSet<ConverterTestType> IgnoreErrors { get; set; }
103
104 private IMessaging Messaging { get; }
105
106 private int IndentationAmount { get; set; }
107
108 private string SourceFile { get; set; }
109
110 /// <summary>
111 /// Convert a file.
112 /// </summary>
113 /// <param name="sourceFile">The file to convert.</param>
114 /// <param name="saveConvertedFile">Option to save the converted errors that are found.</param>
115 /// <returns>The number of errors found.</returns>
116 public int ConvertFile(string sourceFile, bool saveConvertedFile)
117 {
118 XDocument document;
119
120 // Set the instance info.
121 this.Errors = 0;
122 this.SourceFile = sourceFile;
123
124 try
125 {
126 document = XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
127 }
128 catch (XmlException e)
129 {
130 this.OnError(ConverterTestType.XmlException, null, "The xml is invalid. Detail: '{0}'", e.Message);
131
132 return this.Errors;
133 }
134
135 this.ConvertDocument(document);
136
137 // Fix errors if requested and necessary.
138 if (saveConvertedFile && 0 < this.Errors)
139 {
140 try
141 {
142 using (var writer = File.CreateText(this.SourceFile))
143 {
144 document.Save(writer, SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces);
145 }
146 }
147 catch (UnauthorizedAccessException)
148 {
149 this.OnError(ConverterTestType.UnauthorizedAccessException, null, "Could not write to file.");
150 }
151 }
152
153 return this.Errors;
154 }
155
156 /// <summary>
157 /// Convert a document.
158 /// </summary>
159 /// <param name="document">The document to convert.</param>
160 /// <returns>The number of errors found.</returns>
161 public int ConvertDocument(XDocument document)
162 {
163 var declaration = document.Declaration;
164
165 // Convert the declaration.
166 if (null != declaration)
167 {
168 if (!String.Equals("utf-8", declaration.Encoding, StringComparison.OrdinalIgnoreCase))
169 {
170 if (this.OnError(ConverterTestType.DeclarationEncodingWrong, document.Root, "The XML declaration encoding is not properly set to 'utf-8'."))
171 {
172 declaration.Encoding = "utf-8";
173 }
174 }
175 }
176 else // missing declaration
177 {
178 if (this.OnError(ConverterTestType.DeclarationMissing, null, "This file is missing an XML declaration on the first line."))
179 {
180 document.Declaration = new XDeclaration("1.0", "utf-8", null);
181 document.Root.AddBeforeSelf(new XText(XDocumentNewLine.ToString()));
182 }
183 }
184
185 // Start converting the nodes at the top.
186 this.ConvertNodes(document.Nodes(), 0);
187
188 return this.Errors;
189 }
190
191 private void ConvertNodes(IEnumerable<XNode> nodes, int level)
192 {
193 // Note we operate on a copy of the node list since we may
194 // remove some whitespace nodes during this processing.
195 foreach (var node in nodes.ToList())
196 {
197 if (node is XText text)
198 {
199 if (!String.IsNullOrWhiteSpace(text.Value))
200 {
201 text.Value = text.Value.Trim();
202 }
203 else if (node.NextNode is XCData cdata)
204 {
205 this.EnsurePrecedingWhitespaceRemoved(text, node, ConverterTestType.WhitespacePrecedingNodeWrong);
206 }
207 else if (node.NextNode is XElement element)
208 {
209 this.EnsurePrecedingWhitespaceCorrect(text, node, level, ConverterTestType.WhitespacePrecedingNodeWrong);
210 }
211 else if (node.NextNode is null) // this is the space before the close element
212 {
213 if (node.PreviousNode is null || node.PreviousNode is XCData)
214 {
215 this.EnsurePrecedingWhitespaceRemoved(text, node.Parent, ConverterTestType.WhitespacePrecedingEndElementWrong);
216 }
217 else if (level == 0) // root element's close tag
218 {
219 this.EnsurePrecedingWhitespaceCorrect(text, node, 0, ConverterTestType.WhitespacePrecedingEndElementWrong);
220 }
221 else
222 {
223 this.EnsurePrecedingWhitespaceCorrect(text, node, level - 1, ConverterTestType.WhitespacePrecedingEndElementWrong);
224 }
225 }
226 }
227 else if (node is XElement element)
228 {
229 this.ConvertElement(element);
230
231 this.ConvertNodes(element.Nodes(), level + 1);
232 }
233 }
234 }
235
236 private void EnsurePrecedingWhitespaceCorrect(XText whitespace, XNode node, int level, ConverterTestType testType)
237 {
238 if (!Converter.LeadingWhitespaceValid(this.IndentationAmount, level, whitespace.Value))
239 {
240 var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect.";
241
242 if (this.OnError(testType, node, message))
243 {
244 Converter.FixupWhitespace(this.IndentationAmount, level, whitespace);
245 }
246 }
247 }
248
249 private void EnsurePrecedingWhitespaceRemoved(XText whitespace, XNode node, ConverterTestType testType)
250 {
251 if (!String.IsNullOrEmpty(whitespace.Value))
252 {
253 var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect.";
254
255 if (this.OnError(testType, node, message))
256 {
257 whitespace.Remove();
258 }
259 }
260 }
261
262 private void ConvertElement(XElement element)
263 {
264 // Gather any deprecated namespaces, then update this element tree based on those deprecations.
265 var deprecatedToUpdatedNamespaces = new Dictionary<XNamespace, XNamespace>();
266
267 foreach (var declaration in element.Attributes().Where(a => a.IsNamespaceDeclaration))
268 {
269 if (Converter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out var ns))
270 {
271 if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName))
272 {
273 deprecatedToUpdatedNamespaces.Add(declaration.Value, ns);
274 }
275 }
276 }
277
278 if (deprecatedToUpdatedNamespaces.Any())
279 {
280 Converter.UpdateElementsWithDeprecatedNamespaces(element.DescendantsAndSelf(), deprecatedToUpdatedNamespaces);
281 }
282
283 // Apply any specialized conversion actions.
284 if (this.ConvertElementMapping.TryGetValue(element.Name, out var convert))
285 {
286 convert(element);
287 }
288 }
289
290 private void ConvertDirectoryElement(XElement element)
291 {
292 if (null == element.Attribute("Name"))
293 {
294 var attribute = element.Attribute("ShortName");
295 if (null != attribute)
296 {
297 var shortName = attribute.Value;
298 if (this.OnError(ConverterTestType.AssignDirectoryNameFromShortName, element, "The directory ShortName attribute is being renamed to Name since Name wasn't specified for value '{0}'", shortName))
299 {
300 element.Add(new XAttribute("Name", shortName));
301 attribute.Remove();
302 }
303 }
304 }
305 }
306
307 private void ConvertFileElement(XElement element)
308 {
309 if (null == element.Attribute("Id"))
310 {
311 var attribute = element.Attribute("Name");
312
313 if (null == attribute)
314 {
315 attribute = element.Attribute("Source");
316 }
317
318 if (null != attribute)
319 {
320 var name = Path.GetFileName(attribute.Value);
321
322 if (this.OnError(ConverterTestType.AssignAnonymousFileId, element, "The file id is being updated to '{0}' to ensure it remains the same as the default", name))
323 {
324 IEnumerable<XAttribute> attributes = element.Attributes().ToList();
325 element.RemoveAttributes();
326 element.Add(new XAttribute("Id", ToolsCommon.GetIdentifierFromName(name)));
327 element.Add(attributes);
328 }
329 }
330 }
331 }
332
333 private void ConvertSuppressSignatureValidation(XElement element)
334 {
335 var suppressSignatureValidation = element.Attribute("SuppressSignatureValidation");
336
337 if (null != suppressSignatureValidation)
338 {
339 if (this.OnError(ConverterTestType.SuppressSignatureValidationDeprecated, element, "The chain package element contains deprecated '{0}' attribute. Use the 'EnableSignatureValidation' attribute instead.", suppressSignatureValidation))
340 {
341 if ("no" == suppressSignatureValidation.Value)
342 {
343 element.Add(new XAttribute("EnableSignatureValidation", "yes"));
344 }
345 }
346
347 suppressSignatureValidation.Remove();
348 }
349 }
350
351 private void ConvertCustomActionElement(XElement xCustomAction)
352 {
353 var xBinaryKey = xCustomAction.Attribute("BinaryKey");
354
355 if (xBinaryKey?.Value == "WixCA")
356 {
357 if (this.OnError(ConverterTestType.WixCABinaryIdRenamed, xCustomAction, "The WixCA custom action DLL Binary table id has been renamed. Use the id 'UtilCA' instead."))
358 {
359 xBinaryKey.Value = "UtilCA";
360 }
361 }
362
363 var xDllEntry = xCustomAction.Attribute("DllEntry");
364
365 if (xDllEntry?.Value == "CAQuietExec" || xDllEntry?.Value == "CAQuietExec64")
366 {
367 if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The CAQuietExec and CAQuietExec64 custom action ids have been renamed. Use the ids 'WixQuietExec' and 'WixQuietExec64' instead."))
368 {
369 xDllEntry.Value = xDllEntry.Value.Replace("CAQuietExec", "WixQuietExec");
370 }
371 }
372
373 var xProperty = xCustomAction.Attribute("Property");
374
375 if (xProperty?.Value == "QtExecCmdLine" || xProperty?.Value == "QtExec64CmdLine")
376 {
377 if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The QtExecCmdLine and QtExec64CmdLine property ids have been renamed. Use the ids 'WixQuietExecCmdLine' and 'WixQuietExec64CmdLine' instead."))
378 {
379 xProperty.Value = xProperty.Value.Replace("QtExec", "WixQuietExec");
380 }
381 }
382 }
383
384 private void ConvertPropertyElement(XElement xProperty)
385 {
386 var xId = xProperty.Attribute("Id");
387
388 if (xId.Value == "QtExecCmdTimeout")
389 {
390 this.OnError(ConverterTestType.QtExecCmdTimeoutAmbiguous, xProperty, "QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout.");
391 }
392 }
393
394 /// <summary>
395 /// Converts a Wix element.
396 /// </summary>
397 /// <param name="element">The Wix element to convert.</param>
398 /// <returns>The converted element.</returns>
399 private void ConvertWixElementWithoutNamespace(XElement element)
400 {
401 if (this.OnError(ConverterTestType.XmlnsMissing, element, "The xmlns attribute is missing. It must be present with a value of '{0}'.", WixNamespace.NamespaceName))
402 {
403 element.Name = WixNamespace.GetName(element.Name.LocalName);
404
405 element.Add(new XAttribute("xmlns", WixNamespace.NamespaceName)); // set the default namespace.
406
407 foreach (var elementWithoutNamespace in element.Elements().Where(e => XNamespace.None == e.Name.Namespace))
408 {
409 elementWithoutNamespace.Name = WixNamespace.GetName(elementWithoutNamespace.Name.LocalName);
410 }
411 }
412 }
413
414 private IEnumerable<ConverterTestType> YieldConverterTypes(IEnumerable<string> types)
415 {
416 if (null != types)
417 {
418 foreach (var type in types)
419 {
420
421 if (Enum.TryParse<ConverterTestType>(type, true, out var itt))
422 {
423 yield return itt;
424 }
425 else // not a known ConverterTestType
426 {
427 this.OnError(ConverterTestType.ConverterTestTypeUnknown, null, "Unknown error type: '{0}'.", type);
428 }
429 }
430 }
431 }
432
433 private static void UpdateElementsWithDeprecatedNamespaces(IEnumerable<XElement> elements, Dictionary<XNamespace, XNamespace> deprecatedToUpdatedNamespaces)
434 {
435 foreach (var element in elements)
436 {
437
438 if (deprecatedToUpdatedNamespaces.TryGetValue(element.Name.Namespace, out var ns))
439 {
440 element.Name = ns.GetName(element.Name.LocalName);
441 }
442
443 // Remove all the attributes and add them back to with their namespace updated (as necessary).
444 IEnumerable<XAttribute> attributes = element.Attributes().ToList();
445 element.RemoveAttributes();
446
447 foreach (var attribute in attributes)
448 {
449 var convertedAttribute = attribute;
450
451 if (attribute.IsNamespaceDeclaration)
452 {
453 if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Value, out ns))
454 {
455 convertedAttribute = ("xmlns" == attribute.Name.LocalName) ? new XAttribute(attribute.Name.LocalName, ns.NamespaceName) : new XAttribute(XNamespace.Xmlns + attribute.Name.LocalName, ns.NamespaceName);
456 }
457 }
458 else if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Name.Namespace, out ns))
459 {
460 convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value);
461 }
462
463 element.Add(convertedAttribute);
464 }
465 }
466 }
467
468 /// <summary>
469 /// Determine if the whitespace preceding a node is appropriate for its depth level.
470 /// </summary>
471 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
472 /// <param name="level">The depth level that should match this whitespace.</param>
473 /// <param name="whitespace">The whitespace to validate.</param>
474 /// <returns>true if the whitespace is legal; false otherwise.</returns>
475 private static bool LeadingWhitespaceValid(int indentationAmount, int level, string whitespace)
476 {
477 // Strip off leading newlines; there can be an arbitrary number of these.
478 whitespace = whitespace.TrimStart(XDocumentNewLine);
479
480 var indentation = new string(' ', level * indentationAmount);
481
482 return whitespace == indentation;
483 }
484
485 /// <summary>
486 /// Fix the whitespace in a whitespace node.
487 /// </summary>
488 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
489 /// <param name="level">The depth level of the desired whitespace.</param>
490 /// <param name="whitespace">The whitespace node to fix.</param>
491 private static void FixupWhitespace(int indentationAmount, int level, XText whitespace)
492 {
493 var value = new StringBuilder(whitespace.Value.Length);
494
495 // Keep any previous preceeding new lines.
496 var newlines = whitespace.Value.TakeWhile(c => c == XDocumentNewLine).Count();
497
498 // Ensure there is always at least one new line before the indentation.
499 value.Append(XDocumentNewLine, newlines == 0 ? 1 : newlines);
500
501 whitespace.Value = value.Append(' ', level * indentationAmount).ToString();
502 }
503
504 /// <summary>
505 /// Output an error message to the console.
506 /// </summary>
507 /// <param name="converterTestType">The type of converter test.</param>
508 /// <param name="node">The node that caused the error.</param>
509 /// <param name="message">Detailed error message.</param>
510 /// <param name="args">Additional formatted string arguments.</param>
511 /// <returns>Returns true indicating that action should be taken on this error, and false if it should be ignored.</returns>
512 private bool OnError(ConverterTestType converterTestType, XObject node, string message, params object[] args)
513 {
514 if (this.IgnoreErrors.Contains(converterTestType)) // ignore the error
515 {
516 return false;
517 }
518
519 // Increase the error count.
520 this.Errors++;
521
522 var sourceLine = (null == node) ? new SourceLineNumber(this.SourceFile ?? "wixcop.exe") : new SourceLineNumber(this.SourceFile, ((IXmlLineInfo)node).LineNumber);
523 var warning = this.ErrorsAsWarnings.Contains(converterTestType);
524 var display = String.Format(CultureInfo.CurrentCulture, message, args);
525
526 var msg = new Message(sourceLine, warning ? MessageLevel.Warning : MessageLevel.Error, (int)converterTestType, "{0} ({1})", display, converterTestType.ToString());
527
528 this.Messaging.Write(msg);
529
530 return true;
531 }
532
533 /// <summary>
534 /// Converter test types. These are used to condition error messages down to warnings.
535 /// </summary>
536 private enum ConverterTestType
537 {
538 /// <summary>
539 /// Internal-only: displayed when a string cannot be converted to an ConverterTestType.
540 /// </summary>
541 ConverterTestTypeUnknown,
542
543 /// <summary>
544 /// Displayed when an XML loading exception has occurred.
545 /// </summary>
546 XmlException,
547
548 /// <summary>
549 /// Displayed when a file cannot be accessed; typically when trying to save back a fixed file.
550 /// </summary>
551 UnauthorizedAccessException,
552
553 /// <summary>
554 /// Displayed when the encoding attribute in the XML declaration is not 'UTF-8'.
555 /// </summary>
556 DeclarationEncodingWrong,
557
558 /// <summary>
559 /// Displayed when the XML declaration is missing from the source file.
560 /// </summary>
561 DeclarationMissing,
562
563 /// <summary>
564 /// Displayed when the whitespace preceding a CDATA node is wrong.
565 /// </summary>
566 WhitespacePrecedingCDATAWrong,
567
568 /// <summary>
569 /// Displayed when the whitespace preceding a node is wrong.
570 /// </summary>
571 WhitespacePrecedingNodeWrong,
572
573 /// <summary>
574 /// Displayed when an element is not empty as it should be.
575 /// </summary>
576 NotEmptyElement,
577
578 /// <summary>
579 /// Displayed when the whitespace following a CDATA node is wrong.
580 /// </summary>
581 WhitespaceFollowingCDATAWrong,
582
583 /// <summary>
584 /// Displayed when the whitespace preceding an end element is wrong.
585 /// </summary>
586 WhitespacePrecedingEndElementWrong,
587
588 /// <summary>
589 /// Displayed when the xmlns attribute is missing from the document element.
590 /// </summary>
591 XmlnsMissing,
592
593 /// <summary>
594 /// Displayed when the xmlns attribute on the document element is wrong.
595 /// </summary>
596 XmlnsValueWrong,
597
598 /// <summary>
599 /// Assign an identifier to a File element when on Id attribute is specified.
600 /// </summary>
601 AssignAnonymousFileId,
602
603 /// <summary>
604 /// SuppressSignatureValidation attribute is deprecated and replaced with EnableSignatureValidation.
605 /// </summary>
606 SuppressSignatureValidationDeprecated,
607
608 /// <summary>
609 /// WixCA Binary/@Id has been renamed to UtilCA.
610 /// </summary>
611 WixCABinaryIdRenamed,
612
613 /// <summary>
614 /// QtExec custom actions have been renamed.
615 /// </summary>
616 QuietExecCustomActionsRenamed,
617
618 /// <summary>
619 /// QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout.
620 /// </summary>
621 QtExecCmdTimeoutAmbiguous,
622
623 /// <summary>
624 /// Directory/@ShortName may only be specified with Directory/@Name.
625 /// </summary>
626 AssignDirectoryNameFromShortName,
627 }
628 }
629}
diff --git a/src/wixcop/WixCop.csproj b/src/wixcop/WixCop.csproj
index 7a17caf1..4c0d9a16 100644
--- a/src/wixcop/WixCop.csproj
+++ b/src/wixcop/WixCop.csproj
@@ -21,7 +21,7 @@
21 </ItemGroup> 21 </ItemGroup>
22 22
23 <ItemGroup> 23 <ItemGroup>
24 <PackageReference Include="WixToolset.Core" Version="4.0.*" /> 24 <PackageReference Include="WixToolset.Converters" Version="4.0.*" />
25 </ItemGroup> 25 </ItemGroup>
26 26
27 <ItemGroup> 27 <ItemGroup>