File: Microsoft.NetCore.Analyzers\Performance\BasicDoNotGuardCall.Fixer.vb
Web Access
Project: src\src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers\Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers.vbproj (Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers)
' Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.

Imports System.Composition
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.NetCore.Analyzers.Performance

Namespace Microsoft.NetCore.VisualBasic.Analyzers.Performance
    ''' <summary>
    ''' CA1853: <inheritdoc cref="NetCore.Analyzers.MicrosoftNetCoreAnalyzersResources.DoNotGuardDictionaryRemoveByContainsKeyTitle"/>
    ''' CA1868: <inheritdoc cref="NetCore.Analyzers.MicrosoftNetCoreAnalyzersResources.DoNotGuardSetAddOrRemoveByContainsTitle"/>
    ''' </summary>
    <ExportCodeFixProvider(LanguageNames.VisualBasic), [Shared]>
    Public NotInheritable Class BasicDoNotGuardCallFixer
        Inherits DoNotGuardCallFixer

        Protected Overrides Function SyntaxSupportedByFixer(conditionalSyntax As SyntaxNode, childStatementSyntax As SyntaxNode) As Boolean
            If TypeOf childStatementSyntax IsNot ExpressionStatementSyntax Then
                Return False
            End If

            If TypeOf conditionalSyntax Is MultiLineIfBlockSyntax Then
                Dim guardedCallInElse = TypeOf childStatementSyntax.Parent Is ElseBlockSyntax

                If guardedCallInElse Then
                    Return CType(conditionalSyntax, MultiLineIfBlockSyntax).ElseBlock.Statements.Count() = 1
                Else
                    Return CType(conditionalSyntax, MultiLineIfBlockSyntax).Statements.Count() = 1
                End If
            End If

            Return TypeOf conditionalSyntax Is SingleLineIfStatementSyntax
        End Function

        Protected Overrides Function ReplaceConditionWithChild(document As Document, root As SyntaxNode, conditionalOperationNode As SyntaxNode, childOperationNode As SyntaxNode) As Document
            Dim newConditionNode As SyntaxNode = childOperationNode

            ' If there's an else block, negate the condition and replace the single true statement with it
            Dim multiLineIfBlockSyntax = TryCast(conditionalOperationNode, MultiLineIfBlockSyntax)
            If multiLineIfBlockSyntax?.ElseBlock?.ChildNodes().Any() Then
                Dim generator = SyntaxGenerator.GetGenerator(document)
                Dim negatedExpression = generator.LogicalNotExpression(CType(childOperationNode, ExpressionStatementSyntax).Expression.WithoutTrivia())
                Dim guardedCallInElse = TypeOf childOperationNode.Parent Is ElseBlockSyntax

                newConditionNode = multiLineIfBlockSyntax.WithIfStatement(multiLineIfBlockSyntax.IfStatement.WithCondition(CType(negatedExpression, ExpressionSyntax))) _
                    .WithStatements(If(guardedCallInElse, multiLineIfBlockSyntax.Statements, multiLineIfBlockSyntax.ElseBlock.Statements)) _
                    .WithElseBlock(Nothing) _
                    .WithAdditionalAnnotations(Formatter.Annotation).WithTriviaFrom(conditionalOperationNode)
            Else
                ' if there's an else statement, negate the condition and replace the single true statement with it
                Dim singleLineIfBlockSyntax = TryCast(conditionalOperationNode, SingleLineIfStatementSyntax)
                If singleLineIfBlockSyntax?.ElseClause?.ChildNodes().Any() Then
                    Dim generator = SyntaxGenerator.GetGenerator(document)
                    Dim negatedExpression = generator.LogicalNotExpression(CType(childOperationNode, ExpressionStatementSyntax).Expression.WithoutTrivia())
                    Dim guardedCallInElse = TypeOf childOperationNode.Parent Is SingleLineElseClauseSyntax

                    newConditionNode = singleLineIfBlockSyntax.WithCondition(CType(negatedExpression, ExpressionSyntax)) _
                        .WithStatements(If(guardedCallInElse, singleLineIfBlockSyntax.Statements, singleLineIfBlockSyntax.ElseClause.Statements)) _
                        .WithElseClause(Nothing) _
                        .WithAdditionalAnnotations(Formatter.Annotation).WithTriviaFrom(conditionalOperationNode)
                Else
                    newConditionNode = newConditionNode.WithAdditionalAnnotations(Formatter.Annotation).WithTriviaFrom(conditionalOperationNode)
                End If
            End If

            Dim newRoot = root.ReplaceNode(conditionalOperationNode, newConditionNode)

            Return document.WithSyntaxRoot(newRoot)
        End Function
    End Class
End Namespace