File: Microsoft.NetCore.Analyzers\Performance\CSharpPreferLengthCountIsEmptyOverAny.Fixer.cs
Web Access
Project: ..\..\..\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.CSharp.NetAnalyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.csproj (Microsoft.CodeAnalysis.CSharp.NetAnalyzers)
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
 
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.NetCore.Analyzers.Performance;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
namespace Microsoft.NetCore.CSharp.Analyzers.Performance
{
    [ExportCodeFixProvider(LanguageNames.CSharp), Shared]
    public sealed class CSharpPreferLengthCountIsEmptyOverAnyFixer : PreferLengthCountIsEmptyOverAnyFixer
    {
        protected override SyntaxNode? ReplaceAnyWithIsEmpty(SyntaxNode root, SyntaxNode node)
        {
            if (node is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax memberAccess } invocation)
            {
                return null;
            }
 
            var expression = memberAccess.Expression;
            if (invocation.ArgumentList.Arguments.Count > 0)
            {
                expression = invocation.ArgumentList.Arguments[0].Expression;
            }
 
            var newMemberAccess = MemberAccessExpression(
                SyntaxKind.SimpleMemberAccessExpression,
                expression,
                IdentifierName(PreferLengthCountIsEmptyOverAnyAnalyzer.IsEmptyText)
            );
            if (invocation.Parent.IsKind(SyntaxKind.LogicalNotExpression))
            {
                return root.ReplaceNode(invocation.Parent, newMemberAccess.WithTriviaFrom(invocation.Parent));
            }
 
            var negatedExpression = PrefixUnaryExpression(
                SyntaxKind.LogicalNotExpression,
                newMemberAccess
            );
 
            return root.ReplaceNode(invocation, negatedExpression.WithTriviaFrom(invocation));
        }
 
        protected override SyntaxNode? ReplaceAnyWithLength(SyntaxNode root, SyntaxNode node)
        {
            return ReplaceAnyWithPropertyCheck(root, node, PreferLengthCountIsEmptyOverAnyAnalyzer.LengthText);
        }
 
        protected override SyntaxNode? ReplaceAnyWithCount(SyntaxNode root, SyntaxNode node)
        {
            return ReplaceAnyWithPropertyCheck(root, node, PreferLengthCountIsEmptyOverAnyAnalyzer.CountText);
        }
 
        private static SyntaxNode? ReplaceAnyWithPropertyCheck(SyntaxNode root, SyntaxNode node, string propertyName)
        {
            if (node is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax memberAccess } invocation)
            {
                return null;
            }
 
            var expression = memberAccess.Expression;
            if (invocation.ArgumentList.Arguments.Count > 0)
            {
                // .Any() used like a normal static method and not like an extension method.
                expression = invocation.ArgumentList.Arguments[0].Expression;
            }
 
            static BinaryExpressionSyntax GetBinaryExpression(ExpressionSyntax expression, string member, SyntaxKind expressionKind)
            {
                return BinaryExpression(
                    expressionKind,
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        expression,
                        IdentifierName(member)
                    ),
                    LiteralExpression(
                        SyntaxKind.NumericLiteralExpression,
                        Literal(0)
                    )
                );
            }
 
            if (invocation.Parent.IsKind(SyntaxKind.LogicalNotExpression))
            {
                var binaryExpression = GetBinaryExpression(expression, propertyName, SyntaxKind.EqualsExpression);
 
                return root.ReplaceNode(invocation.Parent, binaryExpression.WithTriviaFrom(invocation.Parent));
            }
 
            return root.ReplaceNode(invocation, GetBinaryExpression(expression, propertyName, SyntaxKind.NotEqualsExpression).WithTriviaFrom(invocation));
        }
    }
}