Fix deprecated $(loc.xxx) localization variable references.
Fixes wixtoolset/issues#6262
Ron Martin committed
Mar 28, 2021 at 23:29 UTC
0d29fa5d042d56517aaefb21f4fc512516039377
2 files changed
+102
-12
src/WixToolset.Converters/WixConverter.cs
+64
-12
@@ -179,6 +179,8 @@ namespace WixToolset.Converters
179
};
180
181
private readonly Dictionary<XName, Action<XElement>> ConvertElementMapping;
182
+ private readonly Regex DeprecatedPrefixRegex = new Regex(@"(?<=(^|[^\$])(\$\$)*)\$(?=\(loc\.[^.].*\))",
183
+ RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
184
185
/// <summary>
186
/// Instantiate a new Converter class.
@@ -427,6 +429,13 @@ namespace WixToolset.Converters
429
{
430
if (node is XText text)
431
{
432
+ if (null != text.Value)
433
+ {
434
+ if (this.TryFixDeprecatedLocalizationPrefixes(node, text.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue))
435
+ {
436
+ text.Value = newValue;
437
+ }
438
+ }
439
if (!String.IsNullOrWhiteSpace(text.Value))
440
{
441
text.Value = text.Value.Trim();
@@ -464,6 +473,20 @@ namespace WixToolset.Converters
473
}
474
}
475
476
+ private bool TryFixDeprecatedLocalizationPrefixes(XNode node, string value, out string newValue, ConverterTestType testType)
477
+ {
478
+ newValue = this.DeprecatedPrefixRegex.Replace(value, "!");
479
+
480
+ if (object.ReferenceEquals(newValue, value))
481
+ {
482
+ return false;
483
+ }
484
+
485
+ var message = testType == ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue ? "The prefix on the localization variable in the inner text is incorrect." : "The prefix on the localization variable in the attribute value is incorrect.";
486
+
487
+ return this.OnError(testType, node, message);
488
+ }
489
+
490
private void EnsurePrecedingWhitespaceCorrect(XText whitespace, XNode node, int level, ConverterTestType testType)
491
{
492
if (!WixConverter.LeadingWhitespaceValid(this.IndentationAmount, level, whitespace.Value))
@@ -492,25 +515,40 @@ namespace WixToolset.Converters
515
516
private void ConvertElement(XElement element)
517
{
495
- // Gather any deprecated namespaces, then update this element tree based on those deprecations.
518
var deprecatedToUpdatedNamespaces = new Dictionary<XNamespace, XNamespace>();
519
498
- foreach (var declaration in element.Attributes().Where(a => a.IsNamespaceDeclaration))
520
+ foreach (var attribute in element.Attributes())
521
{
500
- if (element.Name == Wix3ElementName || element.Name == Include3ElementName)
501
- {
502
- this.SourceVersion = 3;
503
- }
504
- else if (element.Name == Wix4ElementName || element.Name == Include4ElementName)
522
+ if (attribute.IsNamespaceDeclaration)
523
{
506
- this.SourceVersion = 4;
507
- }
524
+ // Gather any deprecated namespaces, then update this element tree based on those deprecations.
525
+ var declaration = attribute;
526
509
- if (WixConverter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out var ns))
527
+ if (element.Name == Wix3ElementName || element.Name == Include3ElementName)
528
+ {
529
+ this.SourceVersion = 3;
530
+ }
531
+ else if (element.Name == Wix4ElementName || element.Name == Include4ElementName)
532
+ {
533
+ this.SourceVersion = 4;
534
+ }
535
+
536
+ if (WixConverter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out var ns))
537
+ {
538
+ if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName))
539
+ {
540
+ deprecatedToUpdatedNamespaces.Add(declaration.Value, ns);
541
+ }
542
+ }
543
+ }
544
+ else
545
{
511
- if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName))
546
+ if (null != attribute.Value)
547
{
513
- deprecatedToUpdatedNamespaces.Add(declaration.Value, ns);
548
+ if (this.TryFixDeprecatedLocalizationPrefixes(element, attribute.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInAttributeValue))
549
+ {
550
+ attribute.Value = newValue;
551
+ }
552
}
553
}
554
}
@@ -1958,11 +1996,15 @@ namespace WixToolset.Converters
1996
/// </summary>
1997
WhitespacePrecedingEndElementWrong,
1998
1999
+ // Before this point, ignore errors on convert operation
2000
+
2001
/// <summary>
2002
/// Displayed when the XML declaration is present in the source file.
2003
/// </summary>
2004
DeclarationPresent,
2005
2006
+ // After this point, ignore errors on format operation
2007
+
2008
/// <summary>
2009
/// Displayed when the xmlns attribute is missing from the document element.
2010
/// </summary>
@@ -1973,6 +2015,16 @@ namespace WixToolset.Converters
2015
/// </summary>
2016
XmlnsValueWrong,
2017
2018
+ /// <summary>
2019
+ /// Displayed when inner text contains a deprecated $(loc.xxx) reference.
2020
+ /// </summary>
2021
+ DeprecatedLocalizationVariablePrefixInTextValue,
2022
+
2023
+ /// <summary>
2024
+ /// Displayed when an attribute value contains a deprecated $(loc.xxx) reference.
2025
+ /// </summary>
2026
+ DeprecatedLocalizationVariablePrefixInAttributeValue,
2027
+
2028
/// <summary>
2029
/// Assign an identifier to a File element when on Id attribute is specified.
2030
/// </summary>
src/test/WixToolsetTest.Converters/ConverterFixture.cs
+38
@@ -407,5 +407,43 @@ namespace WixToolsetTest.Converters
407
Assert.Equal(2, errors);
408
Assert.Equal(expected, actual);
409
}
410
+
411
+ [Fact]
412
+ public void CanConvertDeprecatedPrefix()
413
+ {
414
+ var parse = String.Join(Environment.NewLine,
415
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
416
+ "<Fragment>",
417
+ "<ComponentGroup Id=\"$(loc.Variable)\" />",
418
+ "<ComponentGroup Id=\"$$(loc.Variable)\" />",
419
+ "<ComponentGroup Id=\"$$$(loc.Variable)\" />",
420
+ "<ComponentGroup Id=\"$$$$(loc.Variable)\" />",
421
+ "<ComponentGroup Id=\"$$$$$(loc.Variable)\" />",
422
+ "</Fragment>",
423
+ "</Wix>");
424
+
425
+ var expected = String.Join(Environment.NewLine,
426
+ "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
427
+ "<Fragment>",
428
+ "<ComponentGroup Id=\"!(loc.Variable)\" />",
429
+ "<ComponentGroup Id=\"$$(loc.Variable)\" />",
430
+ "<ComponentGroup Id=\"$$!(loc.Variable)\" />",
431
+ "<ComponentGroup Id=\"$$$$(loc.Variable)\" />",
432
+ "<ComponentGroup Id=\"$$$$!(loc.Variable)\" />",
433
+ "</Fragment>",
434
+ "</Wix>");
435
+
436
+ var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
437
+
438
+ var messaging = new MockMessaging();
439
+ var converter = new WixConverter(messaging, 2, null, null);
440
+
441
+ var errors = converter.ConvertDocument(document);
442
+
443
+ var actual = UnformattedDocumentString(document);
444
+
445
+ Assert.Equal(3, errors);
446
+ Assert.Equal(expected, actual);
447
+ }
448
}
449
}