File: Lowering\Instrumentation\DebugInfoInjector.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.Collections.Immutable
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    ''' <summary>
    ''' This type is responsible for adding debugging sequence points for the executable code.
    ''' It can be combined with other <see cref="Instrumenter"/>s. Usually, this class should be 
    ''' the root of the chain in order to ensure sound debugging experience for the instrumented code.
    ''' In other words, sequence points are typically applied after all other changes.
    ''' </summary>
    Partial Friend NotInheritable Class DebugInfoInjector
        Inherits CompoundInstrumenter
 
        ''' <summary>
        ''' A singleton object that performs only one type of instrumentation - addition of debugging sequence points. 
        ''' </summary>
        Public Shared ReadOnly Singleton As New DebugInfoInjector(Instrumenter.NoOp)
 
        Public Sub New(previous As Instrumenter)
            MyBase.New(previous)
        End Sub
 
        Private Shared Function MarkStatementWithSequencePoint(original As BoundStatement, rewritten As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(original.Syntax, rewritten)
        End Function
 
        Public Overrides Function InstrumentExpressionStatement(original As BoundExpressionStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentExpressionStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentStopStatement(original As BoundStopStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentStopStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentEndStatement(original As BoundEndStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentEndStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentContinueStatement(original As BoundContinueStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentContinueStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentExitStatement(original As BoundExitStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentExitStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentGotoStatement(original As BoundGotoStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentGotoStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentLabelStatement(original As BoundLabelStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentLabelStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentRaiseEventStatement(original As BoundRaiseEventStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentRaiseEventStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentReturnStatement(original As BoundReturnStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentReturnStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentThrowStatement(original As BoundThrowStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentThrowStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentOnErrorStatement(original As BoundOnErrorStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentOnErrorStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentResumeStatement(original As BoundResumeStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentResumeStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentAddHandlerStatement(original As BoundAddHandlerStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentAddHandlerStatement(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentRemoveHandlerStatement(original As BoundRemoveHandlerStatement, rewritten As BoundStatement) As BoundStatement
            Return MarkStatementWithSequencePoint(original, MyBase.InstrumentRemoveHandlerStatement(original, rewritten))
        End Function
 
        Public Overrides Function CreateBlockPrologue(trueOriginal As BoundBlock, original As BoundBlock, ByRef synthesizedLocal As LocalSymbol) As BoundStatement
            Return CreateBlockPrologue(original, MyBase.CreateBlockPrologue(trueOriginal, original, synthesizedLocal))
        End Function
 
        Public Overrides Function InstrumentTopLevelExpressionInQuery(original As BoundExpression, rewritten As BoundExpression) As BoundExpression
            rewritten = MyBase.InstrumentTopLevelExpressionInQuery(original, rewritten)
            Return New BoundSequencePointExpression(original.Syntax, rewritten, rewritten.Type)
        End Function
 
        Public Overrides Function InstrumentQueryLambdaBody(original As BoundQueryLambda, rewritten As BoundStatement) As BoundStatement
            rewritten = MyBase.InstrumentQueryLambdaBody(original, rewritten)
 
            Dim createSequencePoint As SyntaxNode = Nothing
            Dim sequencePointSpan As TextSpan
 
            Select Case original.LambdaSymbol.SynthesizedKind
                Case SynthesizedLambdaKind.AggregateQueryLambda
                    Dim aggregateClause = DirectCast(original.Syntax.Parent.Parent, AggregateClauseSyntax)
 
                    If aggregateClause.AggregationVariables.Count = 1 Then
                        ' We are dealing with a simple case of an Aggregate clause - a single aggregate
                        ' function in the Into clause. This lambda is responsible for calculating that
                        ' aggregate function. Actually, it includes all code generated for the entire
                        ' Aggregate clause. We should create sequence point for the entire clause
                        ' rather than sequence points for the top level expressions within the lambda.
                        createSequencePoint = aggregateClause
                        sequencePointSpan = aggregateClause.Span
                    Else
                        ' We should create sequence point that spans from beginning of the Aggregate clause 
                        ' to the beginning of the Into clause because all that code is involved into group calculation.
 
                        createSequencePoint = aggregateClause
                        If aggregateClause.AdditionalQueryOperators.Count = 0 Then
                            sequencePointSpan = TextSpan.FromBounds(aggregateClause.SpanStart,
                                                                    aggregateClause.Variables.Last.Span.End)
                        Else
                            sequencePointSpan = TextSpan.FromBounds(aggregateClause.SpanStart,
                                                                    aggregateClause.AdditionalQueryOperators.Last.Span.End)
                        End If
                    End If
 
                Case SynthesizedLambdaKind.LetVariableQueryLambda
                    ' We will apply sequence points to synthesized return statements if they are contained in LetClause
                    Debug.Assert(original.Syntax.Parent.IsKind(SyntaxKind.ExpressionRangeVariable))
 
                    createSequencePoint = original.Syntax
                    sequencePointSpan = TextSpan.FromBounds(original.Syntax.SpanStart, original.Syntax.Span.End)
            End Select
 
            If createSequencePoint IsNot Nothing Then
                rewritten = New BoundSequencePointWithSpan(createSequencePoint, rewritten, sequencePointSpan)
            End If
 
            Return rewritten
        End Function
 
        Public Overrides Function InstrumentDoLoopEpilogue(original As BoundDoLoopStatement, epilogueOpt As BoundStatement) As BoundStatement
            ' adds EndXXX sequence point to a statement
            ' NOTE: if target statement happens to be a block, then 
            ' sequence point goes inside the block
            ' This ensures that when we stopped on EndXXX, we are still in the block's scope
            ' and can examine locals declared in the block.
            Return New BoundSequencePoint(DirectCast(original.Syntax, DoLoopBlockSyntax).LoopStatement, MyBase.InstrumentDoLoopEpilogue(original, epilogueOpt))
        End Function
 
        Public Overrides Function CreateSyncLockStatementPrologue(original As BoundSyncLockStatement) As BoundStatement
            ' create a sequence point that contains the whole SyncLock statement as the first reachable sequence point
            ' of the SyncLock statement. 
            Return New BoundSequencePoint(DirectCast(original.Syntax, SyncLockBlockSyntax).SyncLockStatement, MyBase.CreateSyncLockStatementPrologue(original))
        End Function
 
        Public Overrides Function InstrumentSyncLockObjectCapture(original As BoundSyncLockStatement, rewritten As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(original.LockExpression.Syntax, MyBase.InstrumentSyncLockObjectCapture(original, rewritten))
        End Function
 
        Public Overrides Function CreateSyncLockExitDueToExceptionEpilogue(original As BoundSyncLockStatement) As BoundStatement
            ' Add a sequence point to highlight the "End SyncLock" syntax in case the body has thrown an exception
            Return New BoundSequencePoint(DirectCast(original.Syntax, SyncLockBlockSyntax).EndSyncLockStatement, MyBase.CreateSyncLockExitDueToExceptionEpilogue(original))
        End Function
 
        Public Overrides Function CreateSyncLockExitNormallyEpilogue(original As BoundSyncLockStatement) As BoundStatement
            ' Add a sequence point to highlight the "End SyncLock" syntax in case the body has been complete executed and
            ' exited normally
            Return New BoundSequencePoint(DirectCast(original.Syntax, SyncLockBlockSyntax).EndSyncLockStatement, MyBase.CreateSyncLockExitNormallyEpilogue(original))
        End Function
 
        Public Overrides Function InstrumentWhileEpilogue(original As BoundWhileStatement, epilogueOpt As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, WhileBlockSyntax).EndWhileStatement, MyBase.InstrumentWhileEpilogue(original, epilogueOpt))
        End Function
 
        Public Overrides Function InstrumentWhileStatementConditionalGotoStart(original As BoundWhileStatement, ifConditionGotoStart As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, WhileBlockSyntax).WhileStatement,
                                          MyBase.InstrumentWhileStatementConditionalGotoStart(original, ifConditionGotoStart))
        End Function
 
        Public Overrides Function InstrumentDoLoopStatementEntryOrConditionalGotoStart(original As BoundDoLoopStatement, ifConditionGotoStartOpt As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, DoLoopBlockSyntax).DoStatement,
                                          MyBase.InstrumentDoLoopStatementEntryOrConditionalGotoStart(original, ifConditionGotoStartOpt))
        End Function
 
        Public Overrides Function InstrumentForEachStatementConditionalGotoStart(original As BoundForEachStatement, ifConditionGotoStart As BoundStatement) As BoundStatement
            ' Add hidden sequence point
            Return New BoundSequencePoint(Nothing, MyBase.InstrumentForEachStatementConditionalGotoStart(original, ifConditionGotoStart))
        End Function
 
        Public Overrides Function InstrumentIfStatementConditionalGoto(original As BoundIfStatement, condGoto As BoundStatement) As BoundStatement
            condGoto = MyBase.InstrumentIfStatementConditionalGoto(original, condGoto)
 
            Select Case original.Syntax.Kind
                Case SyntaxKind.MultiLineIfBlock
                    Dim asMultiline = DirectCast(original.Syntax, MultiLineIfBlockSyntax)
                    condGoto = New BoundSequencePoint(asMultiline.IfStatement, condGoto)
                Case SyntaxKind.ElseIfBlock
                    Dim asElseIfBlock = DirectCast(original.Syntax, ElseIfBlockSyntax)
                    condGoto = New BoundSequencePoint(asElseIfBlock.ElseIfStatement, condGoto)
                Case SyntaxKind.SingleLineIfStatement
                    Dim asSingleLine = DirectCast(original.Syntax, SingleLineIfStatementSyntax)
                    condGoto = New BoundSequencePointWithSpan(asSingleLine, condGoto, TextSpan.FromBounds(asSingleLine.IfKeyword.SpanStart, asSingleLine.ThenKeyword.EndPosition - 1))
            End Select
 
            Return condGoto
        End Function
 
        Public Overrides Function InstrumentIfStatementAfterIfStatement(original As BoundIfStatement, afterIfStatement As BoundStatement) As BoundStatement
            ' Associate afterIf with EndIf
            Return New BoundSequencePoint(DirectCast(original.Syntax, MultiLineIfBlockSyntax).EndIfStatement,
                                          MyBase.InstrumentIfStatementAfterIfStatement(original, afterIfStatement))
        End Function
 
        Public Overrides Function InstrumentIfStatementConsequenceEpilogue(original As BoundIfStatement, epilogueOpt As BoundStatement) As BoundStatement
            epilogueOpt = MyBase.InstrumentIfStatementConsequenceEpilogue(original, epilogueOpt)
 
            Dim syntax As VisualBasicSyntaxNode = Nothing
            Select Case original.Syntax.Kind
                Case SyntaxKind.MultiLineIfBlock
                    syntax = DirectCast(original.Syntax, MultiLineIfBlockSyntax).EndIfStatement
                Case SyntaxKind.ElseIfBlock
                    syntax = DirectCast(original.Syntax.Parent, MultiLineIfBlockSyntax).EndIfStatement
                Case SyntaxKind.SingleLineIfStatement
                    ' single line if has no EndIf
                    Return epilogueOpt
            End Select
 
            Return New BoundSequencePoint(syntax, epilogueOpt)
        End Function
 
        Public Overrides Function InstrumentIfStatementAlternativeEpilogue(original As BoundIfStatement, epilogueOpt As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.AlternativeOpt.Syntax.Parent, MultiLineIfBlockSyntax).EndIfStatement,
                                          MyBase.InstrumentIfStatementAlternativeEpilogue(original, epilogueOpt))
        End Function
 
        Public Overrides Function CreateIfStatementAlternativePrologue(original As BoundIfStatement) As BoundStatement
            Dim prologue = MyBase.CreateIfStatementAlternativePrologue(original)
 
            Select Case original.AlternativeOpt.Syntax.Kind
                Case SyntaxKind.ElseBlock
                    prologue = New BoundSequencePoint(DirectCast(original.AlternativeOpt.Syntax, ElseBlockSyntax).ElseStatement, prologue)
                Case SyntaxKind.SingleLineElseClause
                    prologue = New BoundSequencePointWithSpan(original.AlternativeOpt.Syntax, prologue,
                                                              DirectCast(original.AlternativeOpt.Syntax, SingleLineElseClauseSyntax).ElseKeyword.Span)
            End Select
 
            Return prologue
        End Function
 
        Public Overrides Function InstrumentDoLoopStatementCondition(original As BoundDoLoopStatement, rewrittenCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentDoLoopStatementCondition(original, rewrittenCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentWhileStatementCondition(original As BoundWhileStatement, rewrittenCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentWhileStatementCondition(original, rewrittenCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentForEachStatementCondition(original As BoundForEachStatement, rewrittenCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentForEachStatementCondition(original, rewrittenCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentObjectForLoopInitCondition(original As BoundForToStatement, rewrittenInitCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentObjectForLoopInitCondition(original, rewrittenInitCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentObjectForLoopCondition(original As BoundForToStatement, rewrittenLoopCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentObjectForLoopCondition(original, rewrittenLoopCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentIfStatementCondition(original As BoundIfStatement, rewrittenCondition As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentIfStatementCondition(original, rewrittenCondition, currentMethodOrLambda), original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function InstrumentCatchBlockFilter(original As BoundCatchBlock, rewrittenFilter As BoundExpression, currentMethodOrLambda As MethodSymbol) As BoundExpression
            rewrittenFilter = MyBase.InstrumentCatchBlockFilter(original, rewrittenFilter, currentMethodOrLambda)
 
            ' if we have a filter, we want to stop before the filter expression
            ' and associate the sequence point with whole Catch statement
            rewrittenFilter = New BoundSequencePointExpression(DirectCast(original.Syntax, CatchBlockSyntax).CatchStatement,
                                                               rewrittenFilter,
                                                               rewrittenFilter.Type)
 
            ' EnC: We need to insert a hidden sequence point to handle function remapping in case 
            ' the containing method is edited while methods invoked in the condition are being executed.
            Return AddConditionSequencePoint(rewrittenFilter, original, currentMethodOrLambda)
        End Function
 
        Public Overrides Function CreateSelectStatementPrologue(original As BoundSelectStatement) As BoundStatement
            ' Add select case begin sequence point
            Return New BoundSequencePoint(original.ExpressionStatement.Syntax, MyBase.CreateSelectStatementPrologue(original))
        End Function
 
        Public Overrides Function InstrumentSelectStatementCaseCondition(original As BoundSelectStatement, rewrittenCaseCondition As BoundExpression, currentMethodOrLambda As MethodSymbol, ByRef lazyConditionalBranchLocal As LocalSymbol) As BoundExpression
            Return AddConditionSequencePoint(MyBase.InstrumentSelectStatementCaseCondition(original, rewrittenCaseCondition, currentMethodOrLambda, lazyConditionalBranchLocal),
                                             original, currentMethodOrLambda, lazyConditionalBranchLocal)
        End Function
 
        Public Overrides Function InstrumentCaseBlockConditionalGoto(original As BoundCaseBlock, condGoto As BoundStatement) As BoundStatement
            Return New BoundSequencePoint(original.CaseStatement.Syntax, MyBase.InstrumentCaseBlockConditionalGoto(original, condGoto))
        End Function
 
        Public Overrides Function InstrumentCaseElseBlock(original As BoundCaseBlock, rewritten As BoundBlock) As BoundStatement
            Return New BoundSequencePoint(original.CaseStatement.Syntax, MyBase.InstrumentCaseElseBlock(original, rewritten))
        End Function
 
        Public Overrides Function InstrumentSelectStatementEpilogue(original As BoundSelectStatement, epilogueOpt As BoundStatement) As BoundStatement
            ' Add End Select sequence point
            Return New BoundSequencePoint(DirectCast(original.Syntax, SelectBlockSyntax).EndSelectStatement, MyBase.InstrumentSelectStatementEpilogue(original, epilogueOpt))
        End Function
 
        Public Overrides Function CreateCatchBlockPrologue(original As BoundCatchBlock) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, CatchBlockSyntax).CatchStatement, MyBase.CreateCatchBlockPrologue(original))
        End Function
 
        Public Overrides Function CreateFinallyBlockPrologue(original As BoundTryStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.FinallyBlockOpt.Syntax, FinallyBlockSyntax).FinallyStatement, MyBase.CreateFinallyBlockPrologue(original))
        End Function
 
        Public Overrides Function CreateTryBlockPrologue(original As BoundTryStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, TryBlockSyntax).TryStatement, MyBase.CreateTryBlockPrologue(original))
        End Function
 
        Public Overrides Function InstrumentTryStatement(original As BoundTryStatement, rewritten As BoundStatement) As BoundStatement
            ' Add a sequence point for End Try
            ' Note that scope the point is outside of Try/Catch/Finally 
            Return New BoundStatementList(original.Syntax,
                                          ImmutableArray.Create(Of BoundStatement)(
                                                   MyBase.InstrumentTryStatement(original, rewritten),
                                                   New BoundSequencePoint(DirectCast(original.Syntax, TryBlockSyntax).EndTryStatement, Nothing)
                                               )
                                           )
        End Function
 
        Public Overrides Function InstrumentFieldOrPropertyInitializer(original As BoundFieldOrPropertyInitializer, rewritten As BoundStatement, symbolIndex As Integer, createTemporary As Boolean) As BoundStatement
            rewritten = MyBase.InstrumentFieldOrPropertyInitializer(original, rewritten, symbolIndex, createTemporary)
 
            If createTemporary Then
                rewritten = MarkInitializerSequencePoint(rewritten, original.Syntax, symbolIndex)
            End If
 
            Return rewritten
        End Function
 
        Public Overrides Function InstrumentForEachLoopInitialization(original As BoundForEachStatement, initialization As BoundStatement) As BoundStatement
            ' first sequence point to highlight the for each statement
            Return New BoundSequencePoint(DirectCast(original.Syntax, ForEachBlockSyntax).ForEachStatement,
                                          MyBase.InstrumentForEachLoopInitialization(original, initialization))
        End Function
 
        Public Overrides Function InstrumentForEachLoopEpilogue(original As BoundForEachStatement, epilogueOpt As BoundStatement) As BoundStatement
            epilogueOpt = MyBase.InstrumentForEachLoopEpilogue(original, epilogueOpt)
            Dim nextStmt = DirectCast(original.Syntax, ForEachBlockSyntax).NextStatement
 
            If nextStmt IsNot Nothing Then
                epilogueOpt = New BoundSequencePoint(DirectCast(original.Syntax, ForEachBlockSyntax).NextStatement, epilogueOpt)
            End If
 
            Return epilogueOpt
        End Function
 
        Public Overrides Function InstrumentForLoopInitialization(original As BoundForToStatement, initialization As BoundStatement) As BoundStatement
            ' first sequence point to highlight the for statement
            Return New BoundSequencePoint(DirectCast(original.Syntax, ForBlockSyntax).ForStatement, MyBase.InstrumentForLoopInitialization(original, initialization))
        End Function
 
        Public Overrides Function InstrumentForLoopIncrement(original As BoundForToStatement, increment As BoundStatement) As BoundStatement
            increment = MyBase.InstrumentForLoopIncrement(original, increment)
            Dim nextStmt = DirectCast(original.Syntax, ForBlockSyntax).NextStatement
 
            If nextStmt IsNot Nothing Then
                increment = New BoundSequencePoint(DirectCast(original.Syntax, ForBlockSyntax).NextStatement, increment)
            End If
 
            Return increment
        End Function
 
        Public Overrides Function InstrumentLocalInitialization(original As BoundLocalDeclaration, rewritten As BoundStatement) As BoundStatement
            Return MarkInitializerSequencePoint(MyBase.InstrumentLocalInitialization(original, rewritten), original.Syntax)
        End Function
 
        Public Overrides Function CreateUsingStatementPrologue(original As BoundUsingStatement) As BoundStatement
            ' create a sequence point that contains the whole using statement as the first reachable sequence point
            ' of the using statement. The resource variables are not yet in scope.
            Return New BoundSequencePoint(original.UsingInfo.UsingStatementSyntax.UsingStatement, MyBase.CreateUsingStatementPrologue(original))
        End Function
 
        Public Overrides Function InstrumentUsingStatementResourceCapture(original As BoundUsingStatement, resourceIndex As Integer, rewritten As BoundStatement) As BoundStatement
            rewritten = MyBase.InstrumentUsingStatementResourceCapture(original, resourceIndex, rewritten)
 
            If Not original.ResourceList.IsDefault AndAlso original.ResourceList.Length > 1 Then
                ' Case "Using <variable declarations>"  
                Dim localDeclaration = original.ResourceList(resourceIndex)
                Dim syntaxForSequencePoint As SyntaxNode
 
                If localDeclaration.Kind = BoundKind.LocalDeclaration Then
                    syntaxForSequencePoint = localDeclaration.Syntax.Parent
                Else
                    Debug.Assert(localDeclaration.Kind = BoundKind.AsNewLocalDeclarations)
                    syntaxForSequencePoint = localDeclaration.Syntax
                End If
 
                rewritten = New BoundSequencePoint(syntaxForSequencePoint, rewritten)
            End If
 
            Return rewritten
        End Function
 
        Public Overrides Function CreateUsingStatementDisposePrologue(original As BoundUsingStatement) As BoundStatement
            ' The block should start with a sequence point that points to the "End Using" statement. This is required in order to
            ' highlight the end using when someone step next after the last statement of the original body and in case an exception
            ' was thrown.
            Return New BoundSequencePoint(DirectCast(original.Syntax, UsingBlockSyntax).EndUsingStatement, MyBase.CreateUsingStatementDisposePrologue(original))
        End Function
 
        Public Overrides Function CreateWithStatementPrologue(original As BoundWithStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, WithBlockSyntax).WithStatement, MyBase.CreateWithStatementPrologue(original))
        End Function
 
        Public Overrides Function CreateWithStatementEpilogue(original As BoundWithStatement) As BoundStatement
            Return New BoundSequencePoint(DirectCast(original.Syntax, WithBlockSyntax).EndWithStatement, MyBase.CreateWithStatementEpilogue(original))
        End Function
    End Class
 
End Namespace