| File: Microsoft.NetCore.Analyzers\Performance\CSharpPreferLengthCountIsEmptyOverAny.Fixer.cs | Web Access |
| Project: src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.CSharp.NetAnalyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.csproj (Microsoft.CodeAnalysis.CSharp.NetAnalyzers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Composition; using System.Diagnostics.CodeAnalysis; 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? GetNodeToReplace(SyntaxNode node) { if (node is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax } invocation) { return null; } return invocation.Parent.IsKind(SyntaxKind.LogicalNotExpression) ? invocation.Parent : invocation; } protected override SyntaxNode? ReplaceAnyWithIsEmpty(SyntaxNode currentNode) { if (!TrySplit(currentNode, out bool isNegated, out ExpressionSyntax? expression)) { return null; } var newMemberAccess = MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, expression, IdentifierName(PreferLengthCountIsEmptyOverAnyAnalyzer.IsEmptyText) ); if (isNegated) { return newMemberAccess.WithTriviaFrom(currentNode); } return PrefixUnaryExpression( SyntaxKind.LogicalNotExpression, newMemberAccess ).WithTriviaFrom(currentNode); } protected override SyntaxNode? ReplaceAnyWithPropertyCheck(SyntaxNode currentNode, string propertyName) { if (!TrySplit(currentNode, out bool isNegated, out ExpressionSyntax? expression)) { return null; } return BinaryExpression( isNegated ? SyntaxKind.EqualsExpression : SyntaxKind.NotEqualsExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, expression, IdentifierName(propertyName) ), LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0) ) ).WithTriviaFrom(currentNode); } private static bool TrySplit(SyntaxNode currentNode, out bool isNegated, [NotNullWhen(true)] out ExpressionSyntax? expression) { isNegated = currentNode is PrefixUnaryExpressionSyntax { RawKind: (int)SyntaxKind.LogicalNotExpression }; SyntaxNode operand = isNegated ? ((PrefixUnaryExpressionSyntax)currentNode).Operand : currentNode; if (operand is not InvocationExpressionSyntax { Expression: MemberAccessExpressionSyntax memberAccess } invocation) { expression = null; return false; } // `.Any()` used like a normal static method and not like an extension method. expression = invocation.ArgumentList.Arguments.Count > 0 ? invocation.ArgumentList.Arguments[0].Expression : memberAccess.Expression; return true; } } }