From fa98aa7fa789f9315dcfa031fac132068c1c42b4 Mon Sep 17 00:00:00 2001 From: Louis Zanella Date: Mon, 23 Dec 2024 11:06:50 -0500 Subject: [PATCH] Fix CA1862 false positive with same variable on both sides of comparison --- ...aseInsensitiveStringComparison.Analyzer.cs | 19 +++++++++++++++ ...nsensitiveStringComparison.CSharp.Tests.cs | 24 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs index 87cc05d5cc..1a6ecdc050 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.Analyzer.cs @@ -322,6 +322,15 @@ private static void AnalyzeBinaryOperation(OperationAnalysisContext context, IBi return; } + // If using the same parameter on both sides of the binary operation, don't emit a diagnostic. + var lParam = GetParameter(binaryOperation.LeftOperand); + var rParam = GetParameter(binaryOperation.RightOperand); + + if (lParam is not null && lParam == rParam) + { + return; + } + ImmutableDictionary dict = new Dictionary() { { LeftOffendingMethodName, leftOffendingMethodName }, @@ -380,5 +389,15 @@ private static bool IsOffendingMethod(IInvocationOperation invocation, ITypeSymb offendingMethodName = invocation.TargetMethod.Name; return true; } + + private static IParameterSymbol? GetParameter(IOperation op) + { + return op switch + { + IParameterReferenceOperation paramRefOp => paramRefOp.Parameter, + IInvocationOperation invocationOp => GetParameter(invocationOp.Children.FirstOrDefault()), + _ => null, + }; + } } } diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs index 6b835da3a7..9692ea30e1 100644 --- a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Performance/RecommendCaseInsensitiveStringComparison.CSharp.Tests.cs @@ -431,6 +431,30 @@ void M(string s) }.RunAsync(); } + [Theory] + [InlineData("s != s.ToLowerInvariant()")] + [InlineData("s.ToLower() == s")] + [InlineData("s.ToUpperInvariant() == s.ToUpper()")] + [InlineData("s.ToLower().ToUpper() != s")] + [WorkItem(7074, "https://github.com/dotnet/roslyn-analyzers/issues/7074")] + public async Task NoDiagnostic_SameParameterOnBothSidesOfComparison(string expression) + { + var originalCode = $$""" + using System; + + class C + { + void M(string s) + { + if ({{expression}}) + Console.WriteLine("string comparison was true"); + } + } + """; + + await VerifyNoDiagnosticCSharpAsync(originalCode); + } + private async Task VerifyNoDiagnosticCSharpAsync(string originalSource) { VerifyCS.Test test = new()