| File: MetaAnalyzers\Fixers\CSharpPreferIsKindFix.cs | Web Access |
| Project: src\roslyn\src\RoslynAnalyzers\Microsoft.CodeAnalysis.Analyzers\CSharp\Microsoft.CodeAnalysis.CSharp.Analyzers.csproj (Microsoft.CodeAnalysis.CSharp.Analyzers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Composition; using System.Diagnostics; using Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers.Fixers { [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CSharpPreferIsKindFix))] [Shared] [method: ImportingConstructor] [method: Obsolete("This exported object must be obtained through the MEF export provider.", error: true)] public sealed class CSharpPreferIsKindFix() : PreferIsKindFix { protected override SyntaxNode? TryGetNodeToFix(SyntaxNode root, TextSpan span) { var binaryExpression = root.FindNode(span, getInnermostNodeForTie: true).FirstAncestorOrSelf<BinaryExpressionSyntax>(); if (binaryExpression is null) return null; if (binaryExpression.Left.IsKind(SyntaxKind.InvocationExpression) || binaryExpression.Left.IsKind(SyntaxKind.ConditionalAccessExpression)) { return binaryExpression; } return null; } protected override void FixDiagnostic(DocumentEditor editor, SyntaxNode nodeToFix) { editor.ReplaceNode( nodeToFix, (nodeToFix, generator) => { var binaryExpression = (BinaryExpressionSyntax)nodeToFix; InvocationExpressionSyntax? newInvocation = null; if (binaryExpression.Left.IsKind(SyntaxKind.ConditionalAccessExpression)) { var conditionalAccess = (ConditionalAccessExpressionSyntax)binaryExpression.Left; newInvocation = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, conditionalAccess.Expression, SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("IsKind")))); } else if (binaryExpression.Left.IsKind(SyntaxKind.InvocationExpression)) { var invocation = (InvocationExpressionSyntax)binaryExpression.Left; newInvocation = invocation.WithExpression(ConvertKindNameToIsKind(invocation.Expression)); } else { Debug.Fail("Unreachable."); return nodeToFix; } newInvocation = newInvocation .AddArgumentListArguments(SyntaxFactory.Argument(binaryExpression.Right.WithoutTrailingTrivia())) .WithTrailingTrivia(binaryExpression.Right.GetTrailingTrivia()); var negate = binaryExpression.OperatorToken.IsKind(SyntaxKind.ExclamationEqualsToken); if (negate) { return SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, newInvocation.WithoutLeadingTrivia()).WithLeadingTrivia(newInvocation.GetLeadingTrivia()); } else { return newInvocation; } }); } private static ExpressionSyntax ConvertKindNameToIsKind(ExpressionSyntax expression) { if (expression is MemberAccessExpressionSyntax memberAccessExpression) { return memberAccessExpression.WithName(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("IsKind"))); } else { return expression; } } } }