aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/ExtensibilityServices
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2020-07-05 23:26:48 -0700
committerRob Mensching <rob@firegiant.com>2020-07-08 15:18:09 -0700
commitb8bd03960b79e92d38ee7094a88e246253dad800 (patch)
tree89fec2cf4003832110bcbdd0633c8dcd492efd54 /src/WixToolset.Core/ExtensibilityServices
parent7b583330fd42356930bdc5a28820e546f6ca45a4 (diff)
downloadwix-b8bd03960b79e92d38ee7094a88e246253dad800.tar.gz
wix-b8bd03960b79e92d38ee7094a88e246253dad800.tar.bz2
wix-b8bd03960b79e92d38ee7094a88e246253dad800.zip
Improve compiler performance by removing regex and other string fixes
Diffstat (limited to 'src/WixToolset.Core/ExtensibilityServices')
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs132
1 files changed, 68 insertions, 64 deletions
diff --git a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
index db465354..81a18e24 100644
--- a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
+++ b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
@@ -9,7 +9,6 @@ namespace WixToolset.Core.ExtensibilityServices
9 using System.IO; 9 using System.IO;
10 using System.Security.Cryptography; 10 using System.Security.Cryptography;
11 using System.Text; 11 using System.Text;
12 using System.Text.RegularExpressions;
13 using System.Xml.Linq; 12 using System.Xml.Linq;
14 using WixToolset.Data; 13 using WixToolset.Data;
15 using WixToolset.Data.Symbols; 14 using WixToolset.Data.Symbols;
@@ -20,19 +19,6 @@ namespace WixToolset.Core.ExtensibilityServices
20 19
21 internal class ParseHelper : IParseHelper 20 internal class ParseHelper : IParseHelper
22 { 21 {
23 private const string LegalLongFilenameCharacters = @"[^\\\?|><:/\*""]"; // opposite of illegal above.
24 private static readonly Regex LegalLongFilename = new Regex(String.Concat("^", LegalLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
25
26 private const string LegalRelativeLongFilenameCharacters = @"[^\?|><:/\*""]"; // (like legal long, but we allow '\') illegal: ? | > < : / * "
27 private static readonly Regex LegalRelativeLongFilename = new Regex(String.Concat("^", LegalRelativeLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
28
29 private const string LegalWildcardLongFilenameCharacters = @"[^\\|><:/""]"; // illegal: \ | > < : / "
30 private static readonly Regex LegalWildcardLongFilename = new Regex(String.Concat("^", LegalWildcardLongFilenameCharacters, @"{1,259}$"));
31
32 private static readonly Regex LegalIdentifierWithAccess = new Regex(@"^((?<access>public|internal|protected|private)\s+)?(?<id>[_A-Za-z][0-9A-Za-z_\.]*)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
33
34 private static readonly Regex PutGuidHere = new Regex(@"PUT\-GUID\-(?:\d+\-)?HERE", RegexOptions.Singleline);
35
36 public ParseHelper(IWixToolsetServiceProvider serviceProvider) 22 public ParseHelper(IWixToolsetServiceProvider serviceProvider)
37 { 23 {
38 this.ServiceProvider = serviceProvider; 24 this.ServiceProvider = serviceProvider;
@@ -119,7 +105,7 @@ namespace WixToolset.Core.ExtensibilityServices
119 id = parentId; 105 id = parentId;
120 106
121 var pathStartsAt = 0; 107 var pathStartsAt = 0;
122 if (inlineSyntax[0].EndsWith(":")) 108 if (inlineSyntax[0].EndsWith(":", StringComparison.Ordinal))
123 { 109 {
124 // TODO: should overriding the parent identifier with a specific id be an error or a warning or just let it slide? 110 // TODO: should overriding the parent identifier with a specific id be an error or a warning or just let it slide?
125 //if (null != parentId) 111 //if (null != parentId)
@@ -415,44 +401,34 @@ namespace WixToolset.Core.ExtensibilityServices
415 var emptyRule = canBeEmpty ? EmptyRule.CanBeEmpty : EmptyRule.CanBeWhitespaceOnly; 401 var emptyRule = canBeEmpty ? EmptyRule.CanBeEmpty : EmptyRule.CanBeWhitespaceOnly;
416 var value = this.GetAttributeValue(sourceLineNumbers, attribute, emptyRule); 402 var value = this.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
417 403
418 if (String.IsNullOrEmpty(value) && canBeEmpty) 404 if (String.IsNullOrEmpty(value))
419 {
420 return String.Empty;
421 }
422 else if (!String.IsNullOrEmpty(value))
423 { 405 {
424 // If the value starts and ends with braces or parenthesis, accept that and strip them off. 406 if (canBeEmpty)
425 if ((value.StartsWith("{", StringComparison.Ordinal) && value.EndsWith("}", StringComparison.Ordinal))
426 || (value.StartsWith("(", StringComparison.Ordinal) && value.EndsWith(")", StringComparison.Ordinal)))
427 { 407 {
428 value = value.Substring(1, value.Length - 2); 408 return String.Empty;
429 } 409 }
430 410 }
431 if (generatable && "*".Equals(value, StringComparison.Ordinal)) 411 else
412 {
413 if (generatable && value == "*")
432 { 414 {
433 return value; 415 return value;
434 } 416 }
435 417
436 if (ParseHelper.PutGuidHere.IsMatch(value)) 418 if (Guid.TryParse(value, out var guid))
437 { 419 {
438 this.Messaging.Write(ErrorMessages.ExampleGuid(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 420 return guid.ToString("B").ToUpperInvariant();
439 return CompilerConstants.IllegalGuid;
440 } 421 }
441 else if (value.StartsWith("!(loc", StringComparison.Ordinal) || value.StartsWith("$(loc", StringComparison.Ordinal) || value.StartsWith("!(wix", StringComparison.Ordinal)) 422
423 if (value.StartsWith("!(loc", StringComparison.Ordinal) || value.StartsWith("$(loc", StringComparison.Ordinal) || value.StartsWith("!(wix", StringComparison.Ordinal))
442 { 424 {
443 return value; 425 return value;
444 } 426 }
445 else if (Guid.TryParse(value, out var guid))
446 {
447 var uppercaseGuid = guid.ToString().ToUpperInvariant();
448 427
449 // TODO: This used to be a pedantic error, what should it be now? 428 if (value.StartsWith("PUT-GUID-", StringComparison.OrdinalIgnoreCase) ||
450 //if (uppercaseGuid != value) 429 value.StartsWith("{PUT-GUID-", StringComparison.OrdinalIgnoreCase))
451 //{ 430 {
452 // this.Messaging.Write(WixErrors.GuidContainsLowercaseLetters(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 431 this.Messaging.Write(ErrorMessages.ExampleGuid(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
453 //}
454
455 return String.Concat("{", uppercaseGuid, "}");
456 } 432 }
457 else 433 else
458 { 434 {
@@ -468,19 +444,45 @@ namespace WixToolset.Core.ExtensibilityServices
468 var access = AccessModifier.Public; 444 var access = AccessModifier.Public;
469 var value = Common.GetAttributeValue(this.Messaging, sourceLineNumbers, attribute, EmptyRule.CanBeEmpty); 445 var value = Common.GetAttributeValue(this.Messaging, sourceLineNumbers, attribute, EmptyRule.CanBeEmpty);
470 446
471 var match = ParseHelper.LegalIdentifierWithAccess.Match(value); 447 var separator = value.IndexOf(' ');
472 if (!match.Success) 448 if (separator > 0)
473 { 449 {
474 return null; 450 var prefix = value.Substring(0, separator);
451 switch (prefix)
452 {
453 case "public":
454 case "package":
455 access = AccessModifier.Public;
456 break;
457
458 case "internal":
459 case "library":
460 access = AccessModifier.Internal;
461 break;
462
463 case "protected":
464 case "file":
465 access = AccessModifier.Protected;
466 break;
467
468 case "private":
469 case "fragment":
470 access = AccessModifier.Private;
471 break;
472
473 default:
474 return null;
475 }
476
477 value = value.Substring(separator + 1).Trim();
475 } 478 }
476 else if (match.Groups["access"].Success) 479
480 if (!Common.IsIdentifier(value))
477 { 481 {
478 access = (AccessModifier)Enum.Parse(typeof(AccessModifier), match.Groups["access"].Value, true); 482 this.Messaging.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
483 return null;
479 } 484 }
480 485 else if (72 < value.Length)
481 value = match.Groups["id"].Value;
482
483 if (Common.IsIdentifier(value) && 72 < value.Length)
484 { 486 {
485 this.Messaging.Write(WarningMessages.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 487 this.Messaging.Write(WarningMessages.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
486 } 488 }
@@ -520,7 +522,7 @@ namespace WixToolset.Core.ExtensibilityServices
520 } 522 }
521 else if (resultUsedToCreateReference && 1 == result.Length) 523 else if (resultUsedToCreateReference && 1 == result.Length)
522 { 524 {
523 if (value.EndsWith("\\")) 525 if (value.EndsWith("\\", StringComparison.Ordinal))
524 { 526 {
525 if (!this.IsValidLongFilename(result[0], false, false)) 527 if (!this.IsValidLongFilename(result[0], false, false))
526 { 528 {
@@ -547,7 +549,7 @@ namespace WixToolset.Core.ExtensibilityServices
547 } 549 }
548 } 550 }
549 551
550 if (1 < result.Length && !value.EndsWith("\\")) 552 if (1 < result.Length && !value.EndsWith("\\", StringComparison.Ordinal))
551 { 553 {
552 this.Messaging.Write(WarningMessages.BackslashTerminateInlineDirectorySyntax(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 554 this.Messaging.Write(WarningMessages.BackslashTerminateInlineDirectorySyntax(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
553 } 555 }
@@ -776,14 +778,7 @@ namespace WixToolset.Core.ExtensibilityServices
776 778
777 public bool IsValidLocIdentifier(string identifier) 779 public bool IsValidLocIdentifier(string identifier)
778 { 780 {
779 if (String.IsNullOrEmpty(identifier)) 781 return Common.TryParseWixVariable(identifier, 0, out var parsed) && parsed.Index == 0 && parsed.Length == identifier.Length && parsed.Namespace == "loc";
780 {
781 return false;
782 }
783
784 var match = Common.WixVariableRegex.Match(identifier);
785
786 return (match.Success && "loc" == match.Groups["namespace"].Value && 0 == match.Index && identifier.Length == match.Length);
787 } 782 }
788 783
789 public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative) 784 public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative)
@@ -792,29 +787,38 @@ namespace WixToolset.Core.ExtensibilityServices
792 { 787 {
793 return false; 788 return false;
794 } 789 }
790 else if (filename.Length > 259)
791 {
792 return false;
793 }
795 794
796 // Check for a non-period character (all periods is not legal) 795 // Check for a non-period character (all periods is not legal)
797 var nonPeriodFound = false; 796 var allPeriods = true;
798 foreach (var character in filename) 797 foreach (var character in filename)
799 { 798 {
800 if ('.' != character) 799 if ('.' != character)
801 { 800 {
802 nonPeriodFound = true; 801 allPeriods = false;
803 break; 802 break;
804 } 803 }
805 } 804 }
806 805
806 if (allPeriods)
807 {
808 return false;
809 }
810
807 if (allowWildcards) 811 if (allowWildcards)
808 { 812 {
809 return (nonPeriodFound && ParseHelper.LegalWildcardLongFilename.IsMatch(filename)); 813 return filename.IndexOfAny(Common.IllegalWildcardLongFilenameCharacters) == -1;
810 } 814 }
811 else if (allowRelative) 815 else if (allowRelative)
812 { 816 {
813 return (nonPeriodFound && ParseHelper.LegalRelativeLongFilename.IsMatch(filename)); 817 return filename.IndexOfAny(Common.IllegalRelativeLongFilenameCharacters) == -1;
814 } 818 }
815 else 819 else
816 { 820 {
817 return (nonPeriodFound && ParseHelper.LegalLongFilename.IsMatch(filename)); 821 return filename.IndexOfAny(Common.IllegalLongFilenameCharacters) == -1;
818 } 822 }
819 } 823 }
820 824