diff --git a/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs b/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs index 0aa0149c48..7adb4fbe59 100644 --- a/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs +++ b/src/PublicApiAnalyzers/Core/CodeFixes/DeclarePublicApiFix.cs @@ -115,7 +115,7 @@ static void insertInList(List list, string name) { for (int i = 0; i < list.Count; i++) { - if (string.Compare(name, list[i], StringComparison.Ordinal) < 0) + if (IgnoreCaseWhenPossibleComparer.Instance.Compare(name, list[i]) < 0) { list.Insert(i, name); return; @@ -231,7 +231,7 @@ await publicSurfaceAreaAdditionalDocument.GetTextAsync(cancellationToken).Config .Where(d => d.Location.IsInSource) .GroupBy(d => d.Location.SourceTree); - var newSymbolNames = new SortedSet(); + var newSymbolNames = new SortedSet(IgnoreCaseWhenPossibleComparer.Instance); var symbolNamesToRemoveBuilder = PooledHashSet.GetInstance(); foreach (IGrouping grouping in groupedDiagnostics) @@ -358,5 +358,23 @@ private class PublicSurfaceAreaFixAllProvider : FixAllProvider return new FixAllAdditionalDocumentChangeAction(title, fixAllContext.Solution, diagnosticsToFix); } } + + private sealed class IgnoreCaseWhenPossibleComparer : IComparer + { + public static readonly IgnoreCaseWhenPossibleComparer Instance = new(); + + private IgnoreCaseWhenPossibleComparer() + { + } + + public int Compare(string x, string y) + { + var result = StringComparer.OrdinalIgnoreCase.Compare(x, y); + if (result == 0) + result = StringComparer.Ordinal.Compare(x, y); + + return result; + } + } } } diff --git a/src/PublicApiAnalyzers/UnitTests/DeclarePublicApiAnalyzerTests.cs b/src/PublicApiAnalyzers/UnitTests/DeclarePublicApiAnalyzerTests.cs index 8bc3111f29..6b943c43e8 100644 --- a/src/PublicApiAnalyzers/UnitTests/DeclarePublicApiAnalyzerTests.cs +++ b/src/PublicApiAnalyzers/UnitTests/DeclarePublicApiAnalyzerTests.cs @@ -1757,6 +1757,35 @@ public class {|RS0016:{|RS0016:C2|}|} { } await VerifyCSharpAdditionalFileFixAsync(source, shippedText, unshippedText, fixedUnshippedText); } + [Fact] + public async Task TestMultipleMissingTypeAndMember_CaseSensitiveFix() + { + var source = @" +public class {|RS0016:C|} +{ + private C() { } + public int {|RS0016:Field_A|}; + public int {|RS0016:Field_b|}; + public int {|RS0016:Field_C|}; + public int {|RS0016:Field_d|}; +} + +public class {|RS0016:{|RS0016:C2|}|} { } +"; + + var shippedText = @""; + var unshippedText = @""; + var fixedUnshippedText = @"C +C.Field_A -> int +C.Field_b -> int +C.Field_C -> int +C.Field_d -> int +C2 +C2.C2() -> void"; + + await VerifyCSharpAdditionalFileFixAsync(source, shippedText, unshippedText, fixedUnshippedText); + } + [Fact] public async Task TestChangingMethodSignatureForAnUnshippedMethod_Fix() {