From 84f6ea9639a98fab363387c0c7339ffda5846af0 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 13 Mar 2024 20:33:51 +0100 Subject: [PATCH] Fix RCS1077 (#1421) --- ChangeLog.md | 1 + .../OptimizeLinqMethodCallCodeFixProvider.cs | 34 ++----------------- .../OptimizeLinqMethodCallAnalysis.cs | 19 ++--------- .../RCS1077OptimizeLinqMethodCallTests.cs | 17 ++-------- 4 files changed, 9 insertions(+), 62 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 5aed4baa7b..478491af8e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix analyzer [RCS1267](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1267) ([PR](https://github.com/dotnet/roslynator/pull/1412)) - Fix "Unknown value 'Default'" exception ([PR](https://github.com/dotnet/roslynator/pull/1411)) - Fix name of `UnityEngine.SerializeField` attribute ([PR](https://github.com/dotnet/roslynator/pull/1419)) +- Fix analyzer [RCS1077](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1077) ([PR](https://github.com/dotnet/roslynator/pull/1421)) ## [4.11.0] - 2024-02-19 diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/OptimizeLinqMethodCallCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/OptimizeLinqMethodCallCodeFixProvider.cs index 13b12848d4..e93a85e216 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/OptimizeLinqMethodCallCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/OptimizeLinqMethodCallCodeFixProvider.cs @@ -184,7 +184,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) CodeAction codeAction = CodeAction.Create( "Call 'Find' instead of 'FirstOrDefault'", - ct => CallFindInsteadOfFirstOrDefaultAsync(document, invocationInfo, semanticModel, ct), + ct => CallFindInsteadOfFirstOrDefaultAsync(document, invocationInfo, ct), GetEquivalenceKey(diagnostic, "CallFindInsteadOfFirstOrDefault")); context.RegisterCodeFix(codeAction, diagnostic); @@ -419,39 +419,11 @@ private static Task CallCastInsteadOfSelectAsync( private static Task CallFindInsteadOfFirstOrDefaultAsync( Document document, in SimpleMemberInvocationExpressionInfo invocationInfo, - SemanticModel semanticModel, CancellationToken cancellationToken) { - ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(invocationInfo.Expression, cancellationToken); + IdentifierNameSyntax newName = IdentifierName("Find").WithTriviaFrom(invocationInfo.Name); - if (typeSymbol is IArrayTypeSymbol { Rank: 1 }) - { - NameSyntax arrayName = ParseName("global::System.Array") - .WithLeadingTrivia(invocationInfo.InvocationExpression.GetLeadingTrivia()) - .WithSimplifierAnnotation(); - - MemberAccessExpressionSyntax newMemberAccess = SimpleMemberAccessExpression( - arrayName, - invocationInfo.OperatorToken, - IdentifierName("Find").WithTriviaFrom(invocationInfo.Name)); - - ArgumentListSyntax argumentList = invocationInfo.ArgumentList; - - InvocationExpressionSyntax newInvocation = InvocationExpression( - newMemberAccess, - ArgumentList( - Argument(invocationInfo.Expression.WithoutTrivia()), - argumentList.Arguments[0]) - .WithTriviaFrom(argumentList)); - - return document.ReplaceNodeAsync(invocationInfo.InvocationExpression, newInvocation, cancellationToken); - } - else - { - IdentifierNameSyntax newName = IdentifierName("Find").WithTriviaFrom(invocationInfo.Name); - - return document.ReplaceNodeAsync(invocationInfo.Name, newName, cancellationToken); - } + return document.ReplaceNodeAsync(invocationInfo.Name, newName, cancellationToken); } public static Task UseCountOrLengthPropertyInsteadOfCountMethodAsync( diff --git a/src/Analyzers/CSharp/Analysis/OptimizeLinqMethodCallAnalysis.cs b/src/Analyzers/CSharp/Analysis/OptimizeLinqMethodCallAnalysis.cs index 4e20d64fb8..276a4c7355 100644 --- a/src/Analyzers/CSharp/Analysis/OptimizeLinqMethodCallAnalysis.cs +++ b/src/Analyzers/CSharp/Analysis/OptimizeLinqMethodCallAnalysis.cs @@ -236,23 +236,10 @@ public static void AnalyzeFirstOrDefault(SyntaxNodeAnalysisContext context, in S { ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(invocationInfo.Expression, context.CancellationToken); - if (typeSymbol is not null) + if (typeSymbol?.OriginalDefinition.HasMetadataName(MetadataNames.System_Collections_Generic_List_T) == true) { - if (typeSymbol.Kind == SymbolKind.ArrayType) - { - if (((IArrayTypeSymbol)typeSymbol).Rank == 1 - && !invocationInfo.Expression.IsKind(SyntaxKind.MemberBindingExpression) - && context.SemanticModel.Compilation.GetTypeByMetadataName("System.Array").GetMembers("Find").Any()) - { - Report(context, invocationInfo.Name); - return; - } - } - else if (typeSymbol.OriginalDefinition.HasMetadataName(MetadataNames.System_Collections_Generic_List_T)) - { - Report(context, invocationInfo.Name); - return; - } + Report(context, invocationInfo.Name); + return; } success = true; diff --git a/src/Tests/Analyzers.Tests/RCS1077OptimizeLinqMethodCallTests.cs b/src/Tests/Analyzers.Tests/RCS1077OptimizeLinqMethodCallTests.cs index 1ce5eb8d80..18b68d953c 100644 --- a/src/Tests/Analyzers.Tests/RCS1077OptimizeLinqMethodCallTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1077OptimizeLinqMethodCallTests.cs @@ -711,20 +711,7 @@ void M() [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.OptimizeLinqMethodCall)] public async Task Test_CallFindInsteadOfFirstOrDefault_Array() { - await VerifyDiagnosticAndFixAsync(@" -using System; -using System.Linq; - -class C -{ - void M() - { - var items = new object[0]; - - var x = items.[|FirstOrDefault|](_ => true); - } -} -", @" + await VerifyNoDiagnosticAsync(@" using System; using System.Linq; @@ -734,7 +721,7 @@ void M() { var items = new object[0]; - var x = Array.Find(items, _ => true); + var x = items.FirstOrDefault(_ => true); } } ");