Skip to content

Commit

Permalink
Fix RCS1077 (#1421)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Mar 13, 2024
1 parent dd70714 commit 84f6ea9
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 62 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Expand Up @@ -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

Expand Down
Expand Up @@ -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);
Expand Down Expand Up @@ -419,39 +419,11 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
private static Task<Document> 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<Document> UseCountOrLengthPropertyInsteadOfCountMethodAsync(
Expand Down
19 changes: 3 additions & 16 deletions src/Analyzers/CSharp/Analysis/OptimizeLinqMethodCallAnalysis.cs
Expand Up @@ -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;
Expand Down
17 changes: 2 additions & 15 deletions src/Tests/Analyzers.Tests/RCS1077OptimizeLinqMethodCallTests.cs
Expand Up @@ -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;
Expand All @@ -734,7 +721,7 @@ void M()
{
var items = new object[0];
var x = Array.Find(items, _ => true);
var x = items.FirstOrDefault(_ => true);
}
}
");
Expand Down

0 comments on commit 84f6ea9

Please sign in to comment.