File: MetaAnalyzers\Fixers\BasicPreferIsKindFix.vb
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.Analyzers\VisualBasic\Microsoft.CodeAnalysis.VisualBasic.Analyzers.vbproj (Microsoft.CodeAnalysis.VisualBasic.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.
 
Imports System.Composition
Imports Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.Fixers
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Analyzers.MetaAnalyzers.CodeFixes
    <ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=NameOf(BasicPreferIsKindFix))>
    <[Shared]>
    Public NotInheritable Class BasicPreferIsKindFix
        Inherits PreferIsKindFix
 
        <ImportingConstructor>
        <Obsolete("This exported object must be obtained through the MEF export provider.", True)>
        Public Sub New()
        End Sub
 
        Protected Overrides Function TryGetNodeToFix(root As SyntaxNode, span As TextSpan) As SyntaxNode
            Dim binaryExpression = root.FindNode(span, getInnermostNodeForTie:=True).FirstAncestorOrSelf(Of BinaryExpressionSyntax)()
            If binaryExpression.Left.IsKind(SyntaxKind.InvocationExpression) OrElse
                binaryExpression.Left.IsKind(SyntaxKind.SimpleMemberAccessExpression) OrElse
                binaryExpression.Left.IsKind(SyntaxKind.ConditionalAccessExpression) Then
                Return binaryExpression
            End If
 
            Return Nothing
        End Function
 
        Protected Overrides Sub FixDiagnostic(editor As DocumentEditor, nodeToFix As SyntaxNode)
            editor.ReplaceNode(
                nodeToFix,
                Function(nodeToFix2, generator)
                    Dim binaryExpression = DirectCast(nodeToFix2, BinaryExpressionSyntax)
                    Dim invocation = TryCast(binaryExpression.Left, InvocationExpressionSyntax)
                    invocation = If(invocation, TryConvertMemberAccessToInvocation(binaryExpression.Left))
                    invocation = If(invocation, TryConvertConditionalAccessToInvocation(binaryExpression.Left))
                    If invocation Is Nothing Then
                        Return binaryExpression
                    End If
 
                    Dim newInvocation = invocation _
                        .WithExpression(ConvertKindNameToIsKind(invocation.Expression)) _
                        .AddArgumentListArguments(SyntaxFactory.SimpleArgument(binaryExpression.Right.WithoutTrailingTrivia())) _
                        .WithTrailingTrivia(binaryExpression.Right.GetTrailingTrivia())
                    Dim negate = binaryExpression.OperatorToken.IsKind(SyntaxKind.LessThanGreaterThanToken)
                    If negate Then
                        Return SyntaxFactory.NotExpression(newInvocation.WithoutLeadingTrivia()).WithLeadingTrivia(newInvocation.GetLeadingTrivia())
                    Else
                        Return newInvocation
                    End If
                End Function)
        End Sub
 
        Private Shared Function TryConvertMemberAccessToInvocation(expression As ExpressionSyntax) As InvocationExpressionSyntax
            Dim memberAccessExpression = TryCast(expression, MemberAccessExpressionSyntax)
            If memberAccessExpression IsNot Nothing Then
                Return SyntaxFactory.InvocationExpression(memberAccessExpression.WithoutTrailingTrivia()) _
                    .WithTrailingTrivia(memberAccessExpression.GetTrailingTrivia())
            Else
                Return Nothing
            End If
        End Function
 
        Private Shared Function TryConvertConditionalAccessToInvocation(expression As ExpressionSyntax) As InvocationExpressionSyntax
            Dim conditionalAccessExpression = TryCast(expression, ConditionalAccessExpressionSyntax)
            If conditionalAccessExpression IsNot Nothing Then
                Dim simpleMemberAccess = SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    conditionalAccessExpression.Expression.WithoutTrailingTrivia(),
                    SyntaxFactory.Token(SyntaxKind.DotToken), SyntaxFactory.IdentifierName("Kind"))
                Return SyntaxFactory.InvocationExpression(simpleMemberAccess.WithTrailingTrivia(conditionalAccessExpression.GetTrailingTrivia()))
            Else
                Return Nothing
            End If
        End Function
 
        Private Shared Function ConvertKindNameToIsKind(expression As ExpressionSyntax) As ExpressionSyntax
            Dim memberAccessExpression = TryCast(expression, MemberAccessExpressionSyntax)
            If memberAccessExpression IsNot Nothing Then
                Return memberAccessExpression.WithName(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("IsKind")))
            Else
                Return expression
            End If
        End Function
    End Class
End Namespace