File: IncrementalParser\IncrementalParser.vb
Web Access
Project: src\src\Compilers\VisualBasic\Test\Syntax\Microsoft.CodeAnalysis.VisualBasic.Syntax.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.Syntax.UnitTests)
' 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.ObjectModel
Imports System.Text
Imports System.Xml.Linq
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Roslyn.Test.Utilities
 
Public Class IncrementalParser
 
    Private ReadOnly _s As String = <![CDATA[
'-----------------------
'
'  Copyright (c)
'
'-----------------------

#const BLAH = true

Imports Roslyn.Compilers
Imports Roslyn.Compilers.Common
Imports Roslyn.Compilers.VisualBasic

Public Module ParseExprSemantics
    Dim text = SourceText.From("")
    Dim tree As SyntaxTree = Nothing

    #const x = 1
    ''' <summary>
    ''' This is just gibberish to test parser
    ''' </summary>
    ''' <param name="ITERS"> haha </param>
    ''' <remarks></remarks>
    Public Sub Run(ByVal ITERS As Long)
        Console.WriteLine()

#if BLAH       
        Console.WriteLine("==== Parsing file: " & "Sample_ExpressionSemantics.vb")
        Console.WriteLine("Iterations:" & ITERS)
#end if

        Dim str = IO.File.ReadAllText("Sample_ExpressionSemantics.vb")
        Dim lineNumber = 28335
        Dim root As SyntaxNode = Nothing

        dim s1 = sub () If True Then Console.WriteLine(1) :
        dim s2 = sub () If True Then Console.WriteLine(1) ::Console.WriteLine(1)::
        dim s3 = sub() If True Then Console.WriteLine(1) :::: Console.WriteLine(1)

        Dim sw = System.Diagnostics.Stopwatch.StartNew()
        For i As Integer = 0 To ITERS - 1
            tree = SyntaxTree.Parse(text, Nothing)
            root = tree.Root
            Console.Write(".")
            Dim highWater As Integer = Math.Max(highWater, System.GC.GetTotalMemory(False))
        Next

Dim grouped = From 
node 
In root.GetNodesWhile(root.FullSpan, Function() True)
                        Group By node.Kind Into Group, Count()
                        Order By Count Descending
                        Take 30

        Console.WriteLine("Quick token cache-hits: {0} ({1:G2}%)", Stats.quickReturnedToken, 100.0 * Stats.quickReturnedToken / Stats.quickAttempts)

    End Sub
End Module]]>.Value
 
    <Fact>
    Public Sub FakeEdits()
        Dim text As SourceText = SourceText.From(_s)
        Dim tree As SyntaxTree = Nothing
        Dim root As SyntaxNode = Nothing
        tree = VisualBasicSyntaxTree.ParseText(text)
        root = tree.GetRoot()
 
        Assert.Equal(False, root.ContainsDiagnostics)
 
        For i As Integer = 0 To text.Length - 11
            Dim span = New TextSpan(i, 10)
            text = text.WithChanges(New TextChange(span, text.ToString(span)))
 
            tree = tree.WithChangedText(text)
 
            Dim prevRoot = root
            root = tree.GetRoot()
 
            Assert.True(prevRoot.IsEquivalentTo(root))
        Next
    End Sub
 
    <Fact>
    Public Sub TypeAFile()
        Dim text As SourceText = SourceText.From("")
        Dim tree As SyntaxTree = Nothing
        tree = VisualBasicSyntaxTree.ParseText(text)
 
        Assert.Equal(False, tree.GetRoot().ContainsDiagnostics)
 
        For i As Integer = 0 To _s.Length - 1
            ' add next character in file 's' to text
            Dim newText = text.WithChanges(New TextChange(New TextSpan(text.Length, 0), _s.Substring(i, 1)))
            Dim newTree = tree.WithChangedText(newText)
            Dim tmpTree = VisualBasicSyntaxTree.ParseText(newText)
 
            VerifyEquivalent(newTree, tmpTree)
            text = newText
            tree = newTree
        Next
    End Sub
 
    <Fact>
    Public Sub Preprocessor()
        Dim oldText = SourceText.From(_s)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' commenting out the #const
        Dim pos = _s.IndexOf("#const", StringComparison.Ordinal)
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(pos, 0), "'"))
        Dim newTree = oldTree.WithChangedText(newText)
        Dim tmpTree = VisualBasicSyntaxTree.ParseText(newText)
 
        VerifyEquivalent(newTree, tmpTree)
 
        ' removes ' from the '#const
        Dim newString = newText.ToString()
        pos = newString.IndexOf("'#const", StringComparison.Ordinal)
        Dim anotherText = newText.WithChanges(New TextChange(New TextSpan(pos, 1), ""))
        newTree = newTree.WithChangedText(anotherText)
        tmpTree = VisualBasicSyntaxTree.ParseText(anotherText)
 
        VerifyEquivalent(newTree, tmpTree)
    End Sub
 
#Region "Regressions"
    <WorkItem(899264, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseWithEventsFollowingProperty()
        'Unable to verify this using CDATA, since CDATA value only has Cr appended at end of each line, 
        'where as this bug is reproducible only with CrLf at the end of each line
        Dim code As String = "Public Class HasPublicMembersToConflictWith" & vbCrLf &
    "Public ConflictWithProp" & vbCrLf &
    "" & vbCrLf &
    "Public Property _ConflictWithBF() As String" & vbCrLf &
    "    Get" & vbCrLf &
    "    End Get" & vbCrLf &
    "    Set(value As String)" & vbCrLf &
    "    End Set" & vbCrLf &
    "End Property" & vbCrLf &
    "" & vbCrLf &
    "Public WithEvents ConflictWithBoth As Ob"
 
        ParseAndVerify(code,
        <errors>
            <error id="30481"/>
        </errors>)
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "j",
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(899596, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseClassFollowingDocComments()
        Dim code As String = <![CDATA[Class VBQATestcase
    '''-----------------------------------------------------------------------------
    ''' <summary>
    '''Text
    ''' </summary>
    '''-----------------------------------------------------------------------------]]>.Value
 
        ParseAndVerify(code,
                       <errors>
                           <error id="30481"/>
                       </errors>)
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf & "Pub",
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(899918, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseDirInElse()
        Dim code As String = "Sub Sub1()" & vbCr &
"If true Then" & vbCr &
"goo("""")" & vbCr &
"Else" & vbCr & vbCr &
"#If Not ULTRAVIOLET Then" & vbCr
 
        ParseAndVerify(code,
                       <errors>
                           <error id="30012"/>
                           <error id="30081"/>
                           <error id="30026"/>
                       </errors>)
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "a",
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(899938, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseNamespaceFollowingEvent()
        Dim code As String = "Class cls1" & vbCrLf &
"Custom Event myevent As del" & vbCrLf &
"End Event" & vbCrLf &
"End Class" & vbCrLf &
"Namespace r"
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "e",
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(900209, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseCaseElse()
        Dim code As String = (<![CDATA[
      Sub main()
         Select Case 5
            Case Else
               vvv = 6
            Case Else
               vvv = 7
]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(901386, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseExplicitOnGroupBy()
        Dim code As String = (<![CDATA[
Option Explicit On
Sub goo()
Dim q2 = From x In col let y = x Group x, y By]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "a",
        .changeSpan = New TextSpan(code.Length, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(901639, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseExprLambdaInSubContext()
        Dim code As String = (<![CDATA[Function() NewTextPI.UnwrapObject().FileCodeModel)
If True Then
End If
End Sub
Class WillHaveAnError
End class
Class willBeReused
End class]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "(",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
 
    End Sub
 
    <Fact>
    Public Sub IncParseExprLambdaInSubContext2()
        Dim code As String = (<![CDATA[Function() NewTextPI.UnwrapObject().FileCodeModel)
If True Then
Else
End If
End Sub
Class WillHaveAnError
End class
Class willBeReused
End class]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "(",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
 
    End Sub
 
    <WorkItem(901645, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseExitFunction()
        Dim code As String = (<![CDATA[Function
If strSwitches <> "" Then strCLine = strCLine & " " & strSwitches
End Sub]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Exit ",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
 
    End Sub
 
    <WorkItem(901655, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseDateLiteral()
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = "",
        .changeText = "#10/18/1969# hello 123",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
 
    End Sub
 
    <Fact>
    Public Sub IncParsePPElse()
        Dim code As String = (<![CDATA[
Function goo() As Boolean

#Else

    Dim roleName As Object
    For Each roleName In wbirFields
    Next roleName


End Function
]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "#End If",
        .changeSpan = New TextSpan(code.IndexOf("Next roleName", StringComparison.Ordinal) + 15, 2),
        .changeType = ChangeType.Replace})
    End Sub
 
    <Fact>
    Public Sub IncParsePPElse1()
        Dim code As String = (<![CDATA[
Function goo() As Boolean

#Else

    Dim roleName As Object
    For Each roleName In wbirFields
    Next roleName

#End IF

End Function
]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "#If true " & vbCrLf,
        .changeSpan = New TextSpan(code.IndexOf("#Else", StringComparison.Ordinal), 0),
        .changeType = ChangeType.Replace})
    End Sub
 
    <WorkItem(901669, "DevDiv/Personal")>
    <Fact>
    Public Sub ParseXmlTagWithExprHole()
        Dim code As String = (<![CDATA[e a=<%= b %>>]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "<",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(901671, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseEndBeforeSubWithX()
        Dim code As String = (<![CDATA[Sub
        End Class
    X]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "End ",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(901676, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseInterfaceFollByConstructs()
        Dim code As String = (<![CDATA[
        Public Interface I2
        End Interface
        Sub SEHIllegal501()
            Try
            Catch
            End Try
            Exit Sub
        End Sub
    X]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Interface",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(901680, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseLCFunctionCompoundAsn()
        Dim code As String = (<![CDATA[Public Function goo() As String
            For i As Integer = 0 To  1
                total += y(i)
            Next
End Function]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "> _" & vbCrLf,
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(902710, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseInsertFunctionBeforeEndClass()
        Dim code As String = (<![CDATA[End Class
MustInherit Class C10
End Class]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Function" & vbCrLf,
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(903134, "DevDiv/Personal")>
    <Fact>
    Public Sub InsertSubBeforeCustomEvent()
        Dim code As String = (<![CDATA[            Custom Event e As del
                AddHandler(ByVal value As del)
                End AddHandler
            End Event]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Sub" & vbCrLf,
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(903555, "DevDiv/Personal")>
    <Fact>
    Public Sub ParseMergedForEachAndDecl()
        Dim code As String = (<![CDATA[#Region "abc"
Function goo() As Boolean
Dim roleName As Object
For Each roleName In wbirFields
Next roleName
End Function
#End Region]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(code.IndexOf("Dim roleName As Object", StringComparison.Ordinal) + 22, 2),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(903805, "DevDiv/Personal")>
    <Fact>
    Public Sub ParseEnumWithoutEnd()
        Dim code As String = (<![CDATA[Public Class Class2
    Protected Enum e
        e1
        e2
	End Enum
    Public Function Goo(ByVal arg1 As e) As e
    End Function
End Class]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(code.IndexOf("e2", StringComparison.Ordinal) + 2, 2),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(903826, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseWrongSelectFollByIf()
        Dim code As String = (<![CDATA[        Sub goo()
                Select Case lng
                    Case 44
                        int1 = 4
                End Select
                If true Then
                End If
        End Sub]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "End ",
        .changeSpan = New TextSpan(code.IndexOf("End ", StringComparison.Ordinal), 4),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(904768, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseDoLoop()
        Dim code As String = (<![CDATA[        Sub AnonTConStmnt()
                Do
                    i += 1
                Loop Until true
        End Sub
]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(code.IndexOf("Do", StringComparison.Ordinal) + 2, 2),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(904771, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseClassWithOpDecl()
        Dim code As String = (<![CDATA[
Friend Module m1
Class Class1
Shared Operator -(ByVal x As Class1) As Boolean
End Operator
End Class
End Module
]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Class ",
        .changeSpan = New TextSpan(code.IndexOf("Class ", StringComparison.Ordinal), 6),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(904782, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParsePropFollIncompleteLambda()
        Dim code As String = (<![CDATA[        Class c1

            Public Function goo() As Object
                Dim res = Function(x As Integer) c1.Goo(x)
            End Function

            Default Public Property Prop(ByVal y As String) As Integer
                Get
                End Get
                Set(ByVal value As Integer)
                End Set
            End Property
        End Class]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = ")",
        .changeSpan = New TextSpan(code.IndexOf("x As Integer)", StringComparison.Ordinal) + 12, 1),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(904792, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseErroneousGroupByQuery()
        Dim code As String = (<![CDATA[        Sub goo() 
                Dim q2 = From i In str Group i By key1 = x
                Dim q3 =From j In str Group By key = i 
        End Sub]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = " By",
        .changeSpan = New TextSpan(code.IndexOf(" By key1", StringComparison.Ordinal), 3),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(904804, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseSetAfterIncompleteSub()
        Dim code As String = (<![CDATA[Sub goo()
End Sub
Public WriteOnly Property bar() as short
Set
End Set
End Property]]>).Value
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(code.IndexOf("End Sub", StringComparison.Ordinal) + 7, 2),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(911100, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseEmbeddedIfsInsideCondCompile()
        Dim code As String = "Sub bar() " & vbCrLf &
"#If true Then" & vbCrLf &
    "if true Then goo()" & vbCrLf &
 "If Command() <" & vbCrLf
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = ">",
        .changeSpan = New TextSpan(code.IndexOf("If Command() <", StringComparison.Ordinal) + 14, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(911103, "DevDiv/Personal")>
    <Fact>
    Public Sub IncParseErrorIfStatement()
        Dim code As String = "Public Sub Run() " & vbCrLf &
"If NewTextPI.DTE Is Nothing Then End" & vbCrLf &
 "End Sub"
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "NewTextPI",
        .changeSpan = New TextSpan(code.IndexOf("NewTextPI.DTE", StringComparison.Ordinal), 9),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(537168, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537168")>
    <Fact>
    Public Sub IncParseSubBeforePartialClass()
        Dim code As String = (<![CDATA[End Class
Partial Class class3
End Class]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Sub" & vbCrLf,
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(537172, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537172")>
    <Fact>
    Public Sub IncParseInterfaceDeleteWithColon()
        Dim code As String = (<![CDATA[Interface I : Sub Goo() : End Interface]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "Interface ",
        .changeSpan = New TextSpan(0, 10),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(537174, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537174")>
    <Fact>
    Public Sub IncParseMissingEndAddHandler()
        Dim code As String = (<![CDATA[
                Class C
                    Custom Event e As del
                        AddHandler(ByVal value As del)
                        End AddHandler
                        RemoveHandler(ByVal value As del)
                        End RemoveHandler
                        RaiseEvent()
                        End RaiseEvent
                    End Event
                End Class
]]>).Value
        Dim change = "End AddHandler"
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = change,
        .changeSpan = New TextSpan(code.IndexOf(change, StringComparison.Ordinal), change.Length),
        .changeType = ChangeType.Remove})
    End Sub
 
    <WorkItem(539038, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539038")>
    <Fact>
    Public Sub IncParseInvalidText()
        Dim code As String = (<![CDATA[1. Verify that INT accepts an constant of each type as the
        '                  argument.]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = "os:    ",
        .changeSpan = New TextSpan(0, 0),
        .changeType = ChangeType.InsertBefore})
    End Sub
 
    <WorkItem(539053, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539053")>
    <Fact>
    Public Sub IncParseAddSubValid()
        Dim code As String = (<![CDATA[Class CGoo
    Public S()
        Dim x As Integer = 0
    End Sub
End Class]]>).Value
 
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(22, 0), " Sub "))
 
        Dim incTree = oldTree.WithChangedText(newText)
        Dim newTree = VisualBasicSyntaxTree.ParseText(newText)
 
        Dim exp1 = newTree.GetRoot().ChildNodesAndTokens()(0).ChildNodesAndTokens()(1)
        Dim inc1 = incTree.GetRoot().ChildNodesAndTokens()(0).ChildNodesAndTokens()(1)
        Assert.Equal(SyntaxKind.SubBlock, exp1.Kind())
        Assert.Equal(exp1.Kind(), inc1.Kind())
 
        Dim exp2 = exp1.ChildNodesAndTokens()(1)
        Dim inc2 = inc1.ChildNodesAndTokens()(1)
        Assert.Equal(SyntaxKind.LocalDeclarationStatement, exp2.Kind())
        Assert.Equal(exp2.Kind(), inc2.Kind())
 
        ' this XML output is too much
        'IncParseAndVerify(New IncParseNode With {
        '.oldText = code,
        '.changeText = " Sub ",
        '.changeSpan = New TextSpan(22, 0),
        '.changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(538577, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538577")>
    <Fact>
    Public Sub IncParseAddSpaceAfterForNext()
        Dim code As String = (<![CDATA[Module M
  Sub Main()
   Dim i(1) As Integer
   For i(0) = 1 To 10
     For j = 1 To 10
   Next j, i(0) 
  End Sub
End Module 
]]>).Value
 
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(103, 0), " "))
        Dim incTree = oldTree.WithChangedText(newText)
        Dim newTree = VisualBasicSyntaxTree.ParseText(newText)
 
        Assert.Equal(False, oldTree.GetRoot().ContainsDiagnostics)
        Assert.Equal(False, newTree.GetRoot().ContainsDiagnostics)
        Assert.Equal(False, incTree.GetRoot().ContainsDiagnostics)
        VerifyEquivalent(incTree, newTree)
    End Sub
 
    <Fact>
    <WorkItem(540667, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540667")>
    Public Sub IncrementalParseAddSpaceInSingleLineIf()
        ' The code below intentionally is missing a space between the "Then" and "Console"
        Dim code As String = (<![CDATA[
Module M
  Sub Main()
    If False ThenConsole.WriteLine("FIRST") : Console.WriteLine("TEST") Else Console.WriteLine("TRUE!") : 'comment
  End Sub
End Module 
]]>).Value
 
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim insertionPoint = code.IndexOf("Console", StringComparison.Ordinal)
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(insertionPoint, 0), " "))
        Dim expectedTree = VisualBasicSyntaxTree.ParseText(newText)
        Dim incrementalTree = oldTree.WithChangedText(newText)
 
        Assert.Equal(False, expectedTree.GetRoot().ContainsDiagnostics)
        Assert.Equal(False, incrementalTree.GetRoot().ContainsDiagnostics)
        VerifyEquivalent(incrementalTree, expectedTree)
    End Sub
 
    <Fact>
    <WorkItem(405887, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=405887")>
    Public Sub IncrementalParseInterpolationInSingleLineIf()
        Dim code As String = (<![CDATA[
Module Module1
    Sub Test1(val1 As Integer)
        If val1 = 1 Then System.Console.WriteLine($"abc '" & sServiceName & "'")
    End Sub
End Module
]]>).Value
 
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Const replace = """ &"
        Dim insertionPoint = code.IndexOf(replace, StringComparison.Ordinal)
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(insertionPoint, replace.Length), "{"))
        Dim expectedTree = VisualBasicSyntaxTree.ParseText(newText)
        Dim incrementalTree = oldTree.WithChangedText(newText)
 
        Assert.Equal(True, expectedTree.GetRoot().ContainsDiagnostics)
        Assert.Equal(True, incrementalTree.GetRoot().ContainsDiagnostics)
        VerifyEquivalent(incrementalTree, expectedTree)
    End Sub
#End Region
 
    <WorkItem(543489, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543489")>
    <Fact>
    Public Sub Bug11296()
 
        Dim source As String = <![CDATA[    
Module M
    Sub Main()
        GoTo 100
        Dim Flag1 = 1
        If Flag1 = 1 Then
            Flag1 = 100
        Else 100:
        End If
    End Sub
End Module
]]>.Value
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Assert.Equal(1, oldTree.GetDiagnostics().Count)
        Assert.Equal("Syntax error.", oldTree.GetDiagnostics()(0).GetMessage(EnsureEnglishUICulture.PreferredOrNull))
        Assert.Equal("[131..134)", oldTree.GetDiagnostics()(0).Location.SourceSpan.ToString)
 
        ' commenting out the goto
        Dim pos = source.IndexOf("GoTo 100", StringComparison.Ordinal)
        Dim newText = oldText.WithChanges(New TextChange(New TextSpan(pos, 0), "'"))
 
        Dim newTree = oldTree.WithChangedText(newText)
 
        Dim tmpTree = VisualBasicSyntaxTree.ParseText(newText)
        Assert.Equal(1, tmpTree.GetDiagnostics().Count)
        Assert.Equal("Syntax error.", tmpTree.GetDiagnostics()(0).GetMessage(EnsureEnglishUICulture.PreferredOrNull))
        Assert.Equal("[132..135)", tmpTree.GetDiagnostics()(0).Location.SourceSpan.ToString)
    End Sub
 
    <Fact>
    Public Sub IncParseTypeNewLine()
        Dim code As String = (<![CDATA[
Module m
Sub s
End Sub
End Module     
]]>).Value
 
        IncParseAndVerify(New IncParseNode With {
        .oldText = code,
        .changeText = vbCrLf,
        .changeSpan = New TextSpan(15, 0),
        .changeType = ChangeType.Insert})
    End Sub
 
    <WorkItem(545667, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545667")>
    <Fact>
    Public Sub Bug14266()
        Dim source = <![CDATA[
Enum E
    A
End Enum
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' Insert a single character at the beginning.
        Dim newText = oldText.Replace(start:=0, length:=0, newText:="B")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(546680, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546680")>
    <Fact>
    Public Sub Bug16533()
        Dim source = <![CDATA[
Module M
    Sub M()
        If True Then M() Else : 
    End Sub
End Module
]]>.Value
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Replace "True" with "True".
        Dim str = "True"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:=str)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, oldTree)
    End Sub
 
    <WorkItem(546685, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546685")>
    <Fact>
    Public Sub MultiLineIf()
        Dim source = <![CDATA[
Module M
    Sub M(b As Boolean)
        If b Then
        End If
    End Sub
End Module
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' Change "End Module" to "End module".
        Dim position = oldText.ToString().LastIndexOf("Module", StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=1, newText:="m")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' MultiLineIfBlock should not have been reused.
        Assert.True(diffs.Any(Function(n) n.IsKind(SyntaxKind.MultiLineIfBlock)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    ''' <summary>
    ''' Changes before a multi-line If should
    ''' not affect reuse of the If nodes.
    ''' </summary>
    <Fact>
    Public Sub MultiLineIf_2()
        Dim source = <![CDATA[
Module M
    Sub M()
        Dim b = False
        b = True
        If b Then
        End If
    End Sub
End Module
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' Change "False" to "True".
        Dim position = oldText.ToString().IndexOf("False", StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=5, newText:="True")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' MultiLineIfBlock should have been reused and should not appear in diffs.
        Assert.False(diffs.Any(Function(n) n.IsKind(SyntaxKind.MultiLineIfBlock)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    ''' <summary>
    ''' Changes sufficiently far after a multi-line If
    ''' should not affect reuse of the If nodes.
    ''' </summary>
    <Fact>
    Public Sub MultiLineIf_3()
        Dim source = <![CDATA[
Module M
    Sub M(b As Boolean)
        If b Then
        End If
        While b
        End While
    End Sub
End Module
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' Change "End Module" to "End module".
        Dim position = oldText.ToString().LastIndexOf("Module", StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=1, newText:="m")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' MultiLineIfBlock should have been reused and should not appear in diffs.
        Assert.False(diffs.Any(Function(n) n.IsKind(SyntaxKind.MultiLineIfBlock)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(546692, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546692")>
    <Fact>
    Public Sub Bug16575()
        Dim source = <![CDATA[
Module M
    Sub M()
        If True Then Else Dim x = 1 : Dim y = x
        If True Then Else Dim x = 1 : Dim y = x
    End Sub
End Module
]]>.Value
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Add newline after first single line If
        Dim str = "y = x"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal) + str.Length
        Dim newText = oldText.Replace(start:=position, length:=0, newText:=vbCrLf)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(546698, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546698")>
    <Fact>
    Public Sub Bug16596()
        Dim source = ToText(<![CDATA[
Module M
    Sub M()
        If True Then
            Dim x = Sub() If True Then Return : 'Else
        End If
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Uncomment "Else".
        Dim position = oldText.ToString().IndexOf("'Else", StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=1, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(530662, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530662")>
    <Fact>
    Public Sub Bug16662()
        Dim source = ToText(<![CDATA[
Module M
    Sub M()
        ''' <[
        1: X
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Remove "X".
        Dim position = oldText.ToString().IndexOf("X"c)
        Dim newText = oldText.Replace(start:=position, length:=1, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(546774, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546774")>
    <Fact>
    Public Sub Bug16786()
        Dim source = <![CDATA[
Namespace N
    ''' <summary/>
    Class A
    End Class
End Namespace
Class B
End Class
Class C
End Class
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        ' Append "Class".
        Dim position = oldText.ToString().Length
        Dim newText = oldText.Replace(start:=position, length:=0, newText:=vbCrLf & "Class")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' Original Namespace should have been reused.
        Assert.False(diffs.Any(Function(n) n.IsKind(SyntaxKind.NamespaceBlock)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(530841, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530841")>
    <Fact>
    Public Sub Bug17031()
        Dim source = ToText(<![CDATA[
Module M
    Sub M()
        If True Then
        Else

        End If
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Sub M()"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position + str.Length, length:=0, newText:=vbCrLf)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(531017, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531017")>
    <Fact>
    Public Sub Bug17409()
        Dim source = ToText(<![CDATA[
Module M
    Sub M()
        Dim ch As Char
        Dim ch As Char
        Select Case ch
            Case "~"c

            Case Else
        End Select
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Remove second instance of "Dim ch As Char".
        Const str = "Dim ch As Char"
        Dim position = oldText.ToString().LastIndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:=String.Empty)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact, WorkItem(547242, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547242")>
    Public Sub IncParseAddRemoveStopAtAofAs()
        Dim code As String = <![CDATA[
Module M
    Public obj0 As Object
    Public obj1 A]]>.Value
 
        Dim tree = VisualBasicSyntaxTree.ParseText(code)
        Dim oldIText = tree.GetText()
        ' Remove first N characters.
        Dim span = New TextSpan(0, code.IndexOf("j0", StringComparison.Ordinal))
        Dim change = New TextChange(span, "")
        Dim newIText = oldIText.WithChanges(change)
        Dim newTree = tree.WithChangedText(newIText)
        Dim fulltree = VisualBasicSyntaxTree.ParseText(newIText.ToString())
 
        Dim children1 = newTree.GetRoot().ChildNodesAndTokens()
        Dim children2 = fulltree.GetRoot().ChildNodesAndTokens()
        Assert.Equal(children2.Count, children1.Count)
    End Sub
 
    <Fact, WorkItem(547242, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547242")>
    Public Sub IncParseAddRemoveStopAtAofAs02()
        Dim code As String = <![CDATA[
Module M
    Sub M()
        Try
        Catch ex A]]>.Value
 
        Dim fullTree = VisualBasicSyntaxTree.ParseText(code)
        Dim fullText = fullTree.GetText()
        Dim newTree = fullTree.WithChangedText(fullText)
        Assert.NotSame(newTree, fullTree) ' Relies on #550027 where WithChangedText returns an instance with changes.
        Assert.Equal(fullTree.GetRoot().ToFullString(), newTree.GetRoot().ToFullString())
    End Sub
 
    <Fact, WorkItem(547251, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547251")>
    Public Sub IncParseAddRemoveStopAtAofPropAs()
        Dim code As String =
        <![CDATA[Class C
    Inherits Attribute
]]>.Value
        Dim code1 As String = <![CDATA[    Property goo() A]]>.Value
 
        Dim tree = VisualBasicSyntaxTree.ParseText(code)
        Dim oldIText = tree.GetText()
        ' insert code1 after code
        Dim span = New TextSpan(oldIText.Length, 0)
        Dim change = New TextChange(span, code1)
        Dim newIText = oldIText.WithChanges(change)
        Dim newTree = tree.WithChangedText(newIText)
 
        ' remove
        span = New TextSpan(0, code1.Length)
        change = New TextChange(span, "")
        newIText = newIText.WithChanges(change)
        ' InvalidCastException
        newTree = newTree.WithChangedText(newIText)
 
        Dim fulltree = VisualBasicSyntaxTree.ParseText(newIText.ToString())
        Assert.Equal(fulltree.GetRoot().ToFullString(), newTree.GetRoot().ToFullString())
 
    End Sub
 
    <Fact, WorkItem(547303, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547303")>
    Public Sub IncParseAddRemoveStopAtTofThen()
        Dim code As String = <![CDATA[
Module M
    Sub M()
        If True Then
        ElseIf False T]]>.Value
 
        Dim fullTree = VisualBasicSyntaxTree.ParseText(code)
        Dim fullText = fullTree.GetText()
        Dim newTree = fullTree.WithChangedText(fullText)
        Assert.NotSame(newTree, fullTree) ' Relies on #550027 where WithChangedText returns an instance with changes.
        Assert.Equal(fullTree.GetRoot().ToFullString(), newTree.GetRoot().ToFullString())
    End Sub
 
    <WorkItem(571105, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/571105")>
    <Fact()>
    Public Sub IncParseInsertLineBreakBeforeLambda()
        Dim code As String = <![CDATA[
Module M
    Sub F()
        Dim a1 = If(Sub()
                    End Sub, Nothing)
    End Sub
End Module]]>.Value
 
        Dim tree = VisualBasicSyntaxTree.ParseText(code)
        Dim oldText = tree.GetText()
        ' insert line break after '='
        Dim span = New TextSpan(code.IndexOf("="c), 0)
        Dim change = New TextChange(span, vbCrLf)
        Dim newText = oldText.WithChanges(change)
        Dim newTree = tree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(578279, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/578279")>
    <Fact()>
    Public Sub IncParseInsertLineBreakBetweenEndSub()
        Dim code As String = <![CDATA[Class C
    Sub M()
    En Sub
    Private F = 1
End Class]]>.Value
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' insert line break
        Dim position = code.IndexOf("En ", StringComparison.Ordinal)
        Dim change = New TextChange(New TextSpan(position, 2), "End" + vbCrLf)
        Dim newText = oldText.WithChanges(change)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact()>
    Public Sub InsertWithinLookAhead()
        Dim code As String = <![CDATA[
Module M
    Function F(s As String)
        Return From c In s
    End Function
End Module]]>.Value
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert "Select c" at end of method.
        Dim position = code.IndexOf("    End Function", StringComparison.Ordinal)
        Dim change = New TextChange(New TextSpan(position, 0), "               Select c" + vbCrLf)
        Dim newText = oldText.WithChanges(change)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
#Region "Async & Iterator"
    <Fact>
    Public Sub AsyncToSyncMethod()
        Dim source = ToText(<![CDATA[
Class C
    Async Function M(t As Task) As Task
        Await (t)
    End Function

    Function Await(t)
        Return Nothing
    End Function
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Async"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub AsyncToSyncLambda()
        Dim source = ToText(<![CDATA[
Class C
    Function M(t As Task)
        Dim lambda = Async Function() Await(t)
    End Function

    Function Await(t)
        Return Nothing
    End Function
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Async"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub SyncToAsyncMethod()
        Dim source = ToText(<![CDATA[
Class C
    Function M(t As Task) As Task
        Await (t)
    End Function

    Function Await(t)
        Return Nothing
    End Function
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Function "
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="Async Function ")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub SyncToAsyncLambda()
        Dim source = ToText(<![CDATA[
Class C
    Function M(t As Task)
        Dim lambda = Function() Await(t)
    End Function

    Function Await(t)
        Return Nothing
    End Function
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Function()"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="Async Function ")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub AsyncToSyncMethodDecl()
        Dim source = ToText(<![CDATA[
Class C
    Async Function M(a As Await, t As Task) As Task
        Await t
    End Function
End Class

Class Await
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Async"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub SyncToAsyncMethodDecl()
        Dim source = ToText(<![CDATA[
Class C
    Function M(a As Await, t As Task) As Task
        Await t
    End Function
End Class

Class Await
End Class
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Function "
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="Async Function ")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IteratorToNonIteratorMethod()
        Dim source = ToText(<![CDATA[
Module Program
    Iterator Function Goo() As IEnumerable
        Yield (1)
    End Function
End Module
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Iterator"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub NonIteratorToIteratorMethod()
        Dim source = ToText(<![CDATA[
Module Program
    Function Goo() As IEnumerable
        Yield (1)
    End Function
End Module
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Function "
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="Iterator Function ")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IteratorToNonIteratorMethodDecl()
        Dim source = ToText(<![CDATA[
Module Program
    Iterator Function Goo(Yield As Integer) As IEnumerable
        Yield (1)
    End Function
End Module
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Iterator"
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub NonIteratorToIteratorMethodDecl()
        Dim source = ToText(<![CDATA[
Module Program
    Function Goo(Yield As Integer) As IEnumerable
        Yield (1)
    End Function
End Module
]]>)
 
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Insert blank line at start of method.
        Dim str = "Function "
        Dim position = oldText.ToString().IndexOf(str, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=str.Length, newText:="Iterator Function ")
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
#End Region
 
    <WorkItem(554442, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/554442")>
    <Fact>
    Public Sub SplitCommentAtPreprocessorSymbol()
        Dim source = ToText(<![CDATA[
Module M
    Function F()
        ' comment # 1 and # 2
        ' comment
        ' comment
        Return Nothing
    End Function
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Split comment at "#".
        Dim position = oldText.ToString().IndexOf("#"c)
        Dim newText = oldText.Replace(start:=position, length:=0, newText:=vbCrLf)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(586698, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/586698")>
    <Fact>
    Public Sub SortUsings()
        Dim oldSource = ToText(<![CDATA[
Imports System.Linq
Imports System
Imports Microsoft.VisualBasic
Module Module1
    Sub Main()
    End Sub
End Module
]]>)
        Dim newSource = ToText(<![CDATA[
Imports System
Imports System.Linq
Imports Microsoft.VisualBasic
Module Module1
    Sub Main()
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(oldSource)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Changes:
        ' 1. "" => "System\r\nImports "
        ' 2. "System\r\nImports " => ""
        Dim newText = oldText.WithChanges(
            New TextChange(TextSpan.FromBounds(8, 8), "System" + vbCrLf + "Imports "),
            New TextChange(TextSpan.FromBounds(29, 45), ""))
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub Reformat()
        Dim oldSource = ToText(<![CDATA[
Class C
    Sub Method()
                                Dim i = 1
Select          Case            i               
                                            Case            1           ,           2           ,       3           
                                                    End             Select              
    End Sub
End Class
]]>)
        Dim newSource = ToText(<![CDATA[
Class C
    Sub Method()
        Dim i = 1
        Select Case i
            Case 1, 2, 3
        End Select
    End Sub
End Class
]]>)
        Dim oldText = SourceText.From(oldSource)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim startOfNew = newSource.IndexOf("Dim", StringComparison.Ordinal)
        Dim endOfNew = newSource.LastIndexOf("Select", StringComparison.Ordinal) + 6
        Dim startOfOld = startOfNew
        Dim endOfOld = oldSource.Length - newSource.Length + endOfNew
        Dim newText = oldText.Replace(TextSpan.FromBounds(startOfOld, endOfOld), newSource.Substring(startOfNew, endOfNew - startOfNew + 1))
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(604044, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/604044")>
    <Fact>
    Public Sub BunchALabels()
        Dim source = ToText(<![CDATA[
Module Program
    Sub Main()
&HF:
&HFF:
&HFFF:
&HFFFF:
&HFFFFF:
&HFFFFFF:
&HFFFFFFF:
&HFFFFFFFF:
&HFFFFFFFFF:
&HFFFFFFFFFF:
    End Sub
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Add enter after &HFFFFFFFFFF:.
        Dim position = oldText.ToString().IndexOf("&HFFFFFFFFFF:", StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position + "&HFFFFFFFFFF:".Length, length:=0, newText:=vbCrLf)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(625612, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/625612")>
    <Fact()>
    Public Sub LabelAfterColon()
        ' Label following another label on separate lines.
        LabelAfterColonCore(True, <![CDATA[Module M
            Sub M()
        10:
        20:
        30:
        40:
        50:
        60:
        70:
            End Sub
        End Module
        ]]>.Value)
        ' Label following another label on separate lines.
        LabelAfterColonCore(True, <![CDATA[Module M
            Sub M()
        10: : 
        20:
        30:
        40:
        50:
        60:
        70:
            End Sub
        End Module
        ]]>.Value)
        ' Label following on the same line as another label.
        LabelAfterColonCore(False, <![CDATA[Module M
    Sub M()
10: 20:
30:
40:
50:
60:
70:
    End Sub
End Module
]]>.Value)
        ' Label following on the same line as another label.
        LabelAfterColonCore(False, <![CDATA[Module M
    Sub M()
10: : 20:
30:
40:
50:
60:
70:
    End Sub
End Module
]]>.Value)
        ' Label following on the same line as another statement.
        LabelAfterColonCore(False, <![CDATA[Module M
    Sub M()
M() : 20:
30:
40:
50:
60:
70:
    End Sub
End Module
]]>.Value)
        ' Label following a colon within a single-line statement.
        LabelAfterColonCore(False, <![CDATA[Module M
    Sub M()
If True Then M() : 20:
30:
40:
50:
60:
70:
    End Sub
End Module
]]>.Value)
    End Sub
 
    Private Sub LabelAfterColonCore(valid As Boolean, code As String)
        Dim oldText = SourceText.From(code)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim diagnostics = oldTree.GetDiagnostics()
        Assert.Equal(valid, diagnostics.Count = 0)
        ' Replace "70".
        Dim position = code.IndexOf("70", StringComparison.Ordinal)
        Dim change = New TextChange(New TextSpan(position, 2), "71")
        Dim newText = oldText.WithChanges(change)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(529260, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529260")>
    <Fact()>
    Public Sub DoNotReuseAnnotatedNodes()
        Dim text As String = <![CDATA[
Class C
End Class
Class D
End Class
]]>.Value.Replace(vbCr, vbCrLf)
 
        ' NOTE: We're using the class statement, rather than the block, because the
        ' change region is expanded enough to impinge on the block.
        Dim extractGreenClassC As Func(Of SyntaxTree, Syntax.InternalSyntax.VisualBasicSyntaxNode) =
            Function(tree) DirectCast(tree.GetRoot().DescendantNodes().First(Function(n) n.IsKind(SyntaxKind.ClassStatement)), VisualBasicSyntaxNode).VbGreen
 
        ''''''''''
        ' Check reuse after a trivial change in an unannotated tree.
        ''''''''''
        Dim oldTree1 = VisualBasicSyntaxTree.ParseText(text)
        Dim newTree1 = oldTree1.WithInsertAt(text.Length, " ")
 
        ' Class declaration is reused.
        Assert.Same(extractGreenClassC(oldTree1), extractGreenClassC(newTree1))
 
        ''''''''''
        ' Check reuse after a trivial change in an annotated tree.
        ''''''''''
        Dim tempTree2 = VisualBasicSyntaxTree.ParseText(text)
        Dim tempRoot2 = tempTree2.GetRoot()
        Dim tempToken2 = tempRoot2.DescendantTokens().First(Function(t) t.Kind = SyntaxKind.IdentifierToken)
        Dim oldRoot2 = tempRoot2.ReplaceToken(tempToken2, tempToken2.WithAdditionalAnnotations(New SyntaxAnnotation()))
        Assert.True(oldRoot2.ContainsAnnotations, "Should contain annotations.")
        Assert.Equal(text, oldRoot2.ToFullString())
 
        Dim oldTree2 = VisualBasicSyntaxTree.Create(DirectCast(oldRoot2, VisualBasicSyntaxNode), DirectCast(tempTree2.Options, VisualBasicParseOptions), tempTree2.FilePath, Encoding.UTF8)
        Dim newTree2 = oldTree2.WithInsertAt(text.Length, " ")
 
        Dim oldClassC2 = extractGreenClassC(oldTree2)
        Dim newClassC2 = extractGreenClassC(newTree2)
 
        Assert.True(oldClassC2.ContainsAnnotations, "Should contain annotations")
        Assert.False(newClassC2.ContainsAnnotations, "Annotations should have been removed.")
 
        ' Class declaration is not reused...
        Assert.NotSame(oldClassC2, newClassC2)
        ' ...even though the text is the same.
        Assert.Equal(oldClassC2.ToFullString(), newClassC2.ToFullString())
 
        Dim oldToken2 = DirectCast(oldClassC2, Syntax.InternalSyntax.ClassStatementSyntax).Identifier
        Dim newToken2 = DirectCast(newClassC2, Syntax.InternalSyntax.ClassStatementSyntax).Identifier
 
        Assert.True(oldToken2.ContainsAnnotations, "Should contain annotations")
        Assert.False(newToken2.ContainsAnnotations, "Annotations should have been removed.")
 
        ' Token is not reused...
        Assert.NotSame(oldToken2, newToken2)
        ' ...even though the text is the same.
        Assert.Equal(oldToken2.ToFullString(), newToken2.ToFullString())
 
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_NamespaceBlock_TryLinkSyntaxMethodsBlock()
        'Sub Block
        'Function Block
        'Property Block
        Dim source = ToText(<![CDATA[
Namespace N
    Module M
        Function F() as Boolean
            Return True
        End Function    
        Sub M()
        End Sub
        Function Fn() as Boolean
            Return True
        End Function
        Property as Integer = 1
    End Module
End Namespace

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Module M"
        Dim TextToAdd As String = ""
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_ExecutableStatementBlock_TryLinkSyntaxClass()
        'Class Block         
        Dim source = ToText(<![CDATA[
Module M        
    Sub M()
    End Sub
    Dim x = Nothing

    Public Class C1        
    End Class

    Class C2        
    End Class
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Sub"
        Dim TextToAdd As String = ""
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_ExecutableStatementBlock_TryLinkSyntaxStructure()
        'Structure Block
        Dim source = ToText(<![CDATA[
Module M        
    Sub M()
    End Sub
    Dim x = Nothing

     Structure S2       1
        Dim i as integer
    End Structure

    Public Structure S2        
        Dim i as integer
    End Structure
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Sub"
        Dim TextToAdd As String = ""
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact()>
    Public Sub IncrementalParsing_ExecutableStatementBlock_TryLinkSyntaxOptionStatement()
        'Option Statement
        Dim source = ToText(<![CDATA[
Option Strict Off
Option Infer On
Option Explicit On

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Sub"
        Dim TextToAdd As String = "Module Module1" & Environment.NewLine & "Sub Goo()" & Environment.NewLine
        Dim position = 0
        Dim newText = oldText.Replace(start:=position, length:=1, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact()>
    Public Sub IncrementalParsing_ExecutableStatementBlock_TryLinkSyntaxImports()
        'Imports Statement
        Dim source = ToText(<![CDATA[
Imports System
Imports System.Collections
Imports Microsoft.Visualbasic
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Sub"
        Dim TextToAdd As String = "Module Module1" & Environment.NewLine & "Sub Goo()" & Environment.NewLine
        Dim position = 0
        Dim newText = oldText.Replace(start:=position, length:=1, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_ExecutableStatementBlock_TryLinkSyntaxDelegateSub()
        'ExecutableStatementBlock -> DelegateSub
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()

    End Sub
    Dim x = Nothing
    Delegate Sub Goo()
    Public Delegate Sub GooWithModifier()
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Sub"
        Dim TextToAdd As String = ""
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxOperatorBlock()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()
        Dim x As New SomeClass
        Dim y As Boolean = -x
    End Sub

    Class SomeClass
        Dim member As Long = 2
        Public Overloads Shared Operator -(ByVal value As SomeClass) As Boolean           
            If value.member Mod 5 = 0 Then                                
                Return True
            End If
            Return False
        End Operator
    End Class
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Class SomeClass"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxEventBlock()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()
        
    End Sub

    Class SomeClass
        Dim member As Long = 2
        Public Custom Event AnyName As EventHandler
            AddHandler(ByVal value As EventHandler)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            End RaiseEvent
        End Event
    End Class
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Class SomeClass"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxPropertyBlock()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()        
    End Sub
    Class SomeClass
        Dim member As Long = 2
        Public Property abc As Integer
            Set(value As Integer)

            End Set
            Get

            End Get
        End Property
    End Class
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim TextToRemove As String = "Class SomeClass"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxNamespaceModuleBlock()
        Dim source = ToText(<![CDATA[

Namespace NS1
    Module Module1
        Sub Goo()

        End Sub
        Dim x
    End Module 'Remove
    Namespace vs

    End Namespace
    Module Module1
    
        Dim x
    End Module
End Namespace
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim TextToRemove As String = "End Module 'Remove"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxNamespaceNamespaceBlock()
        Dim source = ToText(<![CDATA[

Namespace NS1
    Module Module1
        Sub Goo()

        End Sub
        Dim x
    End Module 'Remove
    Namespace vs
        Namespace vs2

        End Namespace
    End Namespace
    Namespace vs3

    End Namespace
End Namespace
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim TextToRemove As String = "End Module 'Remove"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_DeclarationContextBlock_TryLinkSyntaxItems()
        Dim source = ToText(<![CDATA[
    Class SomeClass
        Dim member As Long = 2
        Sub abc() 'Remove
            Dim xyz as integer = 2
            IF member = 1 then Console.writeline("TEST");
            Dim SingleLineDeclare as integer = 2
        End Sub

        Dim member2 As Long = 2
        Dim member3 As Long = 2

        Enum EnumItem 
                Item1
        End Enum
    End Class
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim TextToRemove As String = "Sub abc() 'Remove"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_PropertyContextBlock_TryLinkSyntaxSetAccessor()
        'PropertyContextBlock -> SetAccessor 
        Dim source = ToText(<![CDATA[
Class C
    Private _p As Integer = 0

    Property p2 As Integer
        Set(value As Integer)

        End Set
        Get

        End Get
    End Property

    Private _d As Integer = 1
End Class

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Property"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_BlockContext_TryLinkSyntaxSelectBlock()
        Dim source = ToText(<![CDATA[
Module Module1
    Private _p As Integer = 0
    Sub Bar()

    End Sub

    Function Goo(i As Integer) As Integer
        Dim y As Integer = i
        Select Case y
            Case 1
            Case 2, 3
            Case Else
        End Select

        Return y + 1

        Try
        Catch ex As exception
        End Try

        If y = 1 Then Console.WriteLine("Test")
        Y = 1

        While y <= 10
            y = y + 1
        End While

        Using f As New Goo
        End Using

        Dim Obj_C As New OtherClass
        With Obj_C

        End With

        SyncLock Obj_C

        End SyncLock

        Select Case y
            Case 10
            Case Else
        End Select

        y = 0
        Do
            y = y + 1
            If y >= 3 Then Exit Do
        Loop

        y = 0
        Do While y < 4
            y = y + 1
        Loop

        y = 0
        Do Until y > 5
            y = y + 1
        Loop
    End Function
End Module

Class Goo
    Implements IDisposable

#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls
    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
            End If
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region
End Class

Class OtherClass

End Class
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Select"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_EventBlockContext_TryLinkSyntax1()
        Dim source = ToText(<![CDATA[
Module Module1
    Public Custom Event AnyName As EventHandler
        AddHandler(ByVal value As EventHandler)
            _P = 1
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            _P = 2
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            _P = 3
        End RaiseEvent
    End Event
    Private _p As Integer = 0
    Sub Main()
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "RemoveHandler(ByVal value As EventHandler)"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_EventBlockContext_TryLinkSyntax2()
        Dim source = ToText(<![CDATA[
Module Module1
    Public Custom Event AnyName As EventHandler
        AddHandler(ByVal value As EventHandler)
            _P = 1
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            _P = 2          
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            _P = 3
            _P = _P +1
        End RaiseEvent
    End Event
    Private _p As Integer = 0
    Sub Main()
    End Sub
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "_P = 3"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_InterfaceBlockContext_TryLinkSyntaxClass()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()
    End Sub
    Interface IGoo
    End Interface
    Dim _p
    Class C
    End Class
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Interface"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_InterfaceBlockContext_TryLinkSyntaxEnum()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Main()

    End Sub
    Interface IGoo

    End Interface

    Dim _p

    Public Enum TestEnum
        Item
    End Enum
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "End Interface"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_CaseBlockContext_TryLinkSyntaxCase()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Goo()
        Dim i As Integer
        Dim y As Integer
        Select Case i
            Case 1
                _p = 1
            Case 2, 3
                _p = 2
            Case Else
                _p = 3                
        End Select
    End Sub
    Private _p As Integer = 0
    Sub Main()

    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Case 2, 3"
        Dim TextToAdd As String = ""
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_CatchContext_TryLinkSyntaxCatch()
        Dim source = ToText(<![CDATA[
Module Module1
    Sub Goo()
        Dim x1 As Integer = 1
        Try
            x1 = 2
        Catch ex As NullReferenceException
            Dim z = 1
        Catch ex As ArgumentException 'Remove
            Dim z = 1
        Catch ex As Exception
            _p = 3
            Dim s = Bar()
        Finally
            _p = 4
        End Try
    End Sub
    Private _p As Integer = 0
    Function Bar() As String
    End Function
End Module

]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Catch ex As ArgumentException 'Remove"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact()>
    Public Sub IncrementalParsing_NamespaceBlockContext_TryLinkSyntaxModule()
        Dim source = ToText(<![CDATA[
Namespace NS1
Module ModuleTemp 'Remove
End Module
Module Module1 'Remove
    Sub Goo()
        Dim x1 As Integer = 1                
    End Sub
    Private _p As Integer = 0
    Function Bar() As String
    End Function
End Module
End Namespace
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "Module ModuleTemp 'Remove"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <Fact>
    Public Sub IncrementalParsing_IfBlockContext_TryLinkSyntax()
        Dim source = ToText(<![CDATA[

Module Module1
    Private _p As Integer = 0

    Sub Goo()
        If x = 1 Then                
            _p=1
        elseIf x = 2 Then                
            _p=2
        elseIf x = 3 Then                
            _p=3
        else 
            If y = 1 Then            
                _p=2
            End If 
        End If 
    End Sub
End Module
]]>)
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
 
        Dim TextToRemove As String = "elseIf x = 2 Then"
        Dim TextToAdd As String = ""
 
        Dim position = oldText.ToString.IndexOf(TextToRemove, StringComparison.Ordinal)
        Dim newText = oldText.Replace(start:=position, length:=TextToRemove.Length, newText:=TextToAdd)
        Dim newTree = oldTree.WithChangedText(newText)
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(719787, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/719787")>
    <Fact()>
    Public Sub Bug719787_EOF()
        Dim source = <![CDATA[
Namespace N
    Class C
        Property P As Integer
    End Class
    Structure S
        Private F As Object
    End Structure
End Namespace
]]>.Value.Trim()
        ' Add two line breaks at end.
        source += vbCrLf
        Dim position = source.Length
        source += vbCrLf
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        ' Add "Delegate" to end of file between line breaks.
        Dim newText = oldText.Replace(start:=position, length:=0, newText:="Delegate")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' Most of the Namespace should have been reused.
        Assert.False(diffs.Any(Function(n) n.IsKind(SyntaxKind.StructureStatement)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
    <WorkItem(719787, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/719787")>
    <Fact>
    Public Sub Bug719787_MultiLineIf()
        Dim source = <![CDATA[
Class C
    Sub M()
        If e1 Then
            If e2 Then
                M11()
            Else
                M12()
            End If
        ElseIf e2 Then 
            If e2 Then
                M21()
            Else
                M22()
            End If
        ElseIf e3 Then 
            If e2 Then
                M31()
            Else
                M32()
            End If
        ElseIf e4 Then 
            If e2 Then
                M41()
            Else
                M42()
            End If
        Else 
            If e2 Then
                M51()
            Else
                M52()
            End If
        End If
    End Sub
    ' Comment
End Class
]]>.Value.Trim()
        Dim oldText = SourceText.From(source)
        Dim oldTree = VisualBasicSyntaxTree.ParseText(oldText)
        Dim toReplace = "' Comment"
        Dim position = source.IndexOf(toReplace, StringComparison.Ordinal)
        ' Replace "' Comment" with "Property"
        Dim newText = oldText.Replace(start:=position, length:=toReplace.Length, newText:="Property")
        Dim newTree = oldTree.WithChangedText(newText)
        Dim diffs = SyntaxDifferences.GetRebuiltNodes(oldTree, newTree)
        ' The ElseIfBlocks should have been reused.
        Assert.False(diffs.Any(Function(n) n.IsKind(SyntaxKind.ElseIfBlock)))
        VerifyEquivalent(newTree, VisualBasicSyntaxTree.ParseText(newText))
    End Sub
 
#Region "Helpers"
 
    Private Shared Function GetTokens(root As SyntaxNode) As InternalSyntax.VisualBasicSyntaxNode()
        Return root.DescendantTokens().Select(Function(t) DirectCast(t.Node, InternalSyntax.VisualBasicSyntaxNode)).ToArray()
    End Function
 
    Private Shared Sub VerifyTokensEquivalent(rootA As SyntaxNode, rootB As SyntaxNode)
        Dim tokensA = GetTokens(rootA)
        Dim tokensB = GetTokens(rootB)
        Assert.Equal(tokensA.Count, tokensB.Count)
 
        For i = 0 To tokensA.Count - 1
            Dim tokenA = tokensA(i)
            Dim tokenB = tokensB(i)
            Assert.Equal(tokenA.Kind, tokenB.Kind)
            Assert.Equal(tokenA.ToFullString(), tokenB.ToFullString())
        Next
    End Sub
 
    Private Shared Sub VerifyEquivalent(treeA As SyntaxTree, treeB As SyntaxTree)
        Dim rootA = treeA.GetRoot()
        Dim rootB = treeB.GetRoot()
 
        VerifyTokensEquivalent(rootA, rootB)
 
        Dim diagnosticsA = treeA.GetDiagnostics()
        Dim diagnosticsB = treeB.GetDiagnostics()
 
        Assert.True(rootA.IsEquivalentTo(rootB))
        Assert.Equal(diagnosticsA.Count, diagnosticsB.Count)
 
        For i = 0 To diagnosticsA.Count - 1
            Assert.Equal(diagnosticsA(i).Inspect(), diagnosticsB(i).Inspect())
        Next
    End Sub
 
    Private Shared Function ToText(code As XCData) As String
        Dim str = code.Value.Trim()
        ' Normalize line terminators.
        Dim builder = ArrayBuilder(Of Char).GetInstance()
        For i = 0 To str.Length - 1
            Dim c = str(i)
            If (c = vbLf(0)) AndAlso
                ((i = str.Length - 1) OrElse (str(i + 1) <> vbCr(0))) Then
                builder.AddRange(vbCrLf)
            Else
                builder.Add(c)
            End If
        Next
        Return New String(builder.ToArrayAndFree())
    End Function
#End Region
 
End Class