diff options
| author | Rob Mensching <rob@firegiant.com> | 2020-07-05 23:26:48 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2020-07-08 15:18:09 -0700 |
| commit | b8bd03960b79e92d38ee7094a88e246253dad800 (patch) | |
| tree | 89fec2cf4003832110bcbdd0633c8dcd492efd54 /src/WixToolset.Core/ExtensibilityServices | |
| parent | 7b583330fd42356930bdc5a28820e546f6ca45a4 (diff) | |
| download | wix-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.cs | 132 |
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 | ||
