diff options
5 files changed, 272 insertions, 61 deletions
diff --git a/src/wix/WixToolset.Converters/HashSetExtensions.cs b/src/wix/WixToolset.Converters/HashSetExtensions.cs new file mode 100644 index 00000000..49b0d4ac --- /dev/null +++ b/src/wix/WixToolset.Converters/HashSetExtensions.cs | |||
@@ -0,0 +1,17 @@ | |||
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 WixToolset.Converters | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | |||
7 | internal static class HashSetExtensions | ||
8 | { | ||
9 | public static void AddRange<T>(this HashSet<T> set, IEnumerable<T> values) | ||
10 | { | ||
11 | foreach (var value in values) | ||
12 | { | ||
13 | set.Add(value); | ||
14 | } | ||
15 | } | ||
16 | } | ||
17 | } | ||
diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs index de81c876..cf77681c 100644 --- a/src/wix/WixToolset.Converters/WixConverter.cs +++ b/src/wix/WixToolset.Converters/WixConverter.cs | |||
@@ -11,6 +11,7 @@ namespace WixToolset.Converters | |||
11 | using System.Text.RegularExpressions; | 11 | using System.Text.RegularExpressions; |
12 | using System.Xml; | 12 | using System.Xml; |
13 | using System.Xml.Linq; | 13 | using System.Xml.Linq; |
14 | using System.Xml.XPath; | ||
14 | using WixToolset.Data; | 15 | using WixToolset.Data; |
15 | using WixToolset.Data.WindowsInstaller; | 16 | using WixToolset.Data.WindowsInstaller; |
16 | using WixToolset.Extensibility.Services; | 17 | using WixToolset.Extensibility.Services; |
@@ -272,6 +273,8 @@ namespace WixToolset.Converters | |||
272 | { WixConverter.WixLocalizationElementWithoutNamespaceName, this.ConvertWixLocalizationElementWithoutNamespace }, | 273 | { WixConverter.WixLocalizationElementWithoutNamespaceName, this.ConvertWixLocalizationElementWithoutNamespace }, |
273 | }; | 274 | }; |
274 | 275 | ||
276 | this.ConversionMessages = new List<Message>(); | ||
277 | |||
275 | this.Messaging = messaging; | 278 | this.Messaging = messaging; |
276 | 279 | ||
277 | this.IndentationAmount = indentationAmount; | 280 | this.IndentationAmount = indentationAmount; |
@@ -285,7 +288,7 @@ namespace WixToolset.Converters | |||
285 | 288 | ||
286 | private CustomTableTarget CustomTableSetting { get; } | 289 | private CustomTableTarget CustomTableSetting { get; } |
287 | 290 | ||
288 | private int Messages { get; set; } | 291 | private List<Message> ConversionMessages { get; } |
289 | 292 | ||
290 | private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; } | 293 | private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; } |
291 | 294 | ||
@@ -308,54 +311,35 @@ namespace WixToolset.Converters | |||
308 | /// </summary> | 311 | /// </summary> |
309 | /// <param name="sourceFile">The file to convert.</param> | 312 | /// <param name="sourceFile">The file to convert.</param> |
310 | /// <param name="saveConvertedFile">Option to save the converted Messages that are found.</param> | 313 | /// <param name="saveConvertedFile">Option to save the converted Messages that are found.</param> |
311 | /// <returns>The number of Messages found.</returns> | 314 | /// <returns>The number of conversions found.</returns> |
312 | public int ConvertFile(string sourceFile, bool saveConvertedFile) | 315 | public int ConvertFile(string sourceFile, bool saveConvertedFile) |
313 | { | 316 | { |
314 | var document = this.OpenSourceFile(sourceFile); | 317 | var savedDocument = false; |
315 | 318 | ||
316 | if (document is null) | 319 | if (this.TryOpenSourceFile(sourceFile, out var document)) |
317 | { | 320 | { |
318 | return 1; | 321 | this.Convert(document); |
319 | } | ||
320 | |||
321 | this.ConvertDocument(document); | ||
322 | 322 | ||
323 | // Fix Messages if requested and necessary. | 323 | // Fix Messages if requested and necessary. |
324 | if (saveConvertedFile && 0 < this.Messages) | 324 | if (saveConvertedFile && 0 < this.ConversionMessages.Count) |
325 | { | 325 | { |
326 | this.SaveDocument(document); | 326 | savedDocument = this.SaveDocument(document); |
327 | } | ||
327 | } | 328 | } |
328 | 329 | ||
329 | return this.Messages; | 330 | return this.ReportMessages(document, savedDocument); |
330 | } | 331 | } |
331 | 332 | ||
332 | /// <summary> | 333 | /// <summary> |
333 | /// Convert a document. | 334 | /// Convert a document. |
334 | /// </summary> | 335 | /// </summary> |
335 | /// <param name="document">The document to convert.</param> | 336 | /// <param name="document">The document to convert.</param> |
336 | /// <returns>The number of Messages found.</returns> | 337 | /// <returns>The number of conversions found.</returns> |
337 | public int ConvertDocument(XDocument document) | 338 | public int ConvertDocument(XDocument document) |
338 | { | 339 | { |
339 | // Reset the instance info. | 340 | this.Convert(document); |
340 | this.Messages = 0; | ||
341 | this.SourceVersion = 0; | ||
342 | this.Operation = ConvertOperation.Convert; | ||
343 | |||
344 | // Remove the declaration. | ||
345 | if (null != document.Declaration | ||
346 | && this.OnInformation(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) | ||
347 | { | ||
348 | document.Declaration = null; | ||
349 | TrimLeadingText(document); | ||
350 | } | ||
351 | |||
352 | this.XRoot = document.Root; | ||
353 | |||
354 | // Start converting the nodes at the top. | ||
355 | this.ConvertNodes(document.Nodes(), 0); | ||
356 | this.RemoveUnusedNamespaces(document.Root); | ||
357 | 341 | ||
358 | return this.Messages; | 342 | return this.ReportMessages(document, false); |
359 | } | 343 | } |
360 | 344 | ||
361 | /// <summary> | 345 | /// <summary> |
@@ -366,22 +350,20 @@ namespace WixToolset.Converters | |||
366 | /// <returns>The number of Messages found.</returns> | 350 | /// <returns>The number of Messages found.</returns> |
367 | public int FormatFile(string sourceFile, bool saveConvertedFile) | 351 | public int FormatFile(string sourceFile, bool saveConvertedFile) |
368 | { | 352 | { |
369 | var document = this.OpenSourceFile(sourceFile); | 353 | var savedDocument = false; |
370 | 354 | ||
371 | if (document is null) | 355 | if (this.TryOpenSourceFile(sourceFile, out var document)) |
372 | { | 356 | { |
373 | return 1; | 357 | this.FormatDocument(document); |
374 | } | ||
375 | |||
376 | this.FormatDocument(document); | ||
377 | 358 | ||
378 | // Fix Messages if requested and necessary. | 359 | // Fix Messages if requested and necessary. |
379 | if (saveConvertedFile && 0 < this.Messages) | 360 | if (saveConvertedFile && 0 < this.ConversionMessages.Count) |
380 | { | 361 | { |
381 | this.SaveDocument(document); | 362 | savedDocument = this.SaveDocument(document); |
363 | } | ||
382 | } | 364 | } |
383 | 365 | ||
384 | return this.Messages; | 366 | return this.ReportMessages(document, savedDocument); |
385 | } | 367 | } |
386 | 368 | ||
387 | /// <summary> | 369 | /// <summary> |
@@ -391,43 +373,73 @@ namespace WixToolset.Converters | |||
391 | /// <returns>The number of Messages found.</returns> | 373 | /// <returns>The number of Messages found.</returns> |
392 | public int FormatDocument(XDocument document) | 374 | public int FormatDocument(XDocument document) |
393 | { | 375 | { |
376 | this.Format(document); | ||
377 | |||
378 | return this.ReportMessages(document, false); | ||
379 | } | ||
380 | |||
381 | private void Convert(XDocument document) | ||
382 | { | ||
394 | // Reset the instance info. | 383 | // Reset the instance info. |
395 | this.Messages = 0; | 384 | this.ConversionMessages.Clear(); |
396 | this.SourceVersion = 0; | 385 | this.SourceVersion = 0; |
397 | this.Operation = ConvertOperation.Format; | 386 | this.Operation = ConvertOperation.Convert; |
398 | 387 | ||
399 | // Remove the declaration. | 388 | // Remove the declaration. |
400 | if (null != document.Declaration | 389 | if (null != document.Declaration |
401 | && this.OnInformation(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) | 390 | && this.OnInformation(ConverterTestType.DeclarationPresent, document, "This file contains an XML declaration on the first line.")) |
402 | { | 391 | { |
403 | document.Declaration = null; | 392 | document.Declaration = null; |
404 | TrimLeadingText(document); | 393 | TrimLeadingText(document); |
405 | } | 394 | } |
406 | 395 | ||
396 | this.XRoot = document.Root; | ||
397 | |||
407 | // Start converting the nodes at the top. | 398 | // Start converting the nodes at the top. |
408 | this.ConvertNodes(document.Nodes(), 0); | 399 | this.ConvertNodes(document.Nodes(), 0); |
409 | this.RemoveUnusedNamespaces(document.Root); | 400 | this.RemoveUnusedNamespaces(document.Root); |
401 | } | ||
402 | |||
403 | private void Format(XDocument document) | ||
404 | { | ||
405 | // Reset the instance info. | ||
406 | this.ConversionMessages.Clear(); | ||
407 | this.SourceVersion = 0; | ||
408 | this.Operation = ConvertOperation.Format; | ||
410 | 409 | ||
411 | return this.Messages; | 410 | // Remove the declaration. |
411 | if (null != document.Declaration | ||
412 | && this.OnInformation(ConverterTestType.DeclarationPresent, document, "This file contains an XML declaration on the first line.")) | ||
413 | { | ||
414 | document.Declaration = null; | ||
415 | TrimLeadingText(document); | ||
416 | } | ||
417 | |||
418 | this.XRoot = document.Root; | ||
419 | |||
420 | // Start converting the nodes at the top. | ||
421 | this.ConvertNodes(document.Nodes(), 0); | ||
422 | this.RemoveUnusedNamespaces(document.Root); | ||
412 | } | 423 | } |
413 | 424 | ||
414 | private XDocument OpenSourceFile(string sourceFile) | 425 | private bool TryOpenSourceFile(string sourceFile, out XDocument document) |
415 | { | 426 | { |
416 | this.SourceFile = sourceFile; | 427 | this.SourceFile = sourceFile; |
417 | 428 | ||
418 | try | 429 | try |
419 | { | 430 | { |
420 | return XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | 431 | document = XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); |
421 | } | 432 | } |
422 | catch (XmlException e) | 433 | catch (XmlException e) |
423 | { | 434 | { |
424 | this.OnError(ConverterTestType.XmlException, null, "The xml is invalid. Detail: '{0}'", e.Message); | 435 | this.OnError(ConverterTestType.XmlException, null, "The xml is invalid. Detail: '{0}'", e.Message); |
436 | document = null; | ||
425 | } | 437 | } |
426 | 438 | ||
427 | return null; | 439 | return document != null; |
428 | } | 440 | } |
429 | 441 | ||
430 | private void SaveDocument(XDocument document) | 442 | private bool SaveDocument(XDocument document) |
431 | { | 443 | { |
432 | var ignoreDeclarationError = this.IgnoreErrors.Contains(ConverterTestType.DeclarationPresent); | 444 | var ignoreDeclarationError = this.IgnoreErrors.Contains(ConverterTestType.DeclarationPresent); |
433 | 445 | ||
@@ -437,11 +449,15 @@ namespace WixToolset.Converters | |||
437 | { | 449 | { |
438 | document.Save(writer); | 450 | document.Save(writer); |
439 | } | 451 | } |
452 | |||
453 | return true; | ||
440 | } | 454 | } |
441 | catch (UnauthorizedAccessException) | 455 | catch (UnauthorizedAccessException) |
442 | { | 456 | { |
443 | this.OnError(ConverterTestType.UnauthorizedAccessException, null, "Could not write to file."); | 457 | this.OnError(ConverterTestType.UnauthorizedAccessException, null, "Could not write to file."); |
444 | } | 458 | } |
459 | |||
460 | return false; | ||
445 | } | 461 | } |
446 | 462 | ||
447 | private void ConvertNodes(IEnumerable<XNode> nodes, int level) | 463 | private void ConvertNodes(IEnumerable<XNode> nodes, int level) |
@@ -2129,6 +2145,14 @@ namespace WixToolset.Converters | |||
2129 | convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value); | 2145 | convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value); |
2130 | } | 2146 | } |
2131 | 2147 | ||
2148 | if (convertedAttribute != attribute) | ||
2149 | { | ||
2150 | foreach (var message in attribute.Annotations<Message>()) | ||
2151 | { | ||
2152 | convertedAttribute.AddAnnotation(message); | ||
2153 | } | ||
2154 | } | ||
2155 | |||
2132 | element.Add(convertedAttribute); | 2156 | element.Add(convertedAttribute); |
2133 | } | 2157 | } |
2134 | } | 2158 | } |
@@ -2214,6 +2238,110 @@ namespace WixToolset.Converters | |||
2214 | } | 2238 | } |
2215 | } | 2239 | } |
2216 | 2240 | ||
2241 | private int ReportMessages(XDocument document, bool saved) | ||
2242 | { | ||
2243 | var conversionCount = this.ConversionMessages.Count; | ||
2244 | |||
2245 | // If the converted/formatted document was saved, update the source line numbers | ||
2246 | // in the messages since they will possibly be wrong. | ||
2247 | if (saved && conversionCount > 0) | ||
2248 | { | ||
2249 | var fixedupMessages = new HashSet<Message>(); | ||
2250 | |||
2251 | // Load the converted document so we can look up new line numbers for | ||
2252 | // messages. | ||
2253 | var convertedDocument = XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | ||
2254 | var convertedNavigator = convertedDocument.CreateNavigator(); | ||
2255 | |||
2256 | // Look through all nodes in the document and try to fix up their line numbers. | ||
2257 | foreach (var elements in document.Descendants()) | ||
2258 | { | ||
2259 | var fixedup = this.FixupMessageLineNumbers(elements, convertedNavigator); | ||
2260 | fixedupMessages.AddRange(fixedup); | ||
2261 | |||
2262 | // Attributes are not considered nodes so they must be enumerated independently. | ||
2263 | if (elements is XElement element) | ||
2264 | { | ||
2265 | foreach (var attribute in element.Attributes()) | ||
2266 | { | ||
2267 | fixedup = this.FixupMessageLineNumbers(attribute, convertedNavigator); | ||
2268 | fixedupMessages.AddRange(fixedup); | ||
2269 | } | ||
2270 | } | ||
2271 | } | ||
2272 | |||
2273 | // For any messages that couldn't be fixed up, remove their line numbers since they point at lines | ||
2274 | // that are possibly wrong after the conversion. | ||
2275 | for (var i = 0; i < this.ConversionMessages.Count; ++i) | ||
2276 | { | ||
2277 | var message = this.ConversionMessages[i]; | ||
2278 | |||
2279 | if (!fixedupMessages.Contains(message)) | ||
2280 | { | ||
2281 | this.ConversionMessages[i] = new Message(new SourceLineNumber(this.SourceFile), message.Level, message.Id, message.ResourceNameOrFormat, message.MessageArgs); | ||
2282 | } | ||
2283 | } | ||
2284 | } | ||
2285 | |||
2286 | foreach (var message in this.ConversionMessages) | ||
2287 | { | ||
2288 | this.Messaging.Write(message); | ||
2289 | } | ||
2290 | |||
2291 | return conversionCount; | ||
2292 | } | ||
2293 | |||
2294 | private IReadOnlyCollection<Message> FixupMessageLineNumbers(XObject obj, XPathNavigator savedDocument) | ||
2295 | { | ||
2296 | var messages = obj.Annotations<Message>().ToList(); | ||
2297 | |||
2298 | if (messages.Count == 0) | ||
2299 | { | ||
2300 | return Array.Empty<Message>(); | ||
2301 | } | ||
2302 | |||
2303 | // We can't fix up line numbers based on attributes but we can fix up using their parent element, so do so. | ||
2304 | if (obj is XAttribute attribute) | ||
2305 | { | ||
2306 | obj = attribute.Parent; | ||
2307 | } | ||
2308 | |||
2309 | var fixedupMessages = new List<Message>(); | ||
2310 | |||
2311 | var modifiedLineNumber = this.GetModifiedNodeLineNumber((XElement)obj, savedDocument); | ||
2312 | |||
2313 | foreach (var message in messages) | ||
2314 | { | ||
2315 | var fixedupMessage = message; | ||
2316 | |||
2317 | // If the line number wasn't modified, the existing message's source line nuber is correct | ||
2318 | // so skip creating a new one. | ||
2319 | if (modifiedLineNumber != null) | ||
2320 | { | ||
2321 | var index = this.ConversionMessages.IndexOf(message); | ||
2322 | |||
2323 | fixedupMessage = new Message(modifiedLineNumber, message.Level, message.Id, message.ResourceNameOrFormat, message.MessageArgs); | ||
2324 | |||
2325 | this.ConversionMessages[index] = fixedupMessage; | ||
2326 | } | ||
2327 | |||
2328 | fixedupMessages.Add(fixedupMessage); | ||
2329 | } | ||
2330 | |||
2331 | return fixedupMessages; | ||
2332 | } | ||
2333 | |||
2334 | private SourceLineNumber GetModifiedNodeLineNumber(XElement element, XPathNavigator savedDocument) | ||
2335 | { | ||
2336 | var xpathToOld = CalculateXPath(element); | ||
2337 | |||
2338 | var newNode = savedDocument.SelectSingleNode(xpathToOld); | ||
2339 | var newLineNumber = (newNode as IXmlLineInfo).LineNumber; | ||
2340 | |||
2341 | var oldLineNumber = (element as IXmlLineInfo)?.LineNumber; | ||
2342 | return (oldLineNumber != newLineNumber) ? new SourceLineNumber(this.SourceFile, newLineNumber) : null; | ||
2343 | } | ||
2344 | |||
2217 | /// <summary> | 2345 | /// <summary> |
2218 | /// Output an error message to the console. | 2346 | /// Output an error message to the console. |
2219 | /// </summary> | 2347 | /// </summary> |
@@ -2250,10 +2378,8 @@ namespace WixToolset.Converters | |||
2250 | return false; | 2378 | return false; |
2251 | } | 2379 | } |
2252 | 2380 | ||
2253 | // Increase the message count. | 2381 | var sourceLine = SourceLineNumberForXmlLineInfo(this.SourceFile, node); |
2254 | this.Messages++; | ||
2255 | 2382 | ||
2256 | var sourceLine = (null == node) ? new SourceLineNumber(this.SourceFile ?? "wix.exe") : new SourceLineNumber(this.SourceFile, ((IXmlLineInfo)node).LineNumber); | ||
2257 | var prefix = String.Empty; | 2383 | var prefix = String.Empty; |
2258 | if (level == MessageLevel.Information) | 2384 | if (level == MessageLevel.Information) |
2259 | { | 2385 | { |
@@ -2268,11 +2394,34 @@ namespace WixToolset.Converters | |||
2268 | 2394 | ||
2269 | var msg = new Message(sourceLine, level, (int)converterTestType, format, args); | 2395 | var msg = new Message(sourceLine, level, (int)converterTestType, format, args); |
2270 | 2396 | ||
2271 | this.Messaging.Write(msg); | 2397 | // Add the message as a node annotation so it could be possible to remap source line numbers |
2398 | // to their new locations after converting/formatting (since lines of code could be moved). | ||
2399 | node?.AddAnnotation(msg); | ||
2400 | this.ConversionMessages.Add(msg); | ||
2272 | 2401 | ||
2273 | return true; | 2402 | return true; |
2274 | } | 2403 | } |
2275 | 2404 | ||
2405 | private static string CalculateXPath(XElement element) | ||
2406 | { | ||
2407 | var builder = new StringBuilder(); | ||
2408 | |||
2409 | while (element != null) | ||
2410 | { | ||
2411 | var index = element.Parent?.Elements().TakeWhile(e => e != element).Count() ?? 0; | ||
2412 | builder.Insert(0, $"/*[{index + 1}]"); | ||
2413 | |||
2414 | element = element.Parent; | ||
2415 | } | ||
2416 | |||
2417 | return builder.ToString(); | ||
2418 | } | ||
2419 | |||
2420 | private static SourceLineNumber SourceLineNumberForXmlLineInfo(string sourceFile, IXmlLineInfo lineInfo) | ||
2421 | { | ||
2422 | return (lineInfo?.HasLineInfo() == true) ? new SourceLineNumber(sourceFile, lineInfo.LineNumber) : new SourceLineNumber(sourceFile ?? "wix.exe"); | ||
2423 | } | ||
2424 | |||
2276 | /// <summary> | 2425 | /// <summary> |
2277 | /// Return an identifier based on passed file/directory name | 2426 | /// Return an identifier based on passed file/directory name |
2278 | /// </summary> | 2427 | /// </summary> |
@@ -2338,7 +2487,7 @@ namespace WixToolset.Converters | |||
2338 | comments = initialComments; | 2487 | comments = initialComments; |
2339 | var nonCommentNodes = new List<XNode>(); | 2488 | var nonCommentNodes = new List<XNode>(); |
2340 | 2489 | ||
2341 | foreach(var node in nodes) | 2490 | foreach (var node in nodes) |
2342 | { | 2491 | { |
2343 | if (XmlNodeType.Comment == node.NodeType) | 2492 | if (XmlNodeType.Comment == node.NodeType) |
2344 | { | 2493 | { |
diff --git a/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs index d186931b..cd6849d3 100644 --- a/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs +++ b/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs | |||
@@ -3,6 +3,8 @@ | |||
3 | namespace WixToolsetTest.Converters | 3 | namespace WixToolsetTest.Converters |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.IO; | ||
7 | using System.Linq; | ||
6 | using System.Xml.Linq; | 8 | using System.Xml.Linq; |
7 | using WixBuildTools.TestSupport; | 9 | using WixBuildTools.TestSupport; |
8 | using WixToolset.Converters; | 10 | using WixToolset.Converters; |
@@ -62,7 +64,7 @@ namespace WixToolsetTest.Converters | |||
62 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); | 64 | var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); |
63 | 65 | ||
64 | var messaging = new MockMessaging(); | 66 | var messaging = new MockMessaging(); |
65 | var converter = new WixConverter(messaging, 2, ignoreErrors: new[] { "DeclarationPresent" } ); | 67 | var converter = new WixConverter(messaging, 2, ignoreErrors: new[] { "DeclarationPresent" }); |
66 | 68 | ||
67 | var errors = converter.ConvertDocument(document); | 69 | var errors = converter.ConvertDocument(document); |
68 | 70 | ||
@@ -103,6 +105,40 @@ namespace WixToolsetTest.Converters | |||
103 | } | 105 | } |
104 | 106 | ||
105 | [Fact] | 107 | [Fact] |
108 | public void CanConvertMainNamespaceFromDisk() | ||
109 | { | ||
110 | var dataFolder = TestData.Get("TestData", "FixDeclarationAndNamespace"); | ||
111 | |||
112 | var expected = new[] | ||
113 | { | ||
114 | "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">", | ||
115 | " <Fragment />", | ||
116 | "</Wix>", | ||
117 | }; | ||
118 | |||
119 | using (var fs = new TestDataFolderFileSystem()) | ||
120 | { | ||
121 | fs.Initialize(dataFolder); | ||
122 | var path = Path.Combine(fs.BaseFolder, "FixDeclarationAndNamespace.wxs"); | ||
123 | |||
124 | var messaging = new MockMessaging(); | ||
125 | var converter = new WixConverter(messaging, 2, null, null); | ||
126 | |||
127 | var errors = converter.ConvertFile(path, true); | ||
128 | |||
129 | var messages = messaging.Messages.Select(m => $"{Path.GetFileName(m.SourceLineNumbers.FileName)}({m.SourceLineNumbers.LineNumber}) {m.ToString()}").ToArray(); | ||
130 | WixAssert.CompareLineByLine(new[] | ||
131 | { | ||
132 | "FixDeclarationAndNamespace.wxs() [Converted] This file contains an XML declaration on the first line. (DeclarationPresent)", | ||
133 | "FixDeclarationAndNamespace.wxs(1) [Converted] The namespace 'http://schemas.microsoft.com/wix/2006/wi' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs'. (XmlnsValueWrong)" | ||
134 | }, messages); | ||
135 | |||
136 | var actual = File.ReadAllLines(path); | ||
137 | WixAssert.CompareLineByLine(expected, actual); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | [Fact] | ||
106 | public void CanConvertNamedMainNamespace() | 142 | public void CanConvertNamedMainNamespace() |
107 | { | 143 | { |
108 | var parse = String.Join(Environment.NewLine, | 144 | var parse = String.Join(Environment.NewLine, |
diff --git a/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs index a8908df7..fdebc6b0 100644 --- a/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs +++ b/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs | |||
@@ -85,9 +85,14 @@ namespace WixToolsetTest.Converters | |||
85 | 85 | ||
86 | var messaging = new MockMessaging(); | 86 | var messaging = new MockMessaging(); |
87 | var converter = new WixConverter(messaging, 4); | 87 | var converter = new WixConverter(messaging, 4); |
88 | var errors = converter.ConvertFile(targetFile, true); | 88 | var convertedCount = converter.ConvertFile(targetFile, true); |
89 | 89 | ||
90 | Assert.Single(messaging.Messages.Where(m => m.Id == 5/*WixConverter.ConverterTestType.UnauthorizedAccessException*/)); | 90 | var errors = messaging.Messages.Where(m => m.Level == WixToolset.Data.MessageLevel.Error).Select(m => m.ToString()).ToArray(); |
91 | WixAssert.CompareLineByLine(new[] | ||
92 | { | ||
93 | "Could not write to file. (UnauthorizedAccessException)" | ||
94 | }, errors); | ||
95 | Assert.Equal(10, convertedCount); | ||
91 | } | 96 | } |
92 | } | 97 | } |
93 | 98 | ||
diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/FixDeclarationAndNamespace/FixDeclarationAndNamespace.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/FixDeclarationAndNamespace/FixDeclarationAndNamespace.wxs new file mode 100644 index 00000000..a8923337 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/FixDeclarationAndNamespace/FixDeclarationAndNamespace.wxs | |||
@@ -0,0 +1,4 @@ | |||
1 | <?xml version='1.0' encoding='utf-8'?> | ||
2 | <Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'> | ||
3 | <Fragment /> | ||
4 | </Wix> | ||