Skip to content

Commit 6df56d8

Browse files
committed
Fix SearchValues fixer introducing slight changes for edge case inputs
1 parent 8011355 commit 6df56d8

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Performance/CSharpUseSearchValues.Fixer.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,19 @@ protected override SyntaxNode GetDeclaratorInitializer(SyntaxNode syntax)
8989
values.Count <= 128 && // Arbitrary limit to avoid emitting huge literals
9090
!ContainsAnyComments(creationSyntax)) // Avoid removing potentially valuable comments
9191
{
92+
if (isByte)
93+
{
94+
foreach (char c in values)
95+
{
96+
if (c > 127)
97+
{
98+
// We shouldn't turn non-ASCII byte values into Utf8StringLiterals as that may change behavior.
99+
// e.g. (byte)'ÿ' means 0xFF, but "ÿ"u8 is two bytes (0xC3, 0xBF) that encode that character in UTF8.
100+
return null;
101+
}
102+
}
103+
}
104+
92105
string valuesString = string.Concat(values);
93106
string stringLiteral = SymbolDisplay.FormatLiteral(valuesString, quote: true);
94107

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/UseSearchValuesTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,42 @@ private void TestMethod(string text)
771771
await VerifyCodeFixAsync(LanguageVersion.CSharp7_3, source, expected);
772772
}
773773

774+
[Fact]
775+
public async Task TestCodeFixerDoesNotUseUtf8StringLiteralsForNonAsciiChars()
776+
{
777+
string source =
778+
"""
779+
using System;
780+
using System.Buffers;
781+
782+
internal sealed class Test
783+
{
784+
private void TestMethod(ReadOnlySpan<byte> span)
785+
{
786+
_ = span.IndexOfAny([|new[] { (byte)'ÿ', (byte)'a', (byte)'e', (byte)'i', (byte)'o', (byte)'u' }|]);
787+
}
788+
}
789+
""";
790+
791+
string expected =
792+
"""
793+
using System;
794+
using System.Buffers;
795+
796+
internal sealed class Test
797+
{
798+
private static readonly SearchValues<byte> s_myBytes = SearchValues.Create(new[] { (byte)'ÿ', (byte)'a', (byte)'e', (byte)'i', (byte)'o', (byte)'u' });
799+
800+
private void TestMethod(ReadOnlySpan<byte> span)
801+
{
802+
_ = span.IndexOfAny(s_myBytes);
803+
}
804+
}
805+
""";
806+
807+
await VerifyCodeFixAsync(LanguageVersion.CSharp11, source, expected);
808+
}
809+
774810
[Fact]
775811
public static async Task TestCodeFixerDoesNotRemoveTheOriginalMemberIfPublic()
776812
{

0 commit comments

Comments
 (0)