From: Abel Braaksma Date: Mon, 17 Aug 2020 22:25:22 +0000 (+0200) Subject: Make RegexParseException and RegexParseError public, rename enum fields (#40902) X-Git-Tag: submit/tizen/20210909.063632~5903 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e26d0131b23519732f05ec39729bfc3bfe119be7;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Make RegexParseException and RegexParseError public, rename enum fields (#40902) * RegexParseException, RegexParseError public, rename enum fields * Add Unknown field to RegexParseError * Add definitions to ref file * Satisfy NET48 tests * Some nits to resolve review comments * Add default message and Unknown message * Added doc comments * Fix nit in auto-layout change of csproj file * Simplify message for RegexParseException ctor overload * Remove PlatformDetection.IsNetFramework in RegexParserTests.cs * Rename resource names to match the enum names * Use partial class and methods to separate netfx and core * Add offset tests * Apply suggestions from code review Nits * Add remaining test offsets. Verify all offsets. * Nit and TFM * Update src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netcoreapp.cs Co-authored-by: Stephen Toub * Update src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netfx.cs Co-authored-by: Stephen Toub * Update src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netfx.cs Co-authored-by: Stephen Toub * Code review: properly test for deserialized type of exn * Code review: fix doc comments * Code review: fix doc comments * Code review: offset gt zero * Code review: add some tests, remove redundant whiteline * Code review: add doc comment as suggested * Code review: fix doc comments * ref edits with tool * Code review: some nits * Remove using * Rename unknown * Incorrect edit in AssertExtensions * Cherry-pick #d4090296 * Fix naming, ref file, resource strings Co-authored-by: Dan Moseley Co-authored-by: Prashanth Govindarajan Co-authored-by: Stephen Toub --- diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index dea97ee..ec648c7 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -209,7 +209,7 @@ namespace System if (exceptionTypes.Any(t => t.Equals(exceptionType))) return; - throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: ({e.GetType()})"); + throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: ({exceptionType})"); } throw new XunitException($"Expected one of: ({string.Join(", ", exceptionTypes)}) -> Actual: No exception thrown"); diff --git a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs index d25af2a..e048a2e 100644 --- a/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs +++ b/src/libraries/System.Text.RegularExpressions/ref/System.Text.RegularExpressions.cs @@ -241,6 +241,48 @@ namespace System.Text.RegularExpressions ECMAScript = 256, CultureInvariant = 512, } + public enum RegexParseError + { + Unknown = 0, + AlternationHasTooManyConditions = 1, + AlternationHasMalformedCondition = 2, + InvalidUnicodePropertyEscape = 3, + MalformedUnicodePropertyEscape = 4, + UnrecognizedEscape = 5, + UnrecognizedControlCharacter = 6, + MissingControlCharacter = 7, + InsufficientOrInvalidHexDigits = 8, + QuantifierOrCaptureGroupOutOfRange = 9, + UndefinedNamedReference = 10, + UndefinedNumberedReference = 11, + MalformedNamedReference = 12, + UnescapedEndingBackslash = 13, + UnterminatedComment = 14, + InvalidGroupingConstruct = 15, + AlternationHasNamedCapture = 16, + AlternationHasComment = 17, + AlternationHasMalformedReference = 18, + AlternationHasUndefinedReference = 19, + CaptureGroupNameInvalid = 20, + CaptureGroupOfZero = 21, + UnterminatedBracket = 22, + ExclusionGroupNotLast = 23, + ReversedCharacterRange = 24, + ShorthandClassInCharacterRange = 25, + InsufficientClosingParentheses = 26, + ReversedQuantifierRange = 27, + NestedQuantifiersNotParenthesized = 28, + QuantifierAfterNothing = 29, + InsufficientOpeningParentheses = 30, + UnrecognizedUnicodeProperty = 31, + } + public sealed partial class RegexParseException : System.ArgumentException + { + private RegexParseException() { } + public System.Text.RegularExpressions.RegexParseError Error { get { throw null; } } + public int Offset { get { throw null; } } + public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } + } public abstract partial class RegexRunner { protected internal int[]? runcrawl; diff --git a/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx b/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx index 06943ac..ef01f52 100644 --- a/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx +++ b/src/libraries/System.Text.RegularExpressions/src/Resources/Strings.resx @@ -57,10 +57,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + Regular expression parser error '{0}' at offset {1}. + + Alternation conditions do not capture and cannot be named. - + Alternation conditions cannot be comments. @@ -69,16 +72,19 @@ The array cannot contain null elements. - + Cannot include class \\{0} in character range. + + Cannot include class in character range. + Start index cannot be less than 0 or greater than input length. - + Capture group numbers must be less than or equal to Int32.MaxValue. - + Capture number cannot be zero. @@ -87,25 +93,25 @@ Enumeration has either not started or has already finished. - + Illegal conditional (?(...)) expression. AppDomain data '{0}' contains the invalid value or object '{1}' for specifying a default matching timeout for System.Text.RegularExpressions.Regex. - + Illegal \\ at end of pattern. - + Illegal {x,y} with x > y. - + Incomplete \\p{X} character escape. Internal error in ScanRegex. - + Invalid group name: Group names must begin with a word character. @@ -114,28 +120,34 @@ Length cannot be less than 0 or exceed input length. - + Malformed \\k<...> named back reference. - + (?({0}) ) malformed. - + + Alternation has malformed reference. + + Malformed \\p{X} character escape. Invalid pattern '{0}' at offset {1}. {2} - + Missing control character. - + Nested quantifier '{0}'. + + Nested quantifier no parenthesized. + Result cannot be called on a failed Match. - + Not enough )'s. @@ -147,7 +159,7 @@ This platform does not support writing compiled regular expressions to an assembly. - + Quantifier {x,y} following nothing. @@ -156,43 +168,55 @@ Replacement pattern error. - + [x-y] range in reverse order. - + A subtraction must be the last element in a character class. - + Insufficient hexadecimal digits. - + Too many | in (?()|). - + Too many )'s. - + Reference to undefined group number {0}. - + + Reference to undefined group number. + + Reference to undefined group name '{0}'. - + + Reference to undefined group name. + + (?({0}) ) reference to undefined group. + + Alternation has a reference to undefined group. + Unexpected opcode in regular expression generation: {0}. - + Unknown property '{0}'. - + + Unknown property Unicode property. + + Unrecognized control character. Unrecognized escape sequence \\{0}. - + Unrecognized grouping construct. diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs index 840f895..d4022f6 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs @@ -1515,8 +1515,8 @@ namespace System.Text.RegularExpressions } } - throw new RegexParseException(RegexParseError.UnknownUnicodeProperty, currentPos, - SR.Format(SR.MakeException, pattern, currentPos, SR.Format(SR.UnknownProperty, capname))); + throw new RegexParseException(RegexParseError.UnrecognizedUnicodeProperty, currentPos, + SR.Format(SR.MakeException, pattern, currentPos, SR.Format(SR.UnrecognizedUnicodeProperty, capname))); } #if DEBUG diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseError.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseError.cs index 6f930e6..108d1cb 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseError.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseError.cs @@ -3,38 +3,142 @@ namespace System.Text.RegularExpressions { - internal enum RegexParseError + /// + /// Specifies the detailed underlying reason why a is thrown when a + /// regular expression contains a parsing error. + /// + /// + /// This information is made available through . + /// + public enum RegexParseError { - TooManyAlternates, - IllegalCondition, - IncompleteSlashP, - MalformedSlashP, + /// + /// An unknown regular expression parse error. + /// + Unknown, + /// + /// An alternation in a regular expression has too many conditions. + /// + AlternationHasTooManyConditions, + /// + /// An alternation in a regular expression has a malformed condition. + /// + AlternationHasMalformedCondition, + /// + /// A Unicode property escape in a regular expression is invalid or unknown. + /// + InvalidUnicodePropertyEscape, + /// + /// A Unicode property escape is malformed. + /// + MalformedUnicodePropertyEscape, + /// + /// An escape character or sequence in a regular expression is invalid. + /// UnrecognizedEscape, - UnrecognizedControl, - MissingControl, - TooFewHex, - CaptureGroupOutOfRange, - UndefinedNameRef, - UndefinedBackref, - MalformedNameRef, - IllegalEndEscape, + /// + /// A control character in a regular expression is not recognized. + /// + UnrecognizedControlCharacter, + /// + /// A control character in a regular expression is missing. + /// + MissingControlCharacter, + /// + /// A hexadecimal escape sequence in a regular expression does not have enough digits, or contains invalid digits. + /// + InsufficientOrInvalidHexDigits, + /// + /// A captured group or a quantifier in a regular expression is not within range, that is, it is larger than . + /// + QuantifierOrCaptureGroupOutOfRange, + /// + /// A used named reference in a regular expression is not defined. + /// + UndefinedNamedReference, + /// + /// A used numbered reference in a regular expression is not defined. + /// + UndefinedNumberedReference, + /// + /// A named reference in a regular expression is malformed. + /// + MalformedNamedReference, + /// + /// A regular expression ends with a non-escaped ending backslash. + /// + UnescapedEndingBackslash, + /// + /// A comment in a regular expression is not terminated. + /// UnterminatedComment, - UnrecognizedGrouping, - AlternationCantCapture, - AlternationCantHaveComment, - MalformedReference, - UndefinedReference, - InvalidGroupName, - CapnumNotZero, + /// + /// A grouping construct in a regular expression is invalid or malformed. + /// + InvalidGroupingConstruct, + /// + /// An alternation construct in a regular expression uses a named capture. + /// + AlternationHasNamedCapture, + /// + /// An alternation construct in a regular expression contains a comment. + /// + AlternationHasComment, + /// + /// An alternation construct in a regular expression contains a malformed reference. + /// + AlternationHasMalformedReference, + /// + /// An alternation construct in a regular expression contains an undefined reference. + /// + AlternationHasUndefinedReference, + /// + /// The group name of a captured group in a regular expression is invalid. + /// + CaptureGroupNameInvalid, + /// + /// A regular expression defines a numbered subexpression named zero. + /// + CaptureGroupOfZero, + /// + /// A regular expression has a non-escaped left square bracket, or misses a closing right square bracket. + /// UnterminatedBracket, - SubtractionMustBeLast, - ReversedCharRange, - BadClassInCharRange, - NotEnoughParentheses, - IllegalRange, - NestedQuantify, - QuantifyAfterNothing, - TooManyParentheses, - UnknownUnicodeProperty + /// + /// A character class in a regular expression with an exclusion group is not the last part of the character class. + /// + ExclusionGroupNotLast, + /// + /// A character class in a regular expression contains an inverse character range, like z-a instead of a-z. + /// + ReversedCharacterRange, + /// + /// A character-class in a regular expression contains a short-hand class that is not allowed inside a character class. + /// + ShorthandClassInCharacterRange, + /// + /// A regular expression has a non-escaped left parenthesis, or misses a closing right parenthesis. + /// + InsufficientClosingParentheses, + /// + /// A quantifier range in a regular expression is inverse, like {10,1} instead of (1,10}. + /// + ReversedQuantifierRange, + /// + /// Repeated quantifiers on another quantifier inside a regular expression are not grouped in parentheses. + /// + NestedQuantifiersNotParenthesized, + /// + /// A quantifier in a regular expression is in a position where it cannot quantify anything, like at the beginning of a regular expression or in a group. + /// + QuantifierAfterNothing, + /// + /// A regular expression has a non-escaped right parenthesis, or misses an opening left parenthesis. + /// + InsufficientOpeningParentheses, + /// + /// A unicode property in a regular expression is not recognized, or invalid. + /// + UnrecognizedUnicodeProperty } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseException.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseException.cs index 3682911..a013805 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseException.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParseException.cs @@ -5,23 +5,152 @@ using System.Runtime.Serialization; namespace System.Text.RegularExpressions { + /// + /// An exception as a result of a parse error in a regular expression , with + /// detailed information in the and properties. + /// [Serializable] - internal sealed class RegexParseException : ArgumentException + public sealed class RegexParseException : ArgumentException { - private readonly RegexParseError _error; // tests access this via private reflection - /// Gets the error that happened during parsing. - public RegexParseError Error => _error; + public RegexParseError Error { get; } - /// Gets the offset in the supplied pattern. + /// Gets the zero-based character offset in the regular expression pattern where the parse error occurs. public int Offset { get; } - public RegexParseException(RegexParseError error, int offset, string message) : base(message) + internal RegexParseException(RegexParseError error, int offset, string message) : base(message) + { + Error = error; + Offset = offset; + } + + internal RegexParseException(string pattern, RegexParseError error, int offset) : base(MakeMessage(pattern, error, offset)) { - _error = error; + Error = error; Offset = offset; } + /// + /// Construct a that creates a default message based on the given value. + /// + /// The pattern of the regular expression. + /// The value detailing the type of parse error. + /// The zero-based offset in the regular expression where the parse error occurs. + private static string MakeMessage(string pattern, RegexParseError error, int offset) + { + string message; + switch (error) + { + case RegexParseError.Unknown: + message = SR.Format(SR.MakeException, pattern, offset, SR.Generic); + break; + case RegexParseError.AlternationHasTooManyConditions: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasTooManyConditions); + break; + case RegexParseError.AlternationHasMalformedCondition: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasMalformedCondition); + break; + case RegexParseError.InvalidUnicodePropertyEscape: + message = SR.Format(SR.MakeException, pattern, offset, SR.InvalidUnicodePropertyEscape); + break; + case RegexParseError.MalformedUnicodePropertyEscape: + message = SR.Format(SR.MakeException, pattern, offset, SR.MalformedUnicodePropertyEscape); + break; + case RegexParseError.UnrecognizedEscape: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnrecognizedEscape); + break; + case RegexParseError.UnrecognizedControlCharacter: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnrecognizedControlCharacter); + break; + case RegexParseError.MissingControlCharacter: + message = SR.Format(SR.MakeException, pattern, offset, SR.MissingControlCharacter); + break; + case RegexParseError.InsufficientOrInvalidHexDigits: + message = SR.Format(SR.MakeException, pattern, offset, SR.InsufficientOrInvalidHexDigits); + break; + case RegexParseError.QuantifierOrCaptureGroupOutOfRange: + message = SR.Format(SR.MakeException, pattern, offset, SR.QuantifierOrCaptureGroupOutOfRange); + break; + case RegexParseError.UndefinedNamedReference: + message = SR.Format(SR.MakeException, pattern, offset, SR.UndefinedNamedReferenceNoPlaceholder); + break; + case RegexParseError.UndefinedNumberedReference: + message = SR.Format(SR.MakeException, pattern, offset, SR.UndefinedNumberedReferenceNoPlaceholder); + break; + case RegexParseError.MalformedNamedReference: + message = SR.Format(SR.MakeException, pattern, offset, SR.MalformedNamedReference); + break; + case RegexParseError.UnescapedEndingBackslash: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnescapedEndingBackslash); + break; + case RegexParseError.UnterminatedComment: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnterminatedComment); + break; + case RegexParseError.InvalidGroupingConstruct: + message = SR.Format(SR.MakeException, pattern, offset, SR.InvalidGroupingConstruct); + break; + case RegexParseError.AlternationHasNamedCapture: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasNamedCapture); + break; + case RegexParseError.AlternationHasComment: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasComment); + break; + case RegexParseError.AlternationHasMalformedReference: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasMalformedReferenceNoPlaceholder); + break; + case RegexParseError.AlternationHasUndefinedReference: + message = SR.Format(SR.MakeException, pattern, offset, SR.AlternationHasUndefinedReferenceNoPlaceholder); + break; + case RegexParseError.CaptureGroupNameInvalid: + message = SR.Format(SR.MakeException, pattern, offset, SR.CaptureGroupNameInvalid); + break; + case RegexParseError.CaptureGroupOfZero: + message = SR.Format(SR.MakeException, pattern, offset, SR.CaptureGroupOfZero); + break; + case RegexParseError.UnterminatedBracket: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnterminatedBracket); + break; + case RegexParseError.ExclusionGroupNotLast: + message = SR.Format(SR.MakeException, pattern, offset, SR.ExclusionGroupNotLast); + break; + case RegexParseError.ReversedCharacterRange: + message = SR.Format(SR.MakeException, pattern, offset, SR.ReversedCharacterRange); + break; + case RegexParseError.ShorthandClassInCharacterRange: + message = SR.Format(SR.MakeException, pattern, offset, SR.ShorthandClassInCharacterRangeNoPlaceholder); + break; + case RegexParseError.InsufficientClosingParentheses: + message = SR.Format(SR.MakeException, pattern, offset, SR.InsufficientClosingParentheses); + break; + case RegexParseError.ReversedQuantifierRange: + message = SR.Format(SR.MakeException, pattern, offset, SR.ReversedQuantifierRange); + break; + case RegexParseError.NestedQuantifiersNotParenthesized: + message = SR.Format(SR.MakeException, pattern, offset, SR.NestedQuantifiersNotParenthesizedNoPlaceholder); + break; + case RegexParseError.QuantifierAfterNothing: + message = SR.Format(SR.MakeException, pattern, offset, SR.QuantifierAfterNothing); + break; + case RegexParseError.InsufficientOpeningParentheses: + message = SR.Format(SR.MakeException, pattern, offset, SR.InsufficientOpeningParentheses); + break; + case RegexParseError.UnrecognizedUnicodeProperty: + message = SR.Format(SR.MakeException, pattern, offset, SR.UnrecognizedUnicodePropertyNoPlaceholder); + break; + default: + message = SR.Format(SR.MakeException, pattern, offset, SR.Generic); + break; + } + + return message; + } + + private RegexParseException(SerializationInfo info, StreamingContext context) + { + // It means someone modified the payload. + throw new NotImplementedException(); + } + public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs index cb051da..fae6d58 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexParser.cs @@ -350,7 +350,7 @@ namespace System.Text.RegularExpressions case ')': if (EmptyStack()) { - throw MakeException(RegexParseError.TooManyParentheses, SR.TooManyParens); + throw MakeException(RegexParseError.InsufficientOpeningParentheses, SR.InsufficientOpeningParentheses); } AddGroup(); @@ -366,7 +366,7 @@ namespace System.Text.RegularExpressions case '\\': if (CharsRight() == 0) { - throw MakeException(RegexParseError.IllegalEndEscape, SR.IllegalEndEscape); + throw MakeException(RegexParseError.UnescapedEndingBackslash, SR.UnescapedEndingBackslash); } AddUnitNode(ScanBackslash(scanOnly: false)!); @@ -398,8 +398,8 @@ namespace System.Text.RegularExpressions if (Unit() == null) { throw wasPrevQuantifier ? - MakeException(RegexParseError.NestedQuantify, SR.Format(SR.NestedQuantify, ch)) : - MakeException(RegexParseError.QuantifyAfterNothing, SR.QuantifyAfterNothing); + MakeException(RegexParseError.NestedQuantifiersNotParenthesized, SR.Format(SR.NestedQuantifiersNotParenthesized, ch)) : + MakeException(RegexParseError.QuantifierAfterNothing, SR.QuantifierAfterNothing); } MoveLeft(); break; @@ -482,7 +482,7 @@ namespace System.Text.RegularExpressions if (min > max) { - throw MakeException(RegexParseError.IllegalRange, SR.IllegalRange); + throw MakeException(RegexParseError.ReversedQuantifierRange, SR.ReversedQuantifierRange); } AddConcatenate(lazy, min, max); @@ -497,7 +497,7 @@ namespace System.Text.RegularExpressions if (!EmptyStack()) { - throw MakeException(RegexParseError.NotEnoughParentheses, SR.NotEnoughParens); + throw MakeException(RegexParseError.InsufficientClosingParentheses, SR.InsufficientClosingParentheses); } AddGroup(); @@ -593,7 +593,7 @@ namespace System.Text.RegularExpressions { if (inRange) { - throw MakeException(RegexParseError.BadClassInCharRange, SR.Format(SR.BadClassInCharRange, ch)); + throw MakeException(RegexParseError.ShorthandClassInCharacterRange, SR.Format(SR.ShorthandClassInCharacterRange, ch)); } charClass!.AddDigit(UseOptionE(), ch == 'D', _pattern, _currentPos); } @@ -605,7 +605,7 @@ namespace System.Text.RegularExpressions { if (inRange) { - throw MakeException(RegexParseError.BadClassInCharRange, SR.Format(SR.BadClassInCharRange, ch)); + throw MakeException(RegexParseError.ShorthandClassInCharacterRange, SR.Format(SR.ShorthandClassInCharacterRange, ch)); } charClass!.AddSpace(UseOptionE(), ch == 'S'); } @@ -617,7 +617,7 @@ namespace System.Text.RegularExpressions { if (inRange) { - throw MakeException(RegexParseError.BadClassInCharRange, SR.Format(SR.BadClassInCharRange, ch)); + throw MakeException(RegexParseError.ShorthandClassInCharacterRange, SR.Format(SR.ShorthandClassInCharacterRange, ch)); } charClass!.AddWord(UseOptionE(), ch == 'W'); @@ -630,7 +630,7 @@ namespace System.Text.RegularExpressions { if (inRange) { - throw MakeException(RegexParseError.BadClassInCharRange, SR.Format(SR.BadClassInCharRange, ch)); + throw MakeException(RegexParseError.ShorthandClassInCharacterRange, SR.Format(SR.ShorthandClassInCharacterRange, ch)); } charClass!.AddCategoryFromName(ParseProperty(), ch != 'p', caseInsensitive, _pattern, _currentPos); @@ -648,7 +648,7 @@ namespace System.Text.RegularExpressions { if (chPrev > ch) { - throw MakeException(RegexParseError.ReversedCharRange, SR.ReversedCharRange); + throw MakeException(RegexParseError.ReversedCharacterRange, SR.ReversedCharacterRange); } charClass!.AddRange(chPrev, ch); @@ -700,7 +700,7 @@ namespace System.Text.RegularExpressions if (CharsRight() > 0 && RightChar() != ']') { - throw MakeException(RegexParseError.SubtractionMustBeLast, SR.SubtractionMustBeLast); + throw MakeException(RegexParseError.ExclusionGroupNotLast, SR.ExclusionGroupNotLast); } } else @@ -708,7 +708,7 @@ namespace System.Text.RegularExpressions // a regular range, like a-z if (chPrev > ch) { - throw MakeException(RegexParseError.ReversedCharRange, SR.ReversedCharRange); + throw MakeException(RegexParseError.ReversedCharacterRange, SR.ReversedCharacterRange); } charClass!.AddRange(chPrev, ch); } @@ -732,7 +732,7 @@ namespace System.Text.RegularExpressions if (CharsRight() > 0 && RightChar() != ']') { - throw MakeException(RegexParseError.SubtractionMustBeLast, SR.SubtractionMustBeLast); + throw MakeException(RegexParseError.ExclusionGroupNotLast, SR.ExclusionGroupNotLast); } } else @@ -877,12 +877,12 @@ namespace System.Text.RegularExpressions // check if we have bogus characters after the number if (CharsRight() > 0 && !(RightChar() == close || RightChar() == '-')) { - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } if (capnum == 0) { - throw MakeException(RegexParseError.CapnumNotZero, SR.CapnumNotZero); + throw MakeException(RegexParseError.CaptureGroupOfZero, SR.CaptureGroupOfZero); } } else if (RegexCharClass.IsWordChar(ch)) @@ -897,7 +897,7 @@ namespace System.Text.RegularExpressions // check if we have bogus character after the name if (CharsRight() > 0 && !(RightChar() == close || RightChar() == '-')) { - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } } else if (ch == '-') @@ -907,7 +907,7 @@ namespace System.Text.RegularExpressions else { // bad group name - starts with something other than a word character and isn't a number - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } // grab part after - if any @@ -923,13 +923,13 @@ namespace System.Text.RegularExpressions if (!IsCaptureSlot(uncapnum)) { - throw MakeException(RegexParseError.UndefinedBackref, SR.Format(SR.UndefinedBackref, uncapnum)); + throw MakeException(RegexParseError.UndefinedNumberedReference, SR.Format(SR.UndefinedNumberedReference, uncapnum)); } // check if we have bogus characters after the number if (CharsRight() > 0 && RightChar() != close) { - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } } else if (RegexCharClass.IsWordChar(ch)) @@ -942,19 +942,19 @@ namespace System.Text.RegularExpressions } else { - throw MakeException(RegexParseError.UndefinedNameRef, SR.Format(SR.UndefinedNameRef, uncapname)); + throw MakeException(RegexParseError.UndefinedNamedReference, SR.Format(SR.UndefinedNamedReference, uncapname)); } // check if we have bogus character after the name if (CharsRight() > 0 && RightChar() != close) { - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } } else { // bad group name - starts with something other than a word character and isn't a number - throw MakeException(RegexParseError.InvalidGroupName, SR.InvalidGroupName); + throw MakeException(RegexParseError.CaptureGroupNameInvalid, SR.CaptureGroupNameInvalid); } } @@ -987,10 +987,10 @@ namespace System.Text.RegularExpressions return new RegexNode(RegexNode.Testref, _options, capnum); } - throw MakeException(RegexParseError.UndefinedReference, SR.Format(SR.UndefinedReference, capnum.ToString())); + throw MakeException(RegexParseError.AlternationHasUndefinedReference, SR.Format(SR.AlternationHasUndefinedReference, capnum.ToString())); } - throw MakeException(RegexParseError.MalformedReference, SR.Format(SR.MalformedReference, capnum.ToString())); + throw MakeException(RegexParseError.AlternationHasMalformedReference, SR.Format(SR.AlternationHasMalformedReference, capnum.ToString())); } else if (RegexCharClass.IsWordChar(ch)) { @@ -1015,18 +1015,18 @@ namespace System.Text.RegularExpressions // disallow comments in the condition if (rightchar2 == '#') { - throw MakeException(RegexParseError.AlternationCantHaveComment, SR.AlternationCantHaveComment); + throw MakeException(RegexParseError.AlternationHasComment, SR.AlternationHasComment); } // disallow named capture group (?<..>..) in the condition if (rightchar2 == '\'') { - throw MakeException(RegexParseError.AlternationCantCapture, SR.AlternationCantCapture); + throw MakeException(RegexParseError.AlternationHasNamedCapture, SR.AlternationHasNamedCapture); } if (charsRight >= 4 && rightchar2 == '<' && RightChar(3) != '!' && RightChar(3) != '=') { - throw MakeException(RegexParseError.AlternationCantCapture, SR.AlternationCantCapture); + throw MakeException(RegexParseError.AlternationHasNamedCapture, SR.AlternationHasNamedCapture); } } @@ -1066,7 +1066,7 @@ namespace System.Text.RegularExpressions ; // break Recognize comes here - throw MakeException(RegexParseError.UnrecognizedGrouping, SR.UnrecognizedGrouping); + throw MakeException(RegexParseError.InvalidGroupingConstruct, SR.InvalidGroupingConstruct); } /* @@ -1218,7 +1218,7 @@ namespace System.Text.RegularExpressions { if (CharsRight() == 0) { - throw MakeException(RegexParseError.IllegalEndEscape, SR.IllegalEndEscape); + throw MakeException(RegexParseError.UnescapedEndingBackslash, SR.UnescapedEndingBackslash); } int backpos = Textpos(); @@ -1243,7 +1243,7 @@ namespace System.Text.RegularExpressions if (!angled || CharsRight() <= 0) { - throw MakeException(RegexParseError.MalformedNameRef, SR.MalformedNameRef); + throw MakeException(RegexParseError.MalformedNamedReference, SR.MalformedNamedReference); } ch = RightChar(); @@ -1270,7 +1270,7 @@ namespace System.Text.RegularExpressions return scanOnly ? null : IsCaptureSlot(capnum) ? new RegexNode(RegexNode.Ref, _options, capnum) : - throw MakeException(RegexParseError.UndefinedBackref, SR.Format(SR.UndefinedBackref, capnum.ToString())); + throw MakeException(RegexParseError.UndefinedNumberedReference, SR.Format(SR.UndefinedNumberedReference, capnum.ToString())); } } @@ -1320,7 +1320,7 @@ namespace System.Text.RegularExpressions if (capnum <= 9) { - throw MakeException(RegexParseError.UndefinedBackref, SR.Format(SR.UndefinedBackref, capnum.ToString())); + throw MakeException(RegexParseError.UndefinedNumberedReference, SR.Format(SR.UndefinedNumberedReference, capnum.ToString())); } } } @@ -1336,7 +1336,7 @@ namespace System.Text.RegularExpressions return scanOnly ? null : IsCaptureName(capname) ? new RegexNode(RegexNode.Ref, _options, CaptureSlotFromName(capname)) : - throw MakeException(RegexParseError.UndefinedNameRef, SR.Format(SR.UndefinedNameRef, capname)); + throw MakeException(RegexParseError.UndefinedNamedReference, SR.Format(SR.UndefinedNamedReference, capname)); } } @@ -1401,7 +1401,7 @@ namespace System.Text.RegularExpressions int digit = ch - '0'; if (newcapnum > MaxValueDiv10 || (newcapnum == MaxValueDiv10 && digit > MaxValueMod10)) { - throw MakeException(RegexParseError.CaptureGroupOutOfRange, SR.CaptureGroupOutOfRange); + throw MakeException(RegexParseError.QuantifierOrCaptureGroupOutOfRange, SR.QuantifierOrCaptureGroupOutOfRange); } newcapnum = newcapnum * 10 + digit; @@ -1548,7 +1548,7 @@ namespace System.Text.RegularExpressions if (i > MaxValueDiv10 || (i == MaxValueDiv10 && d > MaxValueMod10)) { - throw MakeException(RegexParseError.CaptureGroupOutOfRange, SR.CaptureGroupOutOfRange); + throw MakeException(RegexParseError.QuantifierOrCaptureGroupOutOfRange, SR.QuantifierOrCaptureGroupOutOfRange); } i = (i * 10) + d; @@ -1575,7 +1575,7 @@ namespace System.Text.RegularExpressions if (c > 0) { - throw MakeException(RegexParseError.TooFewHex, SR.TooFewHex); + throw MakeException(RegexParseError.InsufficientOrInvalidHexDigits, SR.InsufficientOrInvalidHexDigits); } return (char)i; @@ -1607,7 +1607,7 @@ namespace System.Text.RegularExpressions { if (CharsRight() == 0) { - throw MakeException(RegexParseError.MissingControl, SR.MissingControl); + throw MakeException(RegexParseError.MissingControlCharacter, SR.MissingControlCharacter); } char ch = RightCharMoveRight(); @@ -1624,7 +1624,7 @@ namespace System.Text.RegularExpressions return ch; } - throw MakeException(RegexParseError.UnrecognizedControl, SR.UnrecognizedControl); + throw MakeException(RegexParseError.UnrecognizedControlCharacter, SR.UnrecognizedControlCharacter); } /// Returns true for options allowed only at the top level @@ -1717,13 +1717,13 @@ namespace System.Text.RegularExpressions { if (CharsRight() < 3) { - throw MakeException(RegexParseError.IncompleteSlashP, SR.IncompleteSlashP); + throw MakeException(RegexParseError.InvalidUnicodePropertyEscape, SR.InvalidUnicodePropertyEscape); } char ch = RightCharMoveRight(); if (ch != '{') { - throw MakeException(RegexParseError.MalformedSlashP, SR.MalformedSlashP); + throw MakeException(RegexParseError.MalformedUnicodePropertyEscape, SR.MalformedUnicodePropertyEscape); } int startpos = Textpos(); @@ -1741,7 +1741,7 @@ namespace System.Text.RegularExpressions if (CharsRight() == 0 || RightCharMoveRight() != '}') { - throw MakeException(RegexParseError.IncompleteSlashP, SR.IncompleteSlashP); + throw MakeException(RegexParseError.InvalidUnicodePropertyEscape, SR.InvalidUnicodePropertyEscape); } return capname; @@ -2176,7 +2176,7 @@ namespace System.Text.RegularExpressions { if (_unit == null) { - throw MakeException(RegexParseError.IllegalCondition, SR.IllegalCondition); + throw MakeException(RegexParseError.AlternationHasMalformedCondition, SR.AlternationHasMalformedCondition); } _group.AddChild(_unit); @@ -2280,7 +2280,7 @@ namespace System.Text.RegularExpressions if (_group.Type == RegexNode.Testref && _group.ChildCount() > 2 || _group.ChildCount() > 3) { - throw MakeException(RegexParseError.TooManyAlternates, SR.TooManyAlternates); + throw MakeException(RegexParseError.AlternationHasTooManyConditions, SR.AlternationHasTooManyConditions); } } else diff --git a/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.cs b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.cs index 849afb7..e4f555b 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.cs @@ -2,27 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; -using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using Xunit; using Xunit.Sdk; namespace System.Text.RegularExpressions.Tests { - public class RegexParserTests + public partial class RegexParserTests { - private static readonly Type s_parseExceptionType; - private static readonly FieldInfo s_parseErrorField; - - static RegexParserTests() - { - if (!PlatformDetection.IsNetFramework) - { - s_parseExceptionType = typeof(Regex).Assembly.GetType("System.Text.RegularExpressions.RegexParseException", true); - s_parseErrorField = s_parseExceptionType.GetField("_error", BindingFlags.NonPublic | BindingFlags.Instance); - } - } - [Theory] // Basic [InlineData("", RegexOptions.None, null)] @@ -30,8 +17,8 @@ namespace System.Text.RegularExpressions.Tests [InlineData(" ", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?#)", RegexOptions.None, null)] [InlineData("(?# )", RegexOptions.None, null)] - [InlineData("(?#", RegexOptions.None, RegexParseError.UnterminatedComment)] - [InlineData("(?# ", RegexOptions.None, RegexParseError.UnterminatedComment)] + [InlineData("(?#", RegexOptions.None, RegexParseError.UnterminatedComment, 3)] + [InlineData("(?# ", RegexOptions.None, RegexParseError.UnterminatedComment, 4)] [InlineData("(?#)(?#)", RegexOptions.None, null)] [InlineData("(?#)(?#)", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?#) (?#)", RegexOptions.None, null)] @@ -42,10 +29,10 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"[a\x00(?#)b]", RegexOptions.None, null)] [InlineData(@"[a\u0000(?#)b]", RegexOptions.None, null)] [InlineData(@"[a\](?#)b]", RegexOptions.None, null)] - [InlineData("(?", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(? ", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData("(? ", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] + [InlineData("(?", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 2)] + [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 2)] + [InlineData("(? ", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData("(? ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 3)] [InlineData("(?i)", RegexOptions.None, null)] [InlineData("(?im)", RegexOptions.None, null)] [InlineData("(?im-x)", RegexOptions.None, null)] @@ -58,12 +45,12 @@ namespace System.Text.RegularExpressions.Tests [InlineData(" (?-x:) ", RegexOptions.IgnorePatternWhitespace, null)] [InlineData(" (?-x: ) ", RegexOptions.IgnorePatternWhitespace, null)] [InlineData(" (?-x: (?+x: ) ) ", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?-x", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?-x ", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?-x :", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?-x )", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?-x :)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData(")", RegexOptions.None, RegexParseError.TooManyParentheses)] + [InlineData("(?-x", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 4)] + [InlineData("(?-x ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData("(?-x :", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData("(?-x )", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData("(?-x :)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(")", RegexOptions.None, RegexParseError.InsufficientOpeningParentheses, 1)] [InlineData("a", RegexOptions.None, null)] [InlineData("ab", RegexOptions.None, null)] [InlineData("a*", RegexOptions.None, null)] @@ -74,8 +61,8 @@ namespace System.Text.RegularExpressions.Tests [InlineData("a??", RegexOptions.None, null)] [InlineData("()", RegexOptions.None, null)] [InlineData("(a)", RegexOptions.None, null)] - [InlineData("(", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(a", RegexOptions.None, RegexParseError.NotEnoughParentheses)] + [InlineData("(", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 1)] + [InlineData("(a", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 2)] [InlineData("|", RegexOptions.None, null)] [InlineData(" |", RegexOptions.None, null)] [InlineData("| ", RegexOptions.None, null)] @@ -89,7 +76,7 @@ namespace System.Text.RegularExpressions.Tests [InlineData("a{0}", RegexOptions.None, null)] [InlineData("a{0,}", RegexOptions.None, null)] [InlineData("a{0,1}", RegexOptions.None, null)] - [InlineData("a{1,0}", RegexOptions.None, RegexParseError.IllegalRange)] + [InlineData("a{1,0}", RegexOptions.None, RegexParseError.ReversedQuantifierRange, 6)] [InlineData("a{0}?", RegexOptions.None, null)] [InlineData("a{0,}?", RegexOptions.None, null)] [InlineData("a{0,1}?", RegexOptions.None, null)] @@ -105,43 +92,43 @@ namespace System.Text.RegularExpressions.Tests [InlineData("a{0,1 }", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("a* ?", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("a* ?", RegexOptions.None, null)] - [InlineData("*", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("(*)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("a**", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData("+", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("(+)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("a*+", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData("?", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("(?)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("a*??", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData("{0}", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("({0})", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData("a*{0}", RegexOptions.None, RegexParseError.NestedQuantify)] + [InlineData("*", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData("(*)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 2)] + [InlineData("a**", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 3)] + [InlineData("+", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData("(+)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 2)] + [InlineData("a*+", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 3)] + [InlineData("?", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData("(?)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 2)] + [InlineData("a*??", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 4)] + [InlineData("{0}", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData("({0})", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 2)] + [InlineData("a*{0}", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 3)] [InlineData("{0", RegexOptions.None, null)] [InlineData("({0)", RegexOptions.None, null)] [InlineData("a*{0", RegexOptions.None, null)] [InlineData(@"\w", RegexOptions.None, null)] [InlineData(@"\b\B\A\G\Z\z\w\W\s\W\s\S\d\D", RegexOptions.None, null)] - [InlineData(@"\c", RegexOptions.None, RegexParseError.MissingControl)] - [InlineData(@"\c<", RegexOptions.None, RegexParseError.UnrecognizedControl)] + [InlineData(@"\c", RegexOptions.None, RegexParseError.MissingControlCharacter, 2)] + [InlineData(@"\c<", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] [InlineData(@"\ca", RegexOptions.None, null)] [InlineData(@"\cA", RegexOptions.None, null)] - [InlineData(@"\c A", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"\c(a)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"\c>", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"\c?", RegexOptions.None, RegexParseError.UnrecognizedControl)] + [InlineData(@"\c A", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] + [InlineData(@"\c(a)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] + [InlineData(@"\c>", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] + [InlineData(@"\c?", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] [InlineData(@"\c@", RegexOptions.None, null)] [InlineData(@"\c^", RegexOptions.None, null)] [InlineData(@"\c_", RegexOptions.None, null)] - [InlineData(@"\c`", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"\c{", RegexOptions.None, RegexParseError.UnrecognizedControl)] + [InlineData(@"\c`", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] + [InlineData(@"\c{", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 3)] [InlineData(@"\cz", RegexOptions.None, null)] [InlineData(@"\cZ", RegexOptions.None, null)] - [InlineData(@"\m", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\x", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\x ", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\x0", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\x0 ", RegexOptions.None, RegexParseError.TooFewHex)] + [InlineData(@"\m", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\x", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\x ", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\x0", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\x0 ", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 4)] [InlineData(@"\x00", RegexOptions.None, null)] [InlineData(@"\x00 ", RegexOptions.None, null)] [InlineData(@"\x000", RegexOptions.None, null)] @@ -149,17 +136,17 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"\xFF", RegexOptions.None, null)] [InlineData(@"\xfF", RegexOptions.None, null)] [InlineData(@"\xfff", RegexOptions.None, null)] - [InlineData(@"\xgg", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\m ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\u", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\u0", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\u00", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\u000", RegexOptions.None, RegexParseError.TooFewHex)] + [InlineData(@"\xgg", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 3)] + [InlineData(@"\m ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\u", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\u0", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\u00", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\u000", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] [InlineData(@"\u0000", RegexOptions.None, null)] [InlineData(@"\u0000 ", RegexOptions.None, null)] - [InlineData(@"\u ", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\u0 ", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"\ugggg", RegexOptions.None, RegexParseError.TooFewHex)] + [InlineData(@"\u ", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\u0 ", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"\ugggg", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 3)] [InlineData(@"\0", RegexOptions.None, null)] [InlineData(@"\0 ", RegexOptions.None, null)] [InlineData(@"\00", RegexOptions.None, null)] @@ -168,45 +155,45 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"\000 ", RegexOptions.None, null)] [InlineData(@"\0000", RegexOptions.None, null)] [InlineData(@"\0000 ", RegexOptions.None, null)] - [InlineData(@"\7", RegexOptions.None, RegexParseError.UndefinedBackref)] + [InlineData(@"\7", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 2)] [InlineData(@"\78", RegexOptions.None, null)] - [InlineData(@"\8", RegexOptions.None, RegexParseError.UndefinedBackref)] + [InlineData(@"\8", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 2)] [InlineData(@"\40", RegexOptions.ECMAScript, null)] [InlineData(@"\401", RegexOptions.ECMAScript, null)] [InlineData(@"\37", RegexOptions.ECMAScript, null)] [InlineData(@"\371", RegexOptions.ECMAScript, null)] [InlineData(@"\0000", RegexOptions.ECMAScript, null)] - [InlineData(@"\k", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"\k ", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"\k<", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"\k< ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\k<0", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\k<0 ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] + [InlineData(@"\k", RegexOptions.None, RegexParseError.MalformedNamedReference, 1)] + [InlineData(@"\k ", RegexOptions.None, RegexParseError.MalformedNamedReference, 3)] + [InlineData(@"\k<", RegexOptions.None, RegexParseError.MalformedNamedReference, 3)] + [InlineData(@"\k< ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\k<0", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\k<0 ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] [InlineData(@"\k<0>", RegexOptions.None, null)] [InlineData(@"\k<0> ", RegexOptions.None, null)] [InlineData(@"\k<00> ", RegexOptions.None, null)] - [InlineData(@"\k ", RegexOptions.None, RegexParseError.UndefinedNameRef)] + [InlineData(@"\k ", RegexOptions.None, RegexParseError.UndefinedNamedReference, 5)] [InlineData(@"(?)\k ", RegexOptions.None, null)] - [InlineData(@"\k", RegexOptions.ECMAScript, RegexParseError.MalformedNameRef)] - [InlineData(@"\k ", RegexOptions.ECMAScript, RegexParseError.MalformedNameRef)] - [InlineData(@"\k<", RegexOptions.ECMAScript, RegexParseError.MalformedNameRef)] + [InlineData(@"\k", RegexOptions.ECMAScript, RegexParseError.MalformedNamedReference, 1)] + [InlineData(@"\k ", RegexOptions.ECMAScript, RegexParseError.MalformedNamedReference, 3)] + [InlineData(@"\k<", RegexOptions.ECMAScript, RegexParseError.MalformedNamedReference, 3)] [InlineData(@"\k< ", RegexOptions.ECMAScript, null)] [InlineData(@"\k<0", RegexOptions.ECMAScript, null)] [InlineData(@"\k<0 ", RegexOptions.ECMAScript, null)] [InlineData(@"\k<0>", RegexOptions.ECMAScript, null)] [InlineData(@"\k<0> ", RegexOptions.ECMAScript, null)] - [InlineData(@"\k'", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"\k' ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\k'0", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\k'0 ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] + [InlineData(@"\k'", RegexOptions.None, RegexParseError.MalformedNamedReference, 3)] + [InlineData(@"\k' ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\k'0", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\k'0 ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] [InlineData(@"\k'0'", RegexOptions.None, null)] [InlineData(@"\k'0' ", RegexOptions.None, null)] [InlineData(@"\k'00' ", RegexOptions.None, null)] - [InlineData(@"\k'a' ", RegexOptions.None, RegexParseError.UndefinedNameRef)] + [InlineData(@"\k'a' ", RegexOptions.None, RegexParseError.UndefinedNamedReference, 5)] [InlineData(@"(?)\k'a' ", RegexOptions.None, null)] - [InlineData(@"\k<0' ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\k'0> ", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"\", RegexOptions.None, RegexParseError.IllegalEndEscape)] + [InlineData(@"\k<0' ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\k'0> ", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"\", RegexOptions.None, RegexParseError.UnescapedEndingBackslash, 1)] [InlineData(@"\ ", RegexOptions.None, null)] [InlineData(@"\<", RegexOptions.None, null)] [InlineData(@"\< ", RegexOptions.None, null)] @@ -215,9 +202,9 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"\<0>", RegexOptions.None, null)] [InlineData(@"\<0> ", RegexOptions.None, null)] [InlineData(@"\<00> ", RegexOptions.None, null)] - [InlineData(@"\ ", RegexOptions.None, RegexParseError.UndefinedNameRef)] + [InlineData(@"\ ", RegexOptions.None, RegexParseError.UndefinedNamedReference, 4)] [InlineData(@"(?)\ ", RegexOptions.None, null)] - [InlineData(@"\", RegexOptions.ECMAScript, RegexParseError.IllegalEndEscape)] + [InlineData(@"\", RegexOptions.ECMAScript, RegexParseError.UnescapedEndingBackslash, 1)] [InlineData(@"\ ", RegexOptions.ECMAScript, null)] [InlineData(@"\<", RegexOptions.ECMAScript, null)] [InlineData(@"\< ", RegexOptions.ECMAScript, null)] @@ -232,77 +219,77 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"\'0'", RegexOptions.None, null)] [InlineData(@"\'0' ", RegexOptions.None, null)] [InlineData(@"\'00' ", RegexOptions.None, null)] - [InlineData(@"\'a' ", RegexOptions.None, RegexParseError.UndefinedNameRef)] + [InlineData(@"\'a' ", RegexOptions.None, RegexParseError.UndefinedNamedReference, 4)] [InlineData(@"(?)\'a' ", RegexOptions.None, null)] [InlineData(@"\<0' ", RegexOptions.None, null)] [InlineData(@"\'0> ", RegexOptions.None, null)] [InlineData("\\p{Cc}", RegexOptions.None, null)] - [InlineData("\\p{ Cc }", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData("\\p{ Cc }", RegexOptions.IgnorePatternWhitespace, RegexParseError.IncompleteSlashP)] - [InlineData("\\p {Cc}", RegexOptions.IgnorePatternWhitespace, RegexParseError.MalformedSlashP)] - [InlineData("\\p{xxx}", RegexOptions.None, RegexParseError.UnknownUnicodeProperty)] - [InlineData("\\p", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData("\\p{", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData("\\p{}", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData("\\p{} ", RegexOptions.None, RegexParseError.UnknownUnicodeProperty)] - [InlineData("\\p {} ", RegexOptions.None, RegexParseError.MalformedSlashP)] - [InlineData("\\p{Cc ", RegexOptions.None, RegexParseError.IncompleteSlashP)] + [InlineData("\\p{ Cc }", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 4)] + [InlineData("\\p{ Cc }", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidUnicodePropertyEscape, 4)] + [InlineData("\\p {Cc}", RegexOptions.IgnorePatternWhitespace, RegexParseError.MalformedUnicodePropertyEscape, 3)] + [InlineData("\\p{xxx}", RegexOptions.None, RegexParseError.UnrecognizedUnicodeProperty, 7)] + [InlineData("\\p", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 2)] + [InlineData("\\p{", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 2)] + [InlineData("\\p{}", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 2)] + [InlineData("\\p{} ", RegexOptions.None, RegexParseError.UnrecognizedUnicodeProperty, 4)] + [InlineData("\\p {} ", RegexOptions.None, RegexParseError.MalformedUnicodePropertyEscape, 3)] + [InlineData("\\p{Cc ", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 6)] [InlineData("\\p{IsArabicPresentationForms-A}", RegexOptions.None, null)] [InlineData("(?:)", RegexOptions.None, null)] [InlineData("(?:a)", RegexOptions.None, null)] - [InlineData("(?:", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(?: ", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?:", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData("(?: ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 4)] [InlineData("(?=)", RegexOptions.None, null)] [InlineData("(?=a)", RegexOptions.None, null)] - [InlineData("(?=", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(?= ", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?=", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData("(?= ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 4)] [InlineData("(?!)", RegexOptions.None, null)] [InlineData("(?!a)", RegexOptions.None, null)] - [InlineData("(?!", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(?! ", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?!", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData("(?! ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 4)] [InlineData("(?>)", RegexOptions.None, null)] [InlineData("(?>a)", RegexOptions.None, null)] - [InlineData("(?>", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(?> ", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?>", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData("(?> ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 4)] [InlineData("(?<=)", RegexOptions.None, null)] [InlineData("(?<=a)", RegexOptions.None, null)] - [InlineData("(?<=", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData("(?<= ", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?<=", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 4)] + [InlineData("(?<= ", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 5)] [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] - [InlineData("(?a", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 5)] + [InlineData("(?a", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 6)] [InlineData("(?a)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?a)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData("(?a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?< a>a)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData("(?< a>a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?< a >a)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData("(?< a >a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] + [InlineData("(?a)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 4)] + [InlineData("(?a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 4)] + [InlineData("(?< a>a)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData("(?< a>a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData("(?< a >a)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData("(?< a >a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 3)] [InlineData("(?a)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<0>a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CapnumNotZero)] + [InlineData("(?<0>a)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupOfZero, 4)] [InlineData("(?<1>a)", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?<10>a)", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?<1>)", RegexOptions.None, null)] [InlineData("(?<1> )", RegexOptions.None, null)] [InlineData("(?<1> )", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?'a')", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?(", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] - [InlineData("(?(0", RegexOptions.IgnorePatternWhitespace, RegexParseError.MalformedReference)] - [InlineData("(?(0)", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] + [InlineData("(?(", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData("(?(0", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasMalformedReference, 4)] + [InlineData("(?(0)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 5)] [InlineData("(?(0))", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(0)a)", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(0)a|)", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(0)a|b)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?(0)a|b|)", RegexOptions.IgnorePatternWhitespace, RegexParseError.TooManyAlternates)] - [InlineData("(?(0)a|b|c)", RegexOptions.IgnorePatternWhitespace, RegexParseError.TooManyAlternates)] - [InlineData("(?(0 )", RegexOptions.IgnorePatternWhitespace, RegexParseError.MalformedReference)] - [InlineData("(?(1))", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedReference)] + [InlineData("(?(0)a|b|)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasTooManyConditions, 10)] + [InlineData("(?(0)a|b|c)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasTooManyConditions, 11)] + [InlineData("(?(0 )", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasMalformedReference, 5)] + [InlineData("(?(1))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasUndefinedReference, 5)] [InlineData("(?(00))", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(a))", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?)(?(a))", RegexOptions.IgnorePatternWhitespace, null)] @@ -310,20 +297,20 @@ namespace System.Text.RegularExpressions.Tests [InlineData("(?)(?( a))", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(()a()))", RegexOptions.None, null)] [InlineData("(?((?)a(?)))", RegexOptions.None, null)] - [InlineData("(?(?'", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantCapture)] - [InlineData("(?(?'x'))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantCapture)] - [InlineData("(?(?#", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnterminatedComment)] - [InlineData("(?(?#)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantHaveComment)] - [InlineData("(?(?#))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantHaveComment)] - [InlineData("(?(?<", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantCapture)] - [InlineData("(?(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantCapture)] - [InlineData("(?(?))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationCantCapture)] + [InlineData("(?(?'", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasNamedCapture, 2)] + [InlineData("(?(?'x'))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasNamedCapture, 2)] + [InlineData("(?(?#", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnterminatedComment, 5)] + [InlineData("(?(?#)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasComment, 2)] + [InlineData("(?(?#))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasComment, 2)] + [InlineData("(?(?<", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData("(?(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasNamedCapture, 2)] + [InlineData("(?(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasNamedCapture, 2)] + [InlineData("(?(?))", RegexOptions.IgnorePatternWhitespace, RegexParseError.AlternationHasNamedCapture, 2)] [InlineData("(?(?<=))", RegexOptions.IgnorePatternWhitespace, null)] [InlineData("(?(?]", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"[\c>-\c<]", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"[\c>-a]", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"[a-\c>]", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"[a--]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\c<-\c>]", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 4)] + [InlineData(@"[\c>-\c<]", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 4)] + [InlineData(@"[\c>-a]", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 4)] + [InlineData(@"[a-\c>]", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 6)] + [InlineData(@"[a--]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 4)] [InlineData(@"[--a]", RegexOptions.None, null)] [InlineData(@"[\--a]", RegexOptions.None, null)] [InlineData(@"[\0-\1]", RegexOptions.None, null)] - [InlineData(@"[\1-\0]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\1-\0]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 6)] [InlineData(@"[\0-\01]", RegexOptions.None, null)] - [InlineData(@"[\01-\0]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\01-\0]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] [InlineData(@"[[:x:]-a]", RegexOptions.None, null)] [InlineData(@"[a-[:x:]]", RegexOptions.None, null)] [InlineData(@"[\0-\ca]", RegexOptions.None, null)] - [InlineData(@"[\ca-\0]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\ca-\0]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] [InlineData(@"[\ca-\cA]", RegexOptions.None, null)] [InlineData(@"[\cA-\ca]", RegexOptions.None, null)] - [InlineData(@"[\u0-\u1]", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"[\u1-\u0]", RegexOptions.None, RegexParseError.TooFewHex)] + [InlineData(@"[\u0-\u1]", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 5)] + [InlineData(@"[\u1-\u0]", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 5)] [InlineData(@"[\u0000-\u0000]", RegexOptions.None, null)] [InlineData(@"[\u0000-\u0001]", RegexOptions.None, null)] - [InlineData(@"[\u0001-\u0000]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\u0001-\u0000]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 14)] [InlineData(@"[\u0001-a]", RegexOptions.None, null)] - [InlineData(@"[a-\u0001]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[a-\u0001]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 9)] [InlineData(@"[a-a]", RegexOptions.None, null)] - [InlineData(@"[a-A]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[a-A]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 4)] [InlineData(@"[A-a]", RegexOptions.None, null)] [InlineData(@"[a-a]", RegexOptions.IgnoreCase, null)] - [InlineData(@"[a-A]", RegexOptions.IgnoreCase, RegexParseError.ReversedCharRange)] + [InlineData(@"[a-A]", RegexOptions.IgnoreCase, RegexParseError.ReversedCharacterRange, 4)] [InlineData(@"[A-a]", RegexOptions.IgnoreCase, null)] [InlineData(@"[a-\x61]", RegexOptions.None, null)] [InlineData(@"[\x61-a]", RegexOptions.None, null)] - [InlineData(@"[a-\x60]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[\x62-a]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[a-\x60]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] + [InlineData(@"[\x62-a]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] [InlineData(@"[a-\x62]", RegexOptions.None, null)] [InlineData(@"[\3-\cc]", RegexOptions.None, null)] [InlineData(@"[\cc-\3]", RegexOptions.None, null)] [InlineData(@"[\2-\cc]", RegexOptions.None, null)] - [InlineData(@"[\cc-\2]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[\4-\cc]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\cc-\2]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] + [InlineData(@"[\4-\cc]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 7)] [InlineData(@"[\cc-\4]", RegexOptions.None, null)] [InlineData(@"[\ca-\cb]", RegexOptions.None, null)] [InlineData(@"[\ca-\cB]", RegexOptions.None, null)] [InlineData(@"[\cA-\cb]", RegexOptions.None, null)] [InlineData(@"[\cA-\cB]", RegexOptions.None, null)] - [InlineData(@"[\cb-\ca]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[\cb-\cA]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[\cB-\ca]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[\cB-\cA]", RegexOptions.None, RegexParseError.ReversedCharRange)] + [InlineData(@"[\cb-\ca]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 8)] + [InlineData(@"[\cb-\cA]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 8)] + [InlineData(@"[\cB-\ca]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 8)] + [InlineData(@"[\cB-\cA]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 8)] [InlineData(@"[\--#]", RegexOptions.None, null)] - [InlineData(@"[b-\-a]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[b-\-\-a]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"()\2", RegexOptions.None, RegexParseError.UndefinedBackref)] + [InlineData(@"[b-\-a]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[b-\-\-a]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"()\2", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 4)] [InlineData(@"()()\2", RegexOptions.None, null)] - [InlineData(@"()\1", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] - [InlineData(@"()\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] - [InlineData(@"()()\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"()\1", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 4)] + [InlineData(@"()\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 4)] + [InlineData(@"()()\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 6)] [InlineData(@"()()(?n)\1\2", RegexOptions.None, null)] - [InlineData(@"()(?n)()\1\2", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"(?n)()()\1\2", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"()()(?n)\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] - [InlineData(@"()(?n)()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] - [InlineData(@"(?n)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"()(?n)()\1\2", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 12)] + [InlineData(@"(?n)()()\1\2", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 10)] + [InlineData(@"()()(?n)\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 10)] + [InlineData(@"()(?n)()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 10)] + [InlineData(@"(?n)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 10)] [InlineData(@"()()(?-n)\1\2", RegexOptions.None, null)] [InlineData(@"()(?-n)()\1\2", RegexOptions.None, null)] [InlineData(@"(?-n)()()\1\2", RegexOptions.None, null)] - [InlineData(@"()()(?-n)\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] - [InlineData(@"()(?-n)()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"()()(?-n)\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 11)] + [InlineData(@"()(?-n)()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 13)] [InlineData(@"(?-n)()()\1\2", RegexOptions.ExplicitCapture, null)] [InlineData(@"()()(?n:\1\2)", RegexOptions.None, null)] - [InlineData(@"()()(?n:\1\2)", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"()()(?n:\1\2)", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 10)] [InlineData(@"()()(?-n:\1\2)", RegexOptions.None, null)] - [InlineData(@"()()(?-n:\1\2)", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"()()(?-n:\1\2)", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 11)] [InlineData(@"(?n:)()()\1\2", RegexOptions.None, null)] - [InlineData(@"(?n:)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"(?n:)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 11)] [InlineData(@"(?-n:)()()\1\2", RegexOptions.None, null)] - [InlineData(@"(?-n:)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"(?-n:)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 12)] [InlineData(@"(?n)(?-n)()()\1\2", RegexOptions.None, null)] [InlineData(@"(?n)(?-n)()()\1\2", RegexOptions.ExplicitCapture, null)] - [InlineData(@"(?-n)(?n)()()\1\2", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"(?-n)(?n)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedBackref)] + [InlineData(@"(?-n)(?n)()()\1\2", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 15)] + [InlineData(@"(?-n)(?n)()()\1\2", RegexOptions.ExplicitCapture, RegexParseError.UndefinedNumberedReference, 15)] // References [InlineData(@"[aeiou]", RegexOptions.None, null)] [InlineData(@"(?\w+)\s\k\W(?\w+)", RegexOptions.None, null)] @@ -474,7 +461,7 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"[\p{IsBasicLatin}-[\x00-\x7F]]", RegexOptions.None, null)] [InlineData(@"[\u0000-\uFFFF-[\s\p{P}\p{IsGreek}\x85]]", RegexOptions.None, null)] [InlineData(@"[a-z-[d-w-[m-o]]]", RegexOptions.None, null)] - [InlineData(@"((\w+(\s?)){2,}", RegexOptions.None, RegexParseError.NotEnoughParentheses)] + [InlineData(@"((\w+(\s?)){2,}", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 15)] [InlineData(@"[a-z-[djp]]", RegexOptions.None, null)] [InlineData(@"(\w)\1+.\b", RegexOptions.None, null)] [InlineData(@"\d{4}\b", RegexOptions.None, null)] @@ -578,258 +565,173 @@ namespace System.Text.RegularExpressions.Tests [InlineData(@"\bgr[ae]y\b", RegexOptions.None, null)] [InlineData(@"\b((?# case sensitive comparison)D\w+)\s(?ixn)((?#case insensitive comparison)d\w+)\b", RegexOptions.None, null)] [InlineData(@"\{\d+(,-*\d+)*(\:\w{1,4}?)*\}(?x) # Looks for a composite format item.", RegexOptions.None, null)] - // Negative tests - [InlineData(@"cat([a-\d]*)dog", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"\k<1", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"(?')", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"(?<)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"(?imn )", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?imn", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?'cat'", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"(?'", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?'=)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?'!)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"[^", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"[cat", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"[^cat", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"\p{cat", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"\k", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"\P{", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"\k<>", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"(?(", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"(?()|", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"?(a|b)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"?((a)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"?((a)a", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"?((a)a|", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"?((a)a|b", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"?(a)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"[a", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"?(a:b)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"(?(?", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(cat", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"(?(cat)|", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - [InlineData(@"foo(?<0>bar)", RegexOptions.None, RegexParseError.CapnumNotZero)] - [InlineData(@"foo(?'0'bar)", RegexOptions.None, RegexParseError.CapnumNotZero)] - [InlineData(@"foo(?<1bar)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"foo(?'1bar)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"\p{klsak", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"(?c:cat)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(??e:cat)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"[a-f-[]]+", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"[A-[]+", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData(@"(?(?e))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?a)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?r:cat)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"\x2", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"(cat) (?#cat) \s+ (?#followed by 1 or more whitespace", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnterminatedComment)] - [InlineData(@"cat(?(?afdcat)dog)", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"cat(?(?cat)dog)", RegexOptions.None, RegexParseError.AlternationCantCapture)] - [InlineData(@"cat(?(?'cat'cat)dog)", RegexOptions.None, RegexParseError.AlternationCantCapture)] - [InlineData(@"cat(?(?#COMMENT)cat)", RegexOptions.None, RegexParseError.AlternationCantHaveComment)] - [InlineData(@"cat(?<>dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?<1dog>dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"cat(?<0>dog)", RegexOptions.None, RegexParseError.CapnumNotZero)] - [InlineData(@"([5-\D]*)dog", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"cat([6-\s]*)dog", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"cat([c-\S]*)", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"cat([7-\w]*)", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"cat([a-\W]*)dog", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"([f-\p{Lu}]\w*)\s([\p{Lu}]\w*)", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"(cat) (?#cat) \s+ (?#followed by 1 or more whitespace", RegexOptions.None, RegexParseError.UnterminatedComment)] - [InlineData(@"([1-\P{Ll}][\p{Ll}]*)\s([\P{Ll}][\p{Ll}]*)", RegexOptions.None, RegexParseError.BadClassInCharRange)] - [InlineData(@"[\P]", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"([\pcat])", RegexOptions.None, RegexParseError.MalformedSlashP)] - [InlineData(@"([\Pcat])", RegexOptions.None, RegexParseError.MalformedSlashP)] - [InlineData(@"(\p{", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"(\p{Ll", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"(cat)([\o]*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedEscape)] - [InlineData(@"[\p]", RegexOptions.None, RegexParseError.IncompleteSlashP)] - [InlineData(@"(?cat)\s+(?dog)\kcat", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"(?cat)\s+(?dog)\k", RegexOptions.None, RegexParseError.UndefinedNameRef)] - [InlineData(@"(?cat)\s+(?dog)\k<8>cat", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"^[abcd]{1}?*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]*+$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]+*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]?*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]*?+$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]+?*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]{1,}?*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]??*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]+{0,5}$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]?{0,5}$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"\ua", RegexOptions.None, RegexParseError.TooFewHex)] - [InlineData(@"^[abcd]*{0,5}$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]{0,16}?*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"^[abcd]{1,}*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"(?cat)\s+(?dog)\k<8>cat", RegexOptions.ECMAScript, RegexParseError.UndefinedBackref)] - [InlineData(@"(?cat)\s+(?dog)\k8", RegexOptions.None, RegexParseError.MalformedNameRef)] - [InlineData(@"(?cat)\s+(?dog)\k8", RegexOptions.ECMAScript, RegexParseError.MalformedNameRef)] - [InlineData(@"(cat)(\7)", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"(cat)\s+(?<2147483648>dog)", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - [InlineData(@"(cat)\s+(?<21474836481097>dog)", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - [InlineData(@"^[abcd]{1}*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"(cat)(\c*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"(cat)(\c *)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"(cat)(\c?*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"(cat)(\c`*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"(cat)(\c\|*)(dog)", RegexOptions.None, RegexParseError.QuantifyAfterNothing)] - [InlineData(@"^[abcd]{0,16}*$", RegexOptions.None, RegexParseError.NestedQuantify)] - [InlineData(@"(cat)\c", RegexOptions.None, RegexParseError.MissingControl)] - // Deep recursion - [InlineData(@"@""(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((""", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - // Scan control - [InlineData("(cat)(\\c\0*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControl)] - [InlineData(@"(cat)(\c\[*)(dog)", RegexOptions.None, RegexParseError.UnterminatedBracket)] - // Invalid grouping constructs - [InlineData("(?<", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?>-", RegexOptions.None, RegexParseError.NotEnoughParentheses)] - // Testgroup with options - [InlineData("())", RegexOptions.None, RegexParseError.TooManyParentheses)] - [InlineData("[a-z-[aeiuo]", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData("[a-z-[aeiuo", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData("[a-z-[b]", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData("[a-z-[b", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData("[b-a]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a-c]{2,1}", RegexOptions.None, RegexParseError.IllegalRange)] - [InlineData(@"\d{2147483648}", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - [InlineData("[a-z-[b][", RegexOptions.None, RegexParseError.UnterminatedBracket)] - [InlineData("(?()|||||)", RegexOptions.None, RegexParseError.TooManyAlternates)] - [InlineData("[^]", RegexOptions.None, RegexParseError.UnterminatedBracket)] - public void Parse(string pattern, RegexOptions options, object errorObj) + public void Parse(string pattern, RegexOptions options, object errorObj, int offset = -1) { RegexParseError? error = (RegexParseError?)errorObj; + Assert.True(error == null || offset > 0, "All tests must be given positive offsets, or null if no offset should be tested."); + // Parse the main tree and if parsing fails check if the supplied error matches. - ParseTree(pattern, options, error); + ParseTree(pattern, options, error, offset); // Assert that only ArgumentException might be thrown during parsing. ParseSubTrees(pattern, options); } [Theory] - [InlineData(@"[a-\-]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a-\-b]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a-\-\-b]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a-\-\D]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a-\-\-\D]", RegexOptions.None, RegexParseError.ReversedCharRange)] - [InlineData(@"[a -\-\b]", RegexOptions.None, null)] - // OutOfMemoryException - [InlineData("a{2147483647}", RegexOptions.None, null)] - [InlineData("a{2147483647,}", RegexOptions.None, null)] - [InlineData(@"(?(?N))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?i))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?I))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?M))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?s))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?S))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?x))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?X))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?n))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(" (?(?n))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"(?(?m))", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - // IndexOutOfRangeException - [InlineData("(?<-", RegexOptions.None, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?<-", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData(@"^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$", RegexOptions.None, null)] - [InlineData(@"((?'Close-Open'>)[^<>]*)+", RegexOptions.None, RegexParseError.UndefinedNameRef)] - [InlineData(@"(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*", RegexOptions.None, null)] - [InlineData(@"(?'Close-Open'>)", RegexOptions.None, RegexParseError.UndefinedNameRef)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)()(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("()(?)(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("()()(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?)(?)(?<-1>)(?<-2>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-4>)(?<4>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<4>)(?<-4>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)(?<-a>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-a>)(?)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?<-1>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("()(?<-1>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-1>)()", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-00>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)(?)(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()()", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)()", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedBackref)] - [InlineData("(?)(?)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)(?<-a>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-0>)", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-0 >)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?<- 0 >)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?<- 0>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?'-0')", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?'a-0')", RegexOptions.IgnorePatternWhitespace, null)] - [InlineData("(?<-0", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnrecognizedGrouping)] - [InlineData("(?<-0)", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupName)] - [InlineData("(?<-0>", RegexOptions.IgnorePatternWhitespace, RegexParseError.NotEnoughParentheses)] - [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.UndefinedNameRef)] - [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.UndefinedBackref)] - [InlineData(@"cat(?<->dog)", RegexOptions.None, RegexParseError.InvalidGroupName)] - [InlineData("a{2147483648}", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - [InlineData("a{2147483648,}", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - [InlineData("a{0,2147483647}", RegexOptions.None, null)] - [InlineData("a{0,2147483648}", RegexOptions.None, RegexParseError.CaptureGroupOutOfRange)] - // Surrogate pair which is parsed as [char,char-char,char] as we operate on UTF-16 code units. - [InlineData("[\uD82F\uDCA0-\uD82F\uDCA3]", RegexOptions.IgnoreCase, RegexParseError.ReversedCharRange)] - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] - public void Parse_NotNetFramework(string pattern, RegexOptions options, object error) - { - Parse(pattern, options, error); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] - [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] - public void RegexParseException_Serializes() + // Negative tests + [InlineData(@"cat([a-\d]*)dog", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 9)] + [InlineData(@"\k<1", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"(?')", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData(@"(?<)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 3)] + [InlineData(@"(?imn )", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 6)] + [InlineData(@"(?imn", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?'cat'", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 7)] + [InlineData(@"(?'", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData(@"(?'=)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 4)] + [InlineData(@"(?'!)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 4)] + [InlineData(@"[^", RegexOptions.None, RegexParseError.UnterminatedBracket, 2)] + [InlineData(@"[cat", RegexOptions.None, RegexParseError.UnterminatedBracket, 4)] + [InlineData(@"[^cat", RegexOptions.None, RegexParseError.UnterminatedBracket, 5)] + [InlineData(@"\p{cat", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 6)] + [InlineData(@"\k", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 7)] + [InlineData(@"\P{", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 2)] + [InlineData(@"\k<>", RegexOptions.None, RegexParseError.UnrecognizedEscape, 2)] + [InlineData(@"(?(", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 3)] + [InlineData(@"(?()|", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 5)] + [InlineData(@"?(a|b)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"?((a)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"?((a)a", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"?((a)a|", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"?((a)a|b", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"?(a)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"[a", RegexOptions.None, RegexParseError.UnterminatedBracket, 2)] + [InlineData(@"?(a:b)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData(@"(?(?", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 4)] + [InlineData(@"(?(cat", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 6)] + [InlineData(@"(?(cat)|", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 8)] + [InlineData(@"foo(?<0>bar)", RegexOptions.None, RegexParseError.CaptureGroupOfZero, 7)] + [InlineData(@"foo(?'0'bar)", RegexOptions.None, RegexParseError.CaptureGroupOfZero, 7)] + [InlineData(@"foo(?<1bar)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 7)] + [InlineData(@"foo(?'1bar)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 7)] + [InlineData(@"\p{klsak", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 8)] + [InlineData(@"(?c:cat)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData(@"(??e:cat)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData(@"[a-f-[]]+", RegexOptions.None, RegexParseError.UnterminatedBracket, 9)] + [InlineData(@"[A-[]+", RegexOptions.None, RegexParseError.UnterminatedBracket, 6)] + [InlineData(@"(?(?e))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?a)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?r:cat)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData(@"\x2", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"(cat) (?#cat) \s+ (?#followed by 1 or more whitespace", RegexOptions.IgnorePatternWhitespace, RegexParseError.UnterminatedComment, 56)] + [InlineData(@"cat(?(?afdcat)dog)", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 8)] + [InlineData(@"cat(?(?cat)dog)", RegexOptions.None, RegexParseError.AlternationHasNamedCapture, 5)] + [InlineData(@"cat(?(?'cat'cat)dog)", RegexOptions.None, RegexParseError.AlternationHasNamedCapture, 5)] + [InlineData(@"cat(?(?#COMMENT)cat)", RegexOptions.None, RegexParseError.AlternationHasComment, 5)] + [InlineData(@"cat(?<>dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 6)] + [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 9)] + [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 9)] + [InlineData(@"cat(?)_*>dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 9)] + [InlineData(@"cat(?dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 9)] + [InlineData(@"cat(?<1dog>dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 7)] + [InlineData(@"cat(?<0>dog)", RegexOptions.None, RegexParseError.CaptureGroupOfZero, 7)] + [InlineData(@"([5-\D]*)dog", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 6)] + [InlineData(@"cat([6-\s]*)dog", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 9)] + [InlineData(@"cat([c-\S]*)", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 9)] + [InlineData(@"cat([7-\w]*)", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 9)] + [InlineData(@"cat([a-\W]*)dog", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 9)] + [InlineData(@"([f-\p{Lu}]\w*)\s([\p{Lu}]\w*)", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 6)] + [InlineData(@"(cat) (?#cat) \s+ (?#followed by 1 or more whitespace", RegexOptions.None, RegexParseError.UnterminatedComment, 56)] + [InlineData(@"([1-\P{Ll}][\p{Ll}]*)\s([\P{Ll}][\p{Ll}]*)", RegexOptions.None, RegexParseError.ShorthandClassInCharacterRange, 6)] + [InlineData(@"[\P]", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 3)] + [InlineData(@"([\pcat])", RegexOptions.None, RegexParseError.MalformedUnicodePropertyEscape, 5)] + [InlineData(@"([\Pcat])", RegexOptions.None, RegexParseError.MalformedUnicodePropertyEscape, 5)] + [InlineData(@"(\p{", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 3)] + [InlineData(@"(\p{Ll", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 6)] + [InlineData(@"(cat)([\o]*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedEscape, 9)] + [InlineData(@"[\p]", RegexOptions.None, RegexParseError.InvalidUnicodePropertyEscape, 3)] + [InlineData(@"(?cat)\s+(?dog)\kcat", RegexOptions.None, RegexParseError.MalformedNamedReference, 28)] + [InlineData(@"(?cat)\s+(?dog)\k", RegexOptions.None, RegexParseError.UndefinedNamedReference, 33)] + [InlineData(@"(?cat)\s+(?dog)\k<8>cat", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 30)] + [InlineData(@"^[abcd]{1}?*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 12)] + [InlineData(@"^[abcd]*+$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"^[abcd]+*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"^[abcd]?*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"^[abcd]*?+$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 10)] + [InlineData(@"^[abcd]+?*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 10)] + [InlineData(@"^[abcd]{1,}?*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 13)] + [InlineData(@"^[abcd]??*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 10)] + [InlineData(@"^[abcd]+{0,5}$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"^[abcd]?{0,5}$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"\ua", RegexOptions.None, RegexParseError.InsufficientOrInvalidHexDigits, 2)] + [InlineData(@"^[abcd]*{0,5}$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 9)] + [InlineData(@"^[abcd]{0,16}?*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 15)] + [InlineData(@"^[abcd]{1,}*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 12)] + [InlineData(@"(?cat)\s+(?dog)\k<8>cat", RegexOptions.ECMAScript, RegexParseError.UndefinedNumberedReference, 30)] + [InlineData(@"(?cat)\s+(?dog)\k8", RegexOptions.None, RegexParseError.MalformedNamedReference, 28)] + [InlineData(@"(?cat)\s+(?dog)\k8", RegexOptions.ECMAScript, RegexParseError.MalformedNamedReference, 28)] + [InlineData(@"(cat)(\7)", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 8)] + [InlineData(@"(cat)\s+(?<2147483648>dog)", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 21)] + [InlineData(@"(cat)\s+(?<21474836481097>dog)", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 21)] + [InlineData(@"^[abcd]{1}*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 11)] + [InlineData(@"(cat)(\c*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 9)] + [InlineData(@"(cat)(\c *)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 9)] + [InlineData(@"(cat)(\c?*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 9)] + [InlineData(@"(cat)(\c`*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 9)] + [InlineData(@"(cat)(\c\|*)(dog)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 11)] + [InlineData(@"^[abcd]{0,16}*$", RegexOptions.None, RegexParseError.NestedQuantifiersNotParenthesized, 14)] + [InlineData(@"(cat)\c", RegexOptions.None, RegexParseError.MissingControlCharacter, 7)] + // Deep recursion + [InlineData(@"((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + +"(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 1183)] + // Scan control + [InlineData("(cat)(\\c\0*)(dog)", RegexOptions.None, RegexParseError.UnrecognizedControlCharacter, 9)] + [InlineData(@"(cat)(\c\[*)(dog)", RegexOptions.None, RegexParseError.UnterminatedBracket, 17)] + // Invalid grouping constructs + [InlineData("(?<", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData("(?>-", RegexOptions.None, RegexParseError.InsufficientClosingParentheses, 4)] + // Testgroup with options + [InlineData("())", RegexOptions.None, RegexParseError.InsufficientOpeningParentheses, 3)] + [InlineData("[a-z-[aeiuo]", RegexOptions.None, RegexParseError.UnterminatedBracket, 12)] + [InlineData("[a-z-[aeiuo", RegexOptions.None, RegexParseError.UnterminatedBracket, 11)] + [InlineData("[a-z-[b]", RegexOptions.None, RegexParseError.UnterminatedBracket, 8)] + [InlineData("[a-z-[b", RegexOptions.None, RegexParseError.UnterminatedBracket, 7)] + [InlineData("[b-a]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 4)] + [InlineData(@"[a-c]{2,1}", RegexOptions.None, RegexParseError.ReversedQuantifierRange, 10)] + [InlineData(@"\d{2147483648}", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 13)] + [InlineData("[a-z-[b][", RegexOptions.None, RegexParseError.UnterminatedBracket, 9)] + [InlineData("(?()|||||)", RegexOptions.None, RegexParseError.AlternationHasTooManyConditions, 10)] + [InlineData("[^]", RegexOptions.None, RegexParseError.UnterminatedBracket, 3)] + [InlineData("\\", RegexOptions.None, RegexParseError.UnescapedEndingBackslash, 1)] + [InlineData("??", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 1)] + [InlineData("(?=*)", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 4)] + [InlineData("((((((*))))))", RegexOptions.None, RegexParseError.QuantifierAfterNothing, 7)] + public void ParseCheckOffset(string pattern, RegexOptions options, object errorObj, int offset) { -#pragma warning disable RE0001 // Regex issue: Not enough )'s - ArgumentException e = Assert.ThrowsAny(() => new Regex("(abc|def")); -#pragma warning restore RE0001 // Regex issue: Not enough )'s + RegexParseError? error = (RegexParseError?)errorObj; - var bf = new BinaryFormatter(); - var s = new MemoryStream(); - bf.Serialize(s, e); - s.Position = 0; + // Parse the main tree and if parsing fails check if the supplied error matches. + ParseTree(pattern, options, error, offset); - ArgumentException e2 = (ArgumentException)bf.Deserialize(s); - Assert.Equal(e.Message, e2.Message); + // Assert that only ArgumentException might be thrown during parsing. + ParseSubTrees(pattern, options); } + private static void ParseSubTrees(string pattern, RegexOptions options) { // Trim the input from the right and make sure tree invariants hold @@ -851,11 +753,11 @@ namespace System.Text.RegularExpressions.Tests } } - private static void ParseTree(string pattern, RegexOptions options, RegexParseError? error) + static void ParseTree(string pattern, RegexOptions options, RegexParseError? error, int offset) { if (error != null) { - Throws(error.Value, () => new Regex(pattern, options)); + Throws(error.Value, offset, () => new Regex(pattern, options)); return; } @@ -875,45 +777,6 @@ namespace System.Text.RegularExpressions.Tests } } - /// - /// Checks if action throws either a RegexParseException or an ArgumentException depending on the - /// environment and the supplied error. - /// - /// The expected parse error - /// The action to invoke. - private static void Throws(RegexParseError error, Action action) - { - // If no specific error is supplied, or we are running on .NET Framework where RegexParseException doesn't exist - // we expect an ArgumentException. - if (PlatformDetection.IsNetFramework) - { - Assert.ThrowsAny(action); - return; - } - - try - { - action(); - } - catch (ArgumentException e) - { - // We use reflection to check if the exception is an internal RegexParseException - // and extract its error property and compare with the given one. - if (e.GetType() == s_parseExceptionType) - { - RegexParseError regexParseError = (RegexParseError)s_parseErrorField.GetValue(e); - - // Success if provided error matches. - if (error == regexParseError) - return; - - throw new XunitException($"Expected RegexParseException with error: ({error}) -> Actual error: {regexParseError})"); - } - - throw new XunitException($"Expected RegexParseException -> Actual: ({e.GetType()})"); - } - - throw new XunitException($"Expected RegexParseException with error: ({error}) -> Actual: No exception thrown"); - } + static partial void Throws(RegexParseError error, int offset, Action action); } } diff --git a/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netcoreapp.cs b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netcoreapp.cs new file mode 100644 index 0000000..349ec28 --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netcoreapp.cs @@ -0,0 +1,150 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using Xunit; +using Xunit.Sdk; + +namespace System.Text.RegularExpressions.Tests +{ + public partial class RegexParserTests + { + [Theory] + [InlineData(@"[a-\-]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[a-\-b]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[a-\-\-b]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[a-\-\D]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[a-\-\-\D]", RegexOptions.None, RegexParseError.ReversedCharacterRange, 5)] + [InlineData(@"[a -\-\b]", RegexOptions.None, null, 5)] + // OutOfMemoryException + [InlineData("a{2147483647}", RegexOptions.None, null)] + [InlineData("a{2147483647,}", RegexOptions.None, null)] + [InlineData(@"(?(?N))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?i))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?I))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?M))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?s))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?S))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?x))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?X))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?n))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData(@"(?(?m))", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 5)] + // IndexOutOfRangeException + [InlineData("(?<-", RegexOptions.None, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData("(?<-", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 3)] + [InlineData(@"^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$", RegexOptions.None, null)] + [InlineData(@"((?'Close-Open'>)[^<>]*)+", RegexOptions.None, RegexParseError.UndefinedNamedReference, 14)] + [InlineData(@"(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*", RegexOptions.None, null)] + [InlineData(@"(?'Close-Open'>)", RegexOptions.None, RegexParseError.UndefinedNamedReference, 13)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)()(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 34)] + [InlineData("()(?)(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 34)] + [InlineData("()()(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 30)] + [InlineData("(?)(?)(?<-1>)(?<-2>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-4>)(?<4>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<4>)(?<-4>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)(?<-a>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-a>)(?)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 7)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 6)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 5)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 5)] + [InlineData("(?<-1>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 5)] + [InlineData("()(?<-1>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-1>)()", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-00>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)(?)(?<-0>)(?<-1>)(?<-2>)(?<-3>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 38)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()()", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 26)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 19)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)()(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 26)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)()", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 26)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)(?", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 19)] + [InlineData("(?<-0>)(?<-1>)(?<-2>)(?<-3>)(?)(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.UndefinedNumberedReference, 26)] + [InlineData("(?)(?)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)(?<-a>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-0>)", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-0 >)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 5)] + [InlineData("(?<- 0 >)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 4)] + [InlineData("(?<- 0>)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 4)] + [InlineData("(?)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 6)] + [InlineData("(?'-0')", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?'a-0')", RegexOptions.IgnorePatternWhitespace, null)] + [InlineData("(?<-0", RegexOptions.IgnorePatternWhitespace, RegexParseError.InvalidGroupingConstruct, 5)] + [InlineData("(?<-0)", RegexOptions.IgnorePatternWhitespace, RegexParseError.CaptureGroupNameInvalid, 5)] + [InlineData("(?<-0>", RegexOptions.IgnorePatternWhitespace, RegexParseError.InsufficientClosingParentheses, 6)] + [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 21)] + [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.UndefinedNamedReference, 27)] + [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 22)] + [InlineData(@"(?cat)\w+(?dog)", RegexOptions.None, RegexParseError.UndefinedNumberedReference, 23)] + [InlineData(@"cat(?<->dog)", RegexOptions.None, RegexParseError.CaptureGroupNameInvalid, 7)] + [InlineData("a{2147483648}", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 12)] + [InlineData("a{2147483648,}", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 12)] + [InlineData("a{0,2147483647}", RegexOptions.None, null)] + [InlineData("a{0,2147483648}", RegexOptions.None, RegexParseError.QuantifierOrCaptureGroupOutOfRange, 14)] + // Surrogate pair which is parsed as [char,char-char,char] as we operate on UTF-16 code units. + [InlineData("[\uD82F\uDCA0-\uD82F\uDCA3]", RegexOptions.IgnoreCase, RegexParseError.ReversedCharacterRange, 5)] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] + public void Parse_Netcoreapp(string pattern, RegexOptions options, object error, int offset = -1) + { + Parse(pattern, options, error, offset); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] + public void RegexParseException_Serializes() + { +#pragma warning disable RE0001 // Regex issue: Not enough )'s + ArgumentException e = Assert.ThrowsAny(() => new Regex("(abc|def")); +#pragma warning restore RE0001 // Regex issue: Not enough )'s + + var bf = new BinaryFormatter(); + var s = new MemoryStream(); + bf.Serialize(s, e); + s.Position = 0; + + object deserialized = bf.Deserialize(s); + Assert.IsType(deserialized); + ArgumentException e2 = (ArgumentException)deserialized; + Assert.Equal(e.Message, e2.Message); + } + + /// + /// Checks if action throws either a RegexParseException or an ArgumentException depending on the + /// environment and the supplied error. + /// + /// The expected parse error + /// The action to invoke. + static partial void Throws(RegexParseError error, int offset, Action action) + { + try + { + action(); + } + catch (RegexParseException e) + { + RegexParseError regexParseError = e.Error; + + // Success if provided error matches and offset is correct. + if (error == regexParseError) + { + Assert.Equal(offset, e.Offset); + return; + } + + throw new XunitException($"Expected RegexParseException with error: ({error}) -> Actual error: {regexParseError})"); + } + catch (Exception e) + { + throw new XunitException($"Expected RegexParseException -> Actual: ({e})"); + } + + throw new XunitException($"Expected RegexParseException with error: ({error}) -> Actual: No exception thrown"); + } + } +} diff --git a/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netfx.cs b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netfx.cs new file mode 100644 index 0000000..4e9006e --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/tests/RegexParserTests.netfx.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using Xunit; +using Xunit.Sdk; + +namespace System.Text.RegularExpressions.Tests +{ + public partial class RegexParserTests + { + /// + /// Checks if action throws either a RegexParseException or an ArgumentException depending on the + /// environment and the supplied error. + /// + /// The expected parse error + /// The action to invoke. + static partial void Throws(RegexParseError error, int offset, Action action) + { + try + { + action(); + } + catch (ArgumentException) + { + // On NetFramework, all we care about is whether the exception is thrown. + return; + } + catch (Exception e) + { + throw new XunitException($"Expected ArgumentException -> Actual: {e}"); + } + + throw new XunitException($"Expected ArgumentException with error: ({error}) -> Actual: No exception thrown"); + } + } +} diff --git a/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj b/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj index 20878ca..fade03b 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj +++ b/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj @@ -1,4 +1,4 @@ - + true @@ -30,10 +30,14 @@ + + + +