Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update regex parsing to latest .Net core parsing (and diagnostic messages). #76269

Merged
merged 37 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cc5c5f0
Update regex messages
CyrusNajmabadi Dec 4, 2024
4e84ae1
in progress
CyrusNajmabadi Dec 4, 2024
c4ba8fb
REvert
CyrusNajmabadi Dec 4, 2024
9c2337e
Fix loc string
CyrusNajmabadi Dec 4, 2024
577b20f
Fix loc string
CyrusNajmabadi Dec 4, 2024
b9ffc66
Fix loc string
CyrusNajmabadi Dec 4, 2024
4223c9a
Fix loc string
CyrusNajmabadi Dec 4, 2024
c3e1a6c
Fix loc string
CyrusNajmabadi Dec 4, 2024
efc8ff0
fix tests
CyrusNajmabadi Dec 4, 2024
3ca0cc9
Fix loc string
CyrusNajmabadi Dec 4, 2024
f589008
Fix loc string
CyrusNajmabadi Dec 4, 2024
9fc1412
Fix loc string
CyrusNajmabadi Dec 4, 2024
32a1f55
Fix loc string
CyrusNajmabadi Dec 4, 2024
c5ef7e1
Fix loc string
CyrusNajmabadi Dec 4, 2024
0f172df
in progress
CyrusNajmabadi Dec 4, 2024
ea674e9
Merge remote-tracking branch 'upstream/main' into regexMessages
CyrusNajmabadi Jan 16, 2025
26ec545
Fixup parsing of options withing a grouping
CyrusNajmabadi Jan 16, 2025
9ad64e0
Consistent error
CyrusNajmabadi Jan 16, 2025
8153848
Change string
CyrusNajmabadi Jan 16, 2025
d2563f4
Fix
CyrusNajmabadi Jan 16, 2025
bd4b4ce
fix test
CyrusNajmabadi Jan 16, 2025
0e95ac3
more fixes
CyrusNajmabadi Jan 16, 2025
3860692
UPDATE TSTS
CyrusNajmabadi Jan 16, 2025
972d5ee
remove exceptions
CyrusNajmabadi Jan 16, 2025
09de88e
Remove posix code
CyrusNajmabadi Jan 16, 2025
1fd543f
Unskip
CyrusNajmabadi Jan 16, 2025
67600f5
Apply suggestions from code review
CyrusNajmabadi Jan 16, 2025
1bda1f0
Apply suggestions from code review
CyrusNajmabadi Jan 16, 2025
89e47ce
Simplify
CyrusNajmabadi Jan 16, 2025
2d7ef9a
Merge branch 'regexMessages' of https://github.com/CyrusNajmabadi/ros…
CyrusNajmabadi Jan 16, 2025
1e9a254
Remove
CyrusNajmabadi Jan 16, 2025
75af96a
remove
CyrusNajmabadi Jan 16, 2025
6a66b70
Simplify
CyrusNajmabadi Jan 16, 2025
49c1a87
Simplify
CyrusNajmabadi Jan 16, 2025
c664db1
Remove
CyrusNajmabadi Jan 16, 2025
169bd79
Merge remote-tracking branch 'upstream/main' into regexMessages
CyrusNajmabadi Jan 17, 2025
0ebd4e3
Lint
CyrusNajmabadi Jan 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private static string RemoveMessagesInNonSupportedLanguage(string value)

var diagnosticsElement = XElement.Parse(value);
foreach (var diagnosticElement in diagnosticsElement.Elements("Diagnostic"))
diagnosticElement.Attribute("Message").Remove();
diagnosticElement.Attribute("Message")!.Remove();

return diagnosticsElement.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,46 +40,26 @@ private static SyntaxToken GetStringToken(string text)
return token;
}

private void Test(string stringText, string expected, RegexOptions options,
bool runSubTreeTests = true,
bool allowIndexOutOfRange = false,
bool allowNullReference = false,
bool allowOutOfMemory = false,
bool allowDiagnosticsMismatch = false)
private void Test(
string stringText, string expected, RegexOptions options)
{
var (tree, sourceText) = TryParseTree(stringText, options, conversionFailureOk: false,
allowIndexOutOfRange, allowNullReference, allowOutOfMemory, allowDiagnosticsMismatch);
var (tree, sourceText) = TryParseTree(stringText, options, conversionFailureOk: false);

// Tests are allowed to not run the subtree tests. This is because some
// subtrees can cause the native regex parser to exhibit very bad behavior
// (like not ever actually finishing compiling).
if (runSubTreeTests)
{
TryParseSubTrees(stringText, options,
allowIndexOutOfRange, allowNullReference, allowOutOfMemory, allowDiagnosticsMismatch);
}
TryParseSubTrees(stringText, options);

const string DoubleQuoteEscaping = "\"\"";
var actual = TreeToText(sourceText, tree)
.Replace("\"", DoubleQuoteEscaping)
.Replace(""", DoubleQuoteEscaping);
AssertEx.Equal(expected.Replace("\"", DoubleQuoteEscaping), actual);
.Replace(""", "\"");
AssertEx.Equal(expected, actual);
}

private void TryParseSubTrees(
string stringText, RegexOptions options,
bool allowIndexOutOfRange,
bool allowNullReference,
bool allowOutOfMemory,
bool allowDiagnosticsMismatch)
private void TryParseSubTrees(string stringText, RegexOptions options)
{
// Trim the input from the right and make sure tree invariants hold
var current = stringText;
while (current is not "@\"\"" and not "\"\"")
{
current = current[..^2] + "\"";
TryParseTree(current, options, conversionFailureOk: true,
allowIndexOutOfRange, allowNullReference, allowOutOfMemory, allowDiagnosticsMismatch);
TryParseTree(current, options, conversionFailureOk: true);
}

// Trim the input from the left and make sure tree invariants hold
Expand All @@ -95,17 +75,16 @@ private void TryParseSubTrees(
current = "\"" + current[2..];
}

TryParseTree(current, options, conversionFailureOk: true,
allowIndexOutOfRange, allowNullReference, allowOutOfMemory, allowDiagnosticsMismatch);
TryParseTree(current, options, conversionFailureOk: true);
}

for (var start = stringText[0] == '@' ? 2 : 1; start < stringText.Length - 1; start++)
{
TryParseTree(
stringText[..start] +
stringText[(start + 1)..],
options, conversionFailureOk: true,
allowIndexOutOfRange, allowNullReference, allowOutOfMemory, allowDiagnosticsMismatch);
options,
conversionFailureOk: true);
}
}

Expand All @@ -125,12 +104,7 @@ private void TryParseSubTrees(
}

private (RegexTree, SourceText) TryParseTree(
string stringText, RegexOptions options,
bool conversionFailureOk,
bool allowIndexOutOfRange,
bool allowNullReference,
bool allowOutOfMemory,
bool allowDiagnosticsMismatch = false)
string stringText, RegexOptions options, bool conversionFailureOk)
{
var (token, tree, allChars) = JustParseTree(stringText, options, conversionFailureOk);
if (tree == null)
Expand All @@ -148,42 +122,24 @@ private void TryParseSubTrees(
{
regex = new Regex(token.ValueText, options);
}
catch (IndexOutOfRangeException) when (allowIndexOutOfRange)
{
// bug with .NET regex parser. Can happen with patterns like: (?<-0
Assert.NotEmpty(tree.Diagnostics);
return treeAndText;
}
catch (NullReferenceException) when (allowNullReference)
{
// bug with .NET regex parser. can happen with patterns like: (?(?S))
return treeAndText;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workarounds for when we found regex strings that would crash .net :) these have been fixed in .net core, so we don't need this.

catch (OutOfMemoryException) when (allowOutOfMemory)
{
// bug with .NET regex parser. can happen with patterns like: a{2147483647,}
return treeAndText;
}
catch (ArgumentException ex)
{
if (!allowDiagnosticsMismatch)
Assert.NotEmpty(tree.Diagnostics);

// Ensure the diagnostic we emit is the same as the .NET one. Note: we can only
// do this in en-US as that's the only culture where we control the text exactly
// and can ensure it exactly matches Regex. We depend on localization to do a
// good enough job here for other languages.
if (Thread.CurrentThread.CurrentCulture.Name == "en-US")
{
Assert.NotEmpty(tree.Diagnostics);

// Ensure the diagnostic we emit is the same as the .NET one. Note: we can only
// do this in en-US as that's the only culture where we control the text exactly
// and can ensure it exactly matches Regex. We depend on localization to do a
// good enough job here for other languages.
if (Thread.CurrentThread.CurrentCulture.Name == "en-US")
{
Assert.True(tree.Diagnostics.Any(d => ex.Message.Contains(d.Message)));
}
var result = tree.Diagnostics.Any(d => ex.Message.Contains(d.Message));
Assert.True(result);
}

return treeAndText;
}

if (!tree.Diagnostics.IsEmpty && !allowDiagnosticsMismatch)
if (!tree.Diagnostics.IsEmpty)
{
var expectedDiagnostics = CreateDiagnosticsElement(sourceText, tree);
Assert.False(true, "Expected diagnostics: \r\n" + expectedDiagnostics.ToString().Replace(@"""", @""""""));
Expand Down
Loading
Loading