Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ private static RegexOptions GetRegexOptionsFromArgument(ImmutableArray<IArgument
return SyntaxFactory.ParseExpression(optionsLiteral);

case UpgradeToGeneratedRegexAnalyzer.PatternArgumentName:
if (argument.Value.ConstantValue.Value is string str && str.Contains('\\'))
if (argument.Value.ConstantValue.Value is string str && ShouldUseVerbatimString(str))
{
// Special handling for string patterns with escaped characters
// Special handling for string patterns with escaped characters or newlines
string escapedVerbatimText = str.Replace("\"", "\"\"");
return SyntaxFactory.ParseExpression($"@\"{escapedVerbatimText}\"");
}
Expand All @@ -401,6 +401,13 @@ private static RegexOptions GetRegexOptionsFromArgument(ImmutableArray<IArgument
return null;
}

private static bool ShouldUseVerbatimString(string str)
{
// Use verbatim string syntax if the string contains backslashes or newlines
// to preserve readability, especially for patterns with RegexOptions.IgnorePatternWhitespace
return str.IndexOfAny(['\\', '\n', '\r']) >= 0;
}

private static string Literal(string stringifiedRegexOptions)
{
if (int.TryParse(stringifiedRegexOptions, NumberStyles.Integer, CultureInfo.InvariantCulture, out int options))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,67 @@ static void Main(string[] args)
await VerifyCS.VerifyCodeFixAsync(test, expectedFixedCode);
}

[Fact]
public async Task MultilineVerbatimStringPreservedByFixer()
{
string test = """
using System.Text.RegularExpressions;

static class Class
{
private static Regex r = [|new Regex(@"a
b
c", RegexOptions.IgnorePatternWhitespace)|];
}
""";

string expectedFixedCode = """
using System.Text.RegularExpressions;

static partial class Class
{
[GeneratedRegex(@"a
b
c", RegexOptions.IgnorePatternWhitespace)]
private static partial Regex r { get; }
}
""";

await VerifyCS.VerifyCodeFixAsync(test, expectedFixedCode);
}

[Fact]
public async Task MultilineStringConcatenationPreservedByFixer()
{
string test = """
using System.Text.RegularExpressions;

static class Class
{
private const string foo = "bar";
private static Regex r1 = [|new Regex(@"a " + foo + @"
b
c", RegexOptions.IgnorePatternWhitespace)|];
}
""";

string expectedFixedCode = """
using System.Text.RegularExpressions;

static partial class Class
{
private const string foo = "bar";

[GeneratedRegex(@"a bar
b
c", RegexOptions.IgnorePatternWhitespace)]
private static partial Regex r1 { get; }
}
""";

await VerifyCS.VerifyCodeFixAsync(test, expectedFixedCode);
}

[Fact]
public async Task TestAsArgument()
{
Expand Down