diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj b/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj index 8f2c6d09fe0f9b..55ae3dff4e3dbe 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System.ComponentModel.TypeConverter.csproj @@ -248,6 +248,7 @@ diff --git a/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj b/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj index c2b707ca50c120..5835fbeec550b3 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj +++ b/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj @@ -152,6 +152,7 @@ diff --git a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj index 18f51320fd483b..c388abd3fb7090 100644 --- a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj +++ b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj @@ -760,6 +760,7 @@ diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj index 6135fc76923dee..32c2137af5a21c 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj @@ -324,6 +324,7 @@ diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 32e79eef2745e2..da78325562cd32 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -843,7 +843,7 @@ void EmitFixedSet_LeftToRight() 3 => $"{span}.IndexOfAny({Literal(primarySet.Chars[0])}, {Literal(primarySet.Chars[1])}, {Literal(primarySet.Chars[2])})", _ => $"{span}.IndexOfAny({Literal(new string(primarySet.Chars))})", } : - (primarySet.Range.Value.LowInclusive == primarySet.Range.Value.HighInclusive, primarySet.Range.Value.Negated) switch + (primarySet.Range!.Value.LowInclusive == primarySet.Range.Value.HighInclusive, primarySet.Range.Value.Negated) switch { (false, false) => $"{span}.IndexOfAnyInRange({Literal(primarySet.Range.Value.LowInclusive)}, {Literal(primarySet.Range.Value.HighInclusive)})", (true, false) => $"{span}.IndexOf({Literal(primarySet.Range.Value.LowInclusive)})", @@ -2920,7 +2920,7 @@ void EmitSingleCharLoop(RegexNode node, RegexNode? subsequent = null, bool emitL if (!rtl && node.N > 1 && // no point in using IndexOf for small loops, in particular optionals subsequent?.FindStartingLiteralNode() is RegexNode literalNode && - TryEmitIndexOf(literalNode, useLast: true, negate: false, out int literalLength, out string indexOfExpr)) + TryEmitIndexOf(literalNode, useLast: true, negate: false, out int literalLength, out string? indexOfExpr)) { writer.WriteLine($"if ({startingPos} >= {endingPos} ||"); @@ -3685,7 +3685,7 @@ void EmitSingleCharAtomicLoop(RegexNode node, bool emitLengthChecksIfRequired = TransferSliceStaticPosToPos(); writer.WriteLine($"int {iterationLocal} = inputSpan.Length - pos;"); } - else if (maxIterations == int.MaxValue && TryEmitIndexOf(node, useLast: false, negate: true, out _, out string indexOfExpr)) + else if (maxIterations == int.MaxValue && TryEmitIndexOf(node, useLast: false, negate: true, out _, out string? indexOfExpr)) { // We're unbounded and we can use an IndexOf method to perform the search. The unbounded restriction is // purely for simplicity; it could be removed in the future with additional code to handle that case. @@ -4351,8 +4351,8 @@ private static bool TryEmitIndexOf( if (node.Kind == RegexNodeKind.Multi) { Debug.Assert(!negate, "Negation isn't appropriate for a multi"); - indexOfExpr = $"{last}IndexOf({Literal(node.Str)})"; - literalLength = node.Str.Length; + indexOfExpr = $"{last}IndexOf({Literal(node.Str!)})"; + literalLength = node.Str!.Length; return true; } diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs index e6e6e57a16e349..e403461a5f15ad 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Parser.cs @@ -41,7 +41,7 @@ public partial class RegexGenerator return null; } - IMethodSymbol regexMethodSymbol = context.TargetSymbol as IMethodSymbol; + IMethodSymbol? regexMethodSymbol = context.TargetSymbol as IMethodSymbol; if (regexMethodSymbol is null) { return null; @@ -95,7 +95,7 @@ public partial class RegexGenerator // int matchTimeoutMilliseconds, or string cultureName. else if (items.Length == 3) { - if (items[2].Type.SpecialType == SpecialType.System_Int32) + if (items[2].Type?.SpecialType == SpecialType.System_Int32) { matchTimeout = items[2].Value as int?; } diff --git a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj index ed6adef253720b..80872d47e04611 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj +++ b/src/libraries/System.Text.RegularExpressions/gen/System.Text.RegularExpressions.Generator.csproj @@ -1,14 +1,18 @@ - netstandard2.0 + + netstandard2.0;$(NetCoreAppToolCurrent) true false true false $(NoWarn);CS0436;CS0649 true - $(DefineConstants);REGEXGENERATOR cs @@ -46,4 +50,9 @@ + + + + + diff --git a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexAnalyzer.cs b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexAnalyzer.cs index 98db27c8d439c7..297ff1cc121d3a 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexAnalyzer.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexAnalyzer.cs @@ -168,7 +168,13 @@ private static bool ValidateParameters(ImmutableArray argume for (int i = 0; i < arguments.Length; i++) { IArgumentOperation argument = arguments[i]; - string argumentName = argument.Parameter.Name; + string? argumentName = argument.Parameter?.Name; + + // If the argument name is null (e.g. an __arglist), then we don't emit a diagnostic. + if (argumentName is null) + { + return false; + } // If one of the arguments is a timeout, then we don't emit a diagnostic. if (argumentName.Equals(timeoutArgumentName, StringComparison.OrdinalIgnoreCase) || @@ -180,7 +186,7 @@ private static bool ValidateParameters(ImmutableArray argume // If the argument is the pattern, then we validate that it is constant and we store the index. if (argumentName.Equals(PatternArgumentName, StringComparison.OrdinalIgnoreCase)) { - if (!IsConstant(argument)) + if (!argument.Value.ConstantValue.HasValue) { return false; } @@ -191,12 +197,12 @@ private static bool ValidateParameters(ImmutableArray argume // If the argument is the options, then we validate that it is constant, that it doesn't have RegexOptions.NonBacktracking, and we store the index. if (argumentName.Equals(OptionsArgumentName, StringComparison.OrdinalIgnoreCase)) { - if (!IsConstant(argument)) + if (!argument.Value.ConstantValue.HasValue) { return false; } - RegexOptions value = (RegexOptions)((int)argument.Value.ConstantValue.Value); + RegexOptions value = (RegexOptions)(int)argument.Value.ConstantValue.Value!; if ((value & RegexOptions.NonBacktracking) > 0) { return false; @@ -209,15 +215,6 @@ private static bool ValidateParameters(ImmutableArray argume return true; } - /// - /// Ensures that the input to the constructor or invocation is constant at compile time - /// which is a requirement in order to be able to use the source generator. - /// - /// The argument to be analyzed. - /// if the argument is constant; otherwise, . - private static bool IsConstant(IArgumentOperation argument) - => argument.Value.ConstantValue.HasValue; - /// /// Ensures that the compilation can find the Regex and RegexAttribute types, and also validates that the /// LangVersion of the project is >= 10.0 (which is the current requirement for the Regex source generator. @@ -233,7 +230,7 @@ private static bool ProjectSupportsRegexSourceGenerator(Compilation compilation, return false; } - INamedTypeSymbol generatedRegexAttributeTypeSymbol = compilation.GetTypeByMetadataName(GeneratedRegexTypeName); + INamedTypeSymbol? generatedRegexAttributeTypeSymbol = compilation.GetTypeByMetadataName(GeneratedRegexTypeName); if (generatedRegexAttributeTypeSymbol == null) { return false; diff --git a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs index e18a40c946cf1c..737b35b15eadf2 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs @@ -161,7 +161,7 @@ private static async Task ConvertToSourceGenerator(Document document, { operationArguments = invocationOperation.Arguments; IEnumerable arguments = operationArguments - .Where(arg => arg.Parameter.Name is not (UpgradeToGeneratedRegexAnalyzer.OptionsArgumentName or UpgradeToGeneratedRegexAnalyzer.PatternArgumentName)) + .Where(arg => arg.Parameter?.Name is not (UpgradeToGeneratedRegexAnalyzer.OptionsArgumentName or UpgradeToGeneratedRegexAnalyzer.PatternArgumentName)) .Select(arg => arg.Syntax); replacement = generator.InvocationExpression(generator.MemberAccessExpression(replacement, invocationOperation.TargetMethod.Name), arguments); @@ -192,7 +192,7 @@ private static async Task ConvertToSourceGenerator(Document document, // we also need to parse the pattern in case there are options that were specified inside the pattern via the `(?i)` switch. SyntaxNode? cultureNameValue = null; RegexOptions regexOptions = regexOptionsValue is not null ? GetRegexOptionsFromArgument(operationArguments) : RegexOptions.None; - string pattern = GetRegexPatternFromArgument(operationArguments); + string pattern = GetRegexPatternFromArgument(operationArguments)!; regexOptions |= RegexParser.ParseOptionsInPattern(pattern, regexOptions); // If the options include IgnoreCase and don't specify CultureInvariant then we will have to calculate the user's current culture in order to pass @@ -239,9 +239,9 @@ static IEnumerable GetAllMembers(ITypeSymbol? symbol) } } - static string GetRegexPatternFromArgument(ImmutableArray arguments) + static string? GetRegexPatternFromArgument(ImmutableArray arguments) { - IArgumentOperation? patternArgument = arguments.SingleOrDefault(arg => arg.Parameter.Name == UpgradeToGeneratedRegexAnalyzer.PatternArgumentName); + IArgumentOperation? patternArgument = arguments.SingleOrDefault(arg => arg.Parameter?.Name == UpgradeToGeneratedRegexAnalyzer.PatternArgumentName); if (patternArgument is null) { return null; @@ -252,16 +252,17 @@ static string GetRegexPatternFromArgument(ImmutableArray arg static RegexOptions GetRegexOptionsFromArgument(ImmutableArray arguments) { - IArgumentOperation? optionsArgument = arguments.SingleOrDefault(arg => arg.Parameter.Name == UpgradeToGeneratedRegexAnalyzer.OptionsArgumentName); + IArgumentOperation? optionsArgument = arguments.SingleOrDefault(arg => arg.Parameter?.Name == UpgradeToGeneratedRegexAnalyzer.OptionsArgumentName); - return optionsArgument is null ? RegexOptions.None : - (RegexOptions)(int)optionsArgument.Value.ConstantValue.Value; + return optionsArgument is null || !optionsArgument.Value.ConstantValue.HasValue ? + RegexOptions.None : + (RegexOptions)(int)optionsArgument.Value.ConstantValue.Value!; } // Helper method that looks generates the node for pattern argument or options argument. static SyntaxNode? GetNode(ImmutableArray arguments, SyntaxGenerator generator, string parameterName) { - IArgumentOperation? argument = arguments.SingleOrDefault(arg => arg.Parameter.Name == parameterName); + IArgumentOperation? argument = arguments.SingleOrDefault(arg => arg.Parameter?.Name == parameterName); if (argument is null) { return null; @@ -270,7 +271,7 @@ static RegexOptions GetRegexOptionsFromArgument(ImmutableArray true $(NetCoreAppCurrent) + $(DefineConstants);SYSTEM_TEXT_REGULAREXPRESSIONS 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 02a61612e6f3cc..894536bcd976fb 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 @@ -547,12 +547,13 @@ public static string ConvertOldStringsToClass(string set, string category) strLength -= 2; } -#if REGEXGENERATOR - return StringExtensions.Create + return +#if NETCOREAPP2_1_OR_GREATER + string #else - return string.Create + StringExtensions #endif - (strLength, (set, category, startsWithNulls), static (span, state) => + .Create(strLength, (set, category, startsWithNulls), static (span, state) => { int index; @@ -981,7 +982,9 @@ public static bool ParticipatesInCaseConversion(ReadOnlySpan s) /// Gets whether the specified span contains only ASCII. public static bool IsAscii(ReadOnlySpan s) { -#if REGEXGENERATOR +#if NET8_0_OR_GREATER + return Ascii.IsValid(s); +#else foreach (char c in s) { if (c >= 128) @@ -991,8 +994,6 @@ public static bool IsAscii(ReadOnlySpan s) } return true; -#else - return Ascii.IsValid(s); #endif } @@ -1250,11 +1251,12 @@ static bool InitializeValue(char ch, string set, ref uint[]? asciiLazyCache) } uint[]? cache = asciiLazyCache ?? Interlocked.CompareExchange(ref asciiLazyCache, new uint[CacheArrayLength], null) ?? asciiLazyCache; -#if REGEXGENERATOR - InterlockedExtensions.Or(ref cache[ch >> 4], bitsToSet); +#if NET5_0_OR_GREATER + Interlocked #else - Interlocked.Or(ref cache[ch >> 4], bitsToSet); + InterlockedExtensions #endif + .Or(ref cache[ch >> 4], bitsToSet); // Return the computed value. return isInClass; @@ -1542,12 +1544,13 @@ internal static unsafe string CharsToStringClass(ReadOnlySpan chars) // Get the pointer/length of the span to be able to pass it into string.Create. #pragma warning disable CS8500 // takes address of managed type ReadOnlySpan tmpChars = chars; // avoid address exposing the span and impacting the other code in the method that uses it -#if REGEXGENERATOR - return StringExtensions.Create( + return +#if NETCOREAPP2_1_OR_GREATER + string #else - return string.Create( + StringExtensions #endif - SetStartIndex + count, (IntPtr)(&tmpChars), static (span, charsPtr) => + .Create(SetStartIndex + count, (IntPtr)(&tmpChars), static (span, charsPtr) => { // Fill in the set string span[FlagsIndex] = (char)0; diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs index 5c04e6da489787..b62560ede90fa6 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexOptions.cs @@ -4,10 +4,10 @@ namespace System.Text.RegularExpressions { [Flags] -#if REGEXGENERATOR - internal -#else +#if SYSTEM_TEXT_REGULAREXPRESSIONS public +#else + internal #endif enum RegexOptions { 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 c3493d685193e4..5903dee630910d 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 @@ -10,10 +10,10 @@ namespace System.Text.RegularExpressions /// /// This information is made available through . /// -#if REGEXGENERATOR - internal -#else +#if SYSTEM_TEXT_REGULAREXPRESSIONS public +#else + internal #endif enum RegexParseError { 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 29951fb740a974..38808caac811fe 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 @@ -10,10 +10,10 @@ namespace System.Text.RegularExpressions /// detailed information in the and properties. /// [Serializable] -#if REGEXGENERATOR - internal -#else +#if SYSTEM_TEXT_REGULAREXPRESSIONS public +#else + internal #endif sealed class RegexParseException : ArgumentException { 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 7216562d29ac9a..7634cda0a377b3 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 @@ -2076,7 +2076,7 @@ internal static int MapCaptureNumber(int capnum, Hashtable? caps) => // ' a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Q, S, 0, 0, 0}; -#if NET7_0_OR_GREATER +#if NET8_0_OR_GREATER private static readonly IndexOfAnyValues s_metachars = IndexOfAnyValues.Create("\t\n\f\r #$()*+.?[\\^{|"); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs index 7c4db7d0bd71ed..bdd80ee5d9a8ca 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexWriter.cs @@ -178,18 +178,18 @@ private void Emit(RegexOpcode op, int opd1, int opd2) /// private int StringCode(string str) { -#if REGEXGENERATOR - if (!_stringTable.TryGetValue(str, out int i)) - { - i = _stringTable.Count; - _stringTable.Add(str, i); - } -#else +#if NET6_0_OR_GREATER ref int i = ref CollectionsMarshal.GetValueRefOrAddDefault(_stringTable, str, out bool exists); if (!exists) { i = _stringTable.Count - 1; } +#else + if (!_stringTable.TryGetValue(str, out int i)) + { + i = _stringTable.Count; + _stringTable.Add(str, i); + } #endif return i; } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs index 48d94c51037961..c338c2bb73e95c 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Threading/StackHelper.cs @@ -12,7 +12,9 @@ internal static class StackHelper /// Tries to ensure there is sufficient stack to execute the average .NET function. public static bool TryEnsureSufficientExecutionStack() { -#if REGEXGENERATOR +#if NETCOREAPP2_0_OR_GREATER + return RuntimeHelpers.TryEnsureSufficientExecutionStack(); +#else try { RuntimeHelpers.EnsureSufficientExecutionStack(); @@ -22,8 +24,6 @@ public static bool TryEnsureSufficientExecutionStack() { return false; } -#else - return RuntimeHelpers.TryEnsureSufficientExecutionStack(); #endif } diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj index 5965d053f1886b..c83d53bcbc1f78 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj @@ -74,7 +74,10 @@ - + diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs index 32db3f3ca0834b..a796d2e1197ccd 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexFindOptimizationsTests.cs @@ -10,106 +10,106 @@ public class RegexFindOptimizationsTests { [Theory] - [InlineData(@"^", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] - [InlineData(@"^hello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] - [InlineData(@"^hello$", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] - [InlineData(@"^hi|^hello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] - - [InlineData(@"\G", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] - [InlineData(@"\Ghello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] - [InlineData(@"\Ghello$", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] - [InlineData(@"\Ghi|\Ghello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] - - [InlineData(@"\Z", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] - [InlineData(@"\Zhello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] - [InlineData(@"\Zhello$", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] - [InlineData(@"\Zhi|\Zhello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] - - [InlineData(@"\z", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] - [InlineData(@"\zhello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] - [InlineData(@"\zhello$", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] - [InlineData(@"\zhi|\zhello", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] - - [InlineData(@"^", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] - [InlineData(@"hello^", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] - [InlineData(@"$hello^", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] - [InlineData(@"hi^|hello^", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] - - [InlineData(@"\G", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] - [InlineData(@"hello\G", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] - [InlineData(@"$hello\G", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] - [InlineData(@"hi\G|hello\G", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] - - [InlineData(@"\Z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] - [InlineData(@"hello\Z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] - [InlineData(@"$hello\Z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] - [InlineData(@"hi\Z|hello\Z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] - - [InlineData(@"\z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] - [InlineData(@"hello\z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] - [InlineData(@"$hello\z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] - [InlineData(@"hi\z|hello\z", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] - public void LeadingAnchor_LeftToRight(string pattern, RegexOptions options, int expectedMode) + [InlineData(@"^", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] + [InlineData(@"^hello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] + [InlineData(@"^hello$", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] + [InlineData(@"^hi|^hello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning)] + + [InlineData(@"\G", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] + [InlineData(@"\Ghello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] + [InlineData(@"\Ghello$", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] + [InlineData(@"\Ghi|\Ghello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start)] + + [InlineData(@"\Z", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] + [InlineData(@"\Zhello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] + [InlineData(@"\Zhello$", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] + [InlineData(@"\Zhi|\Zhello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_EndZ)] + + [InlineData(@"\z", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] + [InlineData(@"\zhello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] + [InlineData(@"\zhello$", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] + [InlineData(@"\zhi|\zhello", 0, (int)FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End)] + + [InlineData(@"^", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] + [InlineData(@"hello^", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] + [InlineData(@"$hello^", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] + [InlineData(@"hi^|hello^", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning)] + + [InlineData(@"\G", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] + [InlineData(@"hello\G", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] + [InlineData(@"$hello\G", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] + [InlineData(@"hi\G|hello\G", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start)] + + [InlineData(@"\Z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] + [InlineData(@"hello\Z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] + [InlineData(@"$hello\Z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] + [InlineData(@"hi\Z|hello\Z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_EndZ)] + + [InlineData(@"\z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] + [InlineData(@"hello\z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] + [InlineData(@"$hello\z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] + [InlineData(@"hi\z|hello\z", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End)] + public void LeadingAnchor_LeftToRight(string pattern, int options, int expectedMode) { - Assert.Equal((FindNextStartingPositionMode)expectedMode, ComputeOptimizations(pattern, options).FindMode); + Assert.Equal((FindNextStartingPositionMode)expectedMode, ComputeOptimizations(pattern, (RegexOptions)options).FindMode); } [Theory] - [InlineData(@"abc\z", RegexOptions.None, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End, 3, (int)RegexNodeKind.End)] - [InlineData(@"abc\Z", RegexOptions.None, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ, 3, (int)RegexNodeKind.EndZ)] - [InlineData(@"abc$", RegexOptions.None, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ, 3, (int)RegexNodeKind.EndZ)] - [InlineData(@"a{4,10}$", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, 10, (int)RegexNodeKind.EndZ)] - [InlineData(@"(abc|defg){1,2}\z", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, 8, (int)RegexNodeKind.End)] - public void TrailingAnchor(string pattern, RegexOptions options, int expectedMode, int expectedLength, int trailingAnchor) + [InlineData(@"abc\z", 0, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_End, 3, (int)RegexNodeKind.End)] + [InlineData(@"abc\Z", 0, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ, 3, (int)RegexNodeKind.EndZ)] + [InlineData(@"abc$", 0, (int)FindNextStartingPositionMode.TrailingAnchor_FixedLength_LeftToRight_EndZ, 3, (int)RegexNodeKind.EndZ)] + [InlineData(@"a{4,10}$", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, 10, (int)RegexNodeKind.EndZ)] + [InlineData(@"(abc|defg){1,2}\z", 0, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, 8, (int)RegexNodeKind.End)] + public void TrailingAnchor(string pattern, int options, int expectedMode, int expectedLength, int trailingAnchor) { - RegexFindOptimizations opts = ComputeOptimizations(pattern, options); + RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); Assert.Equal((FindNextStartingPositionMode)expectedMode, opts.FindMode); Assert.Equal(expectedLength, opts.MaxPossibleLength); Assert.Equal((RegexNodeKind)trailingAnchor, opts.TrailingAnchor); } [Theory] - [InlineData(@"ab", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"ab", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] - [InlineData(@"(a)(bc)", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abc")] - [InlineData(@"(a)(bc)", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "bc")] - [InlineData(@"a{10}", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaaaaaaaaa")] - [InlineData(@"a{10}", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaaaaaaaaa")] - [InlineData(@"(?>a{10,20})", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaaaaaaaaa")] - [InlineData(@"(?>a{10,20})", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaaaaaaaaa")] - [InlineData(@"a{3,5}?", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaa")] - [InlineData(@"a{3,5}?", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaa")] - [InlineData(@"ab{5}", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abbbbb")] - [InlineData(@"ab{5}", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "abbbbb")] - [InlineData(@"ab\w", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"\wab", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] - [InlineData(@"(ab){3}", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ababab")] - [InlineData(@"(ab){3}", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] - [InlineData(@"(ab){2,4}(de){4,}", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abab")] - [InlineData(@"(ab){2,4}(de){4,}", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "de")] - [InlineData(@"ab|(abc)|(abcd)", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"ab|(abc)|(abcd)", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] - [InlineData(@"ab(?=cd)", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] - [InlineData(@"ab(?=cd)", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] - public void LeadingPrefix(string pattern, RegexOptions options, int expectedMode, string expectedPrefix) + [InlineData(@"ab", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] + [InlineData(@"ab", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] + [InlineData(@"(a)(bc)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abc")] + [InlineData(@"(a)(bc)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "bc")] + [InlineData(@"a{10}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaaaaaaaaa")] + [InlineData(@"a{10}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaaaaaaaaa")] + [InlineData(@"(?>a{10,20})", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaaaaaaaaa")] + [InlineData(@"(?>a{10,20})", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaaaaaaaaa")] + [InlineData(@"a{3,5}?", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "aaa")] + [InlineData(@"a{3,5}?", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "aaa")] + [InlineData(@"ab{5}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abbbbb")] + [InlineData(@"ab{5}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "abbbbb")] + [InlineData(@"ab\w", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] + [InlineData(@"\wab", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] + [InlineData(@"(ab){3}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ababab")] + [InlineData(@"(ab){3}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] + [InlineData(@"(ab){2,4}(de){4,}", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "abab")] + [InlineData(@"(ab){2,4}(de){4,}", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "de")] + [InlineData(@"ab|(abc)|(abcd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] + [InlineData(@"ab|(abc)|(abcd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] + [InlineData(@"ab(?=cd)", 0, (int)FindNextStartingPositionMode.LeadingString_LeftToRight, "ab")] + [InlineData(@"ab(?=cd)", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingString_RightToLeft, "ab")] + public void LeadingPrefix(string pattern, int options, int expectedMode, string expectedPrefix) { - RegexFindOptimizations opts = ComputeOptimizations(pattern, options); + RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); Assert.Equal((FindNextStartingPositionMode)expectedMode, opts.FindMode); Assert.Equal(expectedPrefix, opts.LeadingPrefix); } [Theory] - [InlineData(@"[ab]", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "ab")] - [InlineData(@"[Aa]", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "Aa")] - [InlineData(@"a", RegexOptions.IgnoreCase, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "Aa")] - [InlineData(@"ab|cd|ef|gh", RegexOptions.None, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "aceg")] - [InlineData(@"[ab]", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "ab")] - [InlineData(@"[Aa]", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] - [InlineData(@"a", RegexOptions.IgnoreCase | RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] - [InlineData(@"ab|cd|ef|gh", RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bdfh")] - public void LeadingSet(string pattern, RegexOptions options, int expectedMode, string expectedChars) + [InlineData(@"[ab]", 0, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "ab")] + [InlineData(@"[Aa]", 0, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "Aa")] + [InlineData(@"a", (int)RegexOptions.IgnoreCase, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "Aa")] + [InlineData(@"ab|cd|ef|gh", 0, (int)FindNextStartingPositionMode.LeadingSet_LeftToRight, "aceg")] + [InlineData(@"[ab]", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "ab")] + [InlineData(@"[Aa]", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] + [InlineData(@"a", (int)RegexOptions.IgnoreCase | (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "Aa")] + [InlineData(@"ab|cd|ef|gh", (int)RegexOptions.RightToLeft, (int)FindNextStartingPositionMode.LeadingSet_RightToLeft, "bdfh")] + public void LeadingSet(string pattern, int options, int expectedMode, string expectedChars) { - RegexFindOptimizations opts = ComputeOptimizations(pattern, options); + RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); Assert.Equal((FindNextStartingPositionMode)expectedMode, opts.FindMode); Assert.Equal(1, opts.FixedDistanceSets.Count); Assert.Equal(0, opts.FixedDistanceSets[0].Distance); @@ -117,11 +117,11 @@ public void LeadingSet(string pattern, RegexOptions options, int expectedMode, s } [Theory] - [InlineData(@"\d*a", RegexOptions.None, (int)FindNextStartingPositionMode.LiteralAfterLoop_LeftToRight, null, 'a')] - [InlineData(@"\d*abc", RegexOptions.None, (int)FindNextStartingPositionMode.LiteralAfterLoop_LeftToRight, "abc", 0)] - public void LiteralAfterLoop(string pattern, RegexOptions options, int expectedMode, string? expectedString, char expectedChar) + [InlineData(@"\d*a", 0, (int)FindNextStartingPositionMode.LiteralAfterLoop_LeftToRight, null, 'a')] + [InlineData(@"\d*abc", 0, (int)FindNextStartingPositionMode.LiteralAfterLoop_LeftToRight, "abc", 0)] + public void LiteralAfterLoop(string pattern, int options, int expectedMode, string? expectedString, char expectedChar) { - RegexFindOptimizations opts = ComputeOptimizations(pattern, options); + RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); Assert.Equal((FindNextStartingPositionMode)expectedMode, opts.FindMode); Assert.NotNull(opts.LiteralAfterLoop); Assert.Equal(expectedString, opts.LiteralAfterLoop.Value.Literal.String); @@ -129,13 +129,13 @@ public void LiteralAfterLoop(string pattern, RegexOptions options, int expectedM } [Theory] - [InlineData(@".ab", RegexOptions.None, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ab", 1)] - [InlineData(@".ab\w\w\wcdef\w\w\w\w\wghijklmnopq\w\w\w", RegexOptions.None, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ghijklmnopq", 15)] - [InlineData(@"a[Bb]c[Dd]ef", RegexOptions.None, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ef", 4)] - [InlineData(@"a[Bb]cd[Ee]fgh[Ii]", RegexOptions.None, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "fgh", 5)] - public void FixedDistanceString(string pattern, RegexOptions options, int expectedMode, string expectedString, int distance) + [InlineData(@".ab", 0, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ab", 1)] + [InlineData(@".ab\w\w\wcdef\w\w\w\w\wghijklmnopq\w\w\w", 0, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ghijklmnopq", 15)] + [InlineData(@"a[Bb]c[Dd]ef", 0, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "ef", 4)] + [InlineData(@"a[Bb]cd[Ee]fgh[Ii]", 0, (int)FindNextStartingPositionMode.FixedDistanceString_LeftToRight, "fgh", 5)] + public void FixedDistanceString(string pattern, int options, int expectedMode, string expectedString, int distance) { - RegexFindOptimizations opts = ComputeOptimizations(pattern, options); + RegexFindOptimizations opts = ComputeOptimizations(pattern, (RegexOptions)options); Assert.Equal((FindNextStartingPositionMode)expectedMode, opts.FindMode); Assert.Equal(expectedString, opts.FixedDistanceLiteral.String); Assert.Equal(distance, opts.FixedDistanceLiteral.Distance); diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexPrefixAnalyzerTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexPrefixAnalyzerTests.cs index f1a4583540d743..d4520ba19746cd 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexPrefixAnalyzerTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexPrefixAnalyzerTests.cs @@ -12,50 +12,50 @@ public class RegexPrefixAnalyzerTests { [Theory] // Produce starting sets - [InlineData(@"a", RegexOptions.None, "\0\u0002\0ab")] - [InlineData(@"(a)", RegexOptions.None, "\0\u0002\0ab")] - [InlineData(@"(a)+", RegexOptions.None, "\0\u0002\0ab")] - [InlineData(@"abc", RegexOptions.None, "\0\u0002\0ab")] - [InlineData(@"abc", RegexOptions.RightToLeft, "\0\u0002\0cd")] - [InlineData(@"abc|def", RegexOptions.RightToLeft, "\0\u0004\0cdfg")] - [InlineData(@"a?b", RegexOptions.None, "\0\u0002\0ac")] - [InlineData(@"a?[bcd]", RegexOptions.None, "\0\u0002\0ae")] - [InlineData(@"a?[bcd]*[xyz]", RegexOptions.None, "\0\u0004\0aex{")] - [InlineData(@"[a-c]", RegexOptions.None, "\0\u0002\0ad")] - [InlineData(@"a+b+c+", RegexOptions.None, "\0\u0002\0ab")] - [InlineData(@"a*b+c+", RegexOptions.None, "\0\u0002\0ac")] - [InlineData(@"a*b*c+", RegexOptions.None, "\0\u0002\0ad")] - [InlineData(@".", RegexOptions.None, "\u0001\u0002\u0000\u000A\u000B")] - [InlineData(@".|\n", RegexOptions.None, "\0\u0001\0\0")] - [InlineData(@"[^\n]?[\n]", RegexOptions.None, "\0\u0001\0\0")] - [InlineData(@"[^a]?[a]", RegexOptions.None, "\0\u0001\0\0")] - [InlineData(@"(abc)?(?(\1)yes|no)", RegexOptions.None, "\0\u0006\0abnoyz")] - [InlineData(@"(abc)?(?(xyz)yes|no)", RegexOptions.None, "\0\u0006\0abnoyz")] - [InlineData(@"[^a-zA-Z0-9_.]", RegexOptions.None, "\u0001\u000A\u0000./0:A[_`a{")] + [InlineData(@"a", 0, "\0\u0002\0ab")] + [InlineData(@"(a)", 0, "\0\u0002\0ab")] + [InlineData(@"(a)+", 0, "\0\u0002\0ab")] + [InlineData(@"abc", 0, "\0\u0002\0ab")] + [InlineData(@"abc", (int)RegexOptions.RightToLeft, "\0\u0002\0cd")] + [InlineData(@"abc|def", (int)RegexOptions.RightToLeft, "\0\u0004\0cdfg")] + [InlineData(@"a?b", 0, "\0\u0002\0ac")] + [InlineData(@"a?[bcd]", 0, "\0\u0002\0ae")] + [InlineData(@"a?[bcd]*[xyz]", 0, "\0\u0004\0aex{")] + [InlineData(@"[a-c]", 0, "\0\u0002\0ad")] + [InlineData(@"a+b+c+", 0, "\0\u0002\0ab")] + [InlineData(@"a*b+c+", 0, "\0\u0002\0ac")] + [InlineData(@"a*b*c+", 0, "\0\u0002\0ad")] + [InlineData(@".", 0, "\u0001\u0002\u0000\u000A\u000B")] + [InlineData(@".|\n", 0, "\0\u0001\0\0")] + [InlineData(@"[^\n]?[\n]", 0, "\0\u0001\0\0")] + [InlineData(@"[^a]?[a]", 0, "\0\u0001\0\0")] + [InlineData(@"(abc)?(?(\1)yes|no)", 0, "\0\u0006\0abnoyz")] + [InlineData(@"(abc)?(?(xyz)yes|no)", 0, "\0\u0006\0abnoyz")] + [InlineData(@"[^a-zA-Z0-9_.]", 0, "\u0001\u000A\u0000./0:A[_`a{")] // Can't produce starting sets - [InlineData(@"", RegexOptions.None, null)] - [InlineData(@"a*", RegexOptions.None, null)] - [InlineData(@"a*b*", RegexOptions.None, null)] - [InlineData(@"a*b*c*", RegexOptions.None, null)] - [InlineData(@"a*|b*", RegexOptions.None, null)] - [InlineData(@"(a)*", RegexOptions.None, null)] - [InlineData(@"(?:a)*", RegexOptions.None, null)] - [InlineData(@"(a*)+", RegexOptions.None, null)] - [InlineData(@"(a*)+?", RegexOptions.None, null)] - [InlineData(@"[^ab]|a", RegexOptions.None, null)] - [InlineData(@"[^ab]|ab", RegexOptions.None, null)] - [InlineData(@"[^ab]?[a]", RegexOptions.None, null)] - [InlineData(@"[^ab]?(a)+", RegexOptions.None, null)] - [InlineData(@"(abc)?\1", RegexOptions.None, null)] - [InlineData(@"[abc-[bc]]|[def]", RegexOptions.None, null)] - [InlineData(@"[def]|[abc-[bc]]", RegexOptions.None, null)] - [InlineData(@"(abc)?(?(\1)d*|f)", RegexOptions.None, null)] - [InlineData(@"(abc)?(?(\1)d|f*)", RegexOptions.None, null)] - [InlineData(@"(abc)?(?(xyz)d*|f)", RegexOptions.None, null)] - [InlineData(@"(abc)?(?(xyz)d|f*)", RegexOptions.None, null)] - public void FindFirstCharClass(string pattern, RegexOptions options, string? expectedSet) + [InlineData(@"", 0, null)] + [InlineData(@"a*", 0, null)] + [InlineData(@"a*b*", 0, null)] + [InlineData(@"a*b*c*", 0, null)] + [InlineData(@"a*|b*", 0, null)] + [InlineData(@"(a)*", 0, null)] + [InlineData(@"(?:a)*", 0, null)] + [InlineData(@"(a*)+", 0, null)] + [InlineData(@"(a*)+?", 0, null)] + [InlineData(@"[^ab]|a", 0, null)] + [InlineData(@"[^ab]|ab", 0, null)] + [InlineData(@"[^ab]?[a]", 0, null)] + [InlineData(@"[^ab]?(a)+", 0, null)] + [InlineData(@"(abc)?\1", 0, null)] + [InlineData(@"[abc-[bc]]|[def]", 0, null)] + [InlineData(@"[def]|[abc-[bc]]", 0, null)] + [InlineData(@"(abc)?(?(\1)d*|f)", 0, null)] + [InlineData(@"(abc)?(?(\1)d|f*)", 0, null)] + [InlineData(@"(abc)?(?(xyz)d*|f)", 0, null)] + [InlineData(@"(abc)?(?(xyz)d|f*)", 0, null)] + public void FindFirstCharClass(string pattern, int options, string? expectedSet) { - RegexTree tree = RegexParser.Parse(pattern, options, CultureInfo.InvariantCulture); + RegexTree tree = RegexParser.Parse(pattern, (RegexOptions)options, CultureInfo.InvariantCulture); string actualSet = RegexPrefixAnalyzer.FindFirstCharClass(tree.Root); if (expectedSet != actualSet) { @@ -67,7 +67,7 @@ public void FindFirstCharClass(string pattern, RegexOptions options, string? exp public void FindFirstCharClass_StressDeep() { int nesting = 8000; - FindFirstCharClass(string.Concat(Enumerable.Repeat($"(a?", nesting).Concat(Enumerable.Repeat(")*", nesting))), RegexOptions.None, null); + FindFirstCharClass(string.Concat(Enumerable.Repeat($"(a?", nesting).Concat(Enumerable.Repeat(")*", nesting))), 0, null); } private static string FormatSet(string set) diff --git a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs index c7c8cc5a3936b3..4438e3fc2d9b9a 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/UnitTests/RegexReductionTests.cs @@ -508,77 +508,77 @@ public void PatternsReduceDifferently(string actual, string expected) } [Theory] - [InlineData(@"a", RegexOptions.None, 1, 1)] - [InlineData(@"[^a]", RegexOptions.None, 1, 1)] - [InlineData(@"[abcdefg]", RegexOptions.None, 1, 1)] - [InlineData(@"abcd", RegexOptions.None, 4, 4)] - [InlineData(@"a*", RegexOptions.None, 0, null)] - [InlineData(@"a*?", RegexOptions.None, 0, null)] - [InlineData(@"a?", RegexOptions.None, 0, 1)] - [InlineData(@"a??", RegexOptions.None, 0, 1)] - [InlineData(@"a+", RegexOptions.None, 1, null)] - [InlineData(@"a+?", RegexOptions.None, 1, null)] - [InlineData(@"(?>a*)a", RegexOptions.None, 1, null)] - [InlineData(@"(?>a*)a+", RegexOptions.None, 1, null)] - [InlineData(@"(?>a*)a*", RegexOptions.None, 0, null)] - [InlineData(@"a{2}", RegexOptions.None, 2, 2)] - [InlineData(@"a{2}?", RegexOptions.None, 2, 2)] - [InlineData(@"a{3,17}", RegexOptions.None, 3, 17)] - [InlineData(@"a{3,17}?", RegexOptions.None, 3, 17)] - [InlineData(@"[^a]{3,17}", RegexOptions.None, 3, 17)] - [InlineData(@"[^a]{3,17}?", RegexOptions.None, 3, 17)] - [InlineData(@"(abcd){5}", RegexOptions.None, 20, 20)] - [InlineData(@"(abcd|ef){2,6}", RegexOptions.None, 4, 24)] - [InlineData(@"abcef|de", RegexOptions.None, 2, 5)] - [InlineData(@"abc(def|ghij)k", RegexOptions.None, 7, 8)] - [InlineData(@"abc(def|ghij|k||lmnopqrs|t)u", RegexOptions.None, 4, 12)] - [InlineData(@"(ab)c(def|ghij|k|l|\1|m)n", RegexOptions.None, 4, null)] - [InlineData(@"abc|de*f|ghi", RegexOptions.None, 2, null)] - [InlineData(@"abc|de+f|ghi", RegexOptions.None, 3, null)] - [InlineData(@"abc|(def)+|ghi", RegexOptions.None, 3, null)] - [InlineData(@"(abc)+|def", RegexOptions.None, 3, null)] - [InlineData(@"\d{1,2}-\d{1,2}-\d{2,4}", RegexOptions.None, 6, 10)] - [InlineData(@"\d{1,2}-(?>\d{1,2})-\d{2,4}", RegexOptions.None, 6, 10)] - [InlineData(@"1(?=9)\d", RegexOptions.None, 2, 2)] - [InlineData(@"1(?!\d)\w", RegexOptions.None, 2, 2)] - [InlineData(@"a*a*a*a*a*a*a*b*", RegexOptions.None, 0, null)] - [InlineData(@"((a{1,2}){4}){3,7}", RegexOptions.None, 12, 56)] - [InlineData(@"((a{1,2}){4}?){3,7}", RegexOptions.None, 12, 56)] - [InlineData(@"\b\w{4}\b", RegexOptions.None, 4, 4)] - [InlineData(@"\b\w{4}\b", RegexOptions.ECMAScript, 4, 4)] - [InlineData(@"abcd(?=efgh)efgh", RegexOptions.None, 8, 8)] - [InlineData(@"abcd(?<=cd)efgh", RegexOptions.None, 8, 8)] - [InlineData(@"abcd(?!ab)efgh", RegexOptions.None, 8, 8)] - [InlineData(@"abcd(?a*)a", 0, 1, null)] + [InlineData(@"(?>a*)a+", 0, 1, null)] + [InlineData(@"(?>a*)a*", 0, 0, null)] + [InlineData(@"a{2}", 0, 2, 2)] + [InlineData(@"a{2}?", 0, 2, 2)] + [InlineData(@"a{3,17}", 0, 3, 17)] + [InlineData(@"a{3,17}?", 0, 3, 17)] + [InlineData(@"[^a]{3,17}", 0, 3, 17)] + [InlineData(@"[^a]{3,17}?", 0, 3, 17)] + [InlineData(@"(abcd){5}", 0, 20, 20)] + [InlineData(@"(abcd|ef){2,6}", 0, 4, 24)] + [InlineData(@"abcef|de", 0, 2, 5)] + [InlineData(@"abc(def|ghij)k", 0, 7, 8)] + [InlineData(@"abc(def|ghij|k||lmnopqrs|t)u", 0, 4, 12)] + [InlineData(@"(ab)c(def|ghij|k|l|\1|m)n", 0, 4, null)] + [InlineData(@"abc|de*f|ghi", 0, 2, null)] + [InlineData(@"abc|de+f|ghi", 0, 3, null)] + [InlineData(@"abc|(def)+|ghi", 0, 3, null)] + [InlineData(@"(abc)+|def", 0, 3, null)] + [InlineData(@"\d{1,2}-\d{1,2}-\d{2,4}", 0, 6, 10)] + [InlineData(@"\d{1,2}-(?>\d{1,2})-\d{2,4}", 0, 6, 10)] + [InlineData(@"1(?=9)\d", 0, 2, 2)] + [InlineData(@"1(?!\d)\w", 0, 2, 2)] + [InlineData(@"a*a*a*a*a*a*a*b*", 0, 0, null)] + [InlineData(@"((a{1,2}){4}){3,7}", 0, 12, 56)] + [InlineData(@"((a{1,2}){4}?){3,7}", 0, 12, 56)] + [InlineData(@"\b\w{4}\b", 0, 4, 4)] + [InlineData(@"\b\w{4}\b", (int)RegexOptions.ECMAScript, 4, 4)] + [InlineData(@"abcd(?=efgh)efgh", 0, 8, 8)] + [InlineData(@"abcd(?<=cd)efgh", 0, 8, 8)] + [InlineData(@"abcd(?!ab)efgh", 0, 8, 8)] + [InlineData(@"abcd(?