File: CompileExpressionsTests.vb
Web Access
Project: ..\..\..\src\ExpressionEvaluator\VisualBasic\Test\ExpressionCompiler\Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.ExpressionCompiler.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 Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Roslyn.Test.Utilities
Imports Xunit
 
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
 
    Public Class CompileExpressionsTests
        Inherits ExpressionCompilerTestBase
 
        <Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems?id=482753")>
        Public Sub LocalsInAsync()
            Const source =
"Imports System
Imports System.Threading.Tasks
Class C
    Shared Function E(o As Object, p As Func(Of Object, Boolean)) As Task(Of Object)
        Throw New NotImplementedException()
    End Function
    Function F() As Object
        Throw New NotImplementedException()
    End Function
    Function G(o As Object) As Task(Of Object)
        Throw New NotImplementedException()
    End Function
    Async Function M(x As Object) As Task
        Dim z = Await E(F(), Function(y) x = y)
#ExternalSource(""Test"", 999)
        Await G(z)
#End ExternalSource
    End Function
End Class"
            ' Test with CompileExpression rather than CompileExpressions
            ' so field references in IL are named.
            ' Debug build.
            Dim comp = CreateCompilationWithMscorlib45AndVBRuntime(
                {VisualBasicSyntaxTree.ParseText(source)},
                options:=TestOptions.DebugDll,
                references:={SystemCoreRef})
            Dim testData As CompilationTestData
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "C.VB$StateMachine_4_M.MoveNext()", atLineNumber:=999)
                    Dim errorMessage As String = Nothing
                    testData = New CompilationTestData()
                    Dim result = context.CompileExpression("If(z, x)", errorMessage, testData)
                    Assert.NotNull(result.Assembly)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL(
"{
  // Code size       22 (0x16)
  .maxstack  2
  .locals init (Integer V_0,
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_1,
                C.VB$StateMachine_4_M V_2,
                Object V_3,
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_4,
                System.Exception V_5)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_4_M.$VB$ResumableLocal_z$1 As Object""
  IL_0006:  dup
  IL_0007:  brtrue.s   IL_0015
  IL_0009:  pop
  IL_000a:  ldarg.0
  IL_000b:  ldfld      ""C.VB$StateMachine_4_M.$VB$ResumableLocal_$VB$Closure_$0 As C._Closure$__4-0""
  IL_0010:  ldfld      ""C._Closure$__4-0.$VB$Local_x As Object""
  IL_0015:  ret
}")
                End Sub)
            ' Release build.
            comp = CreateCompilationWithMscorlib45AndVBRuntime(
                {VisualBasicSyntaxTree.ParseText(source)},
                options:=TestOptions.ReleaseDll,
                references:={SystemCoreRef})
            ' Note from MoveNext() below that local $VB$Closure_0 should not be
            ' used in the compiled expression to access the display class since that
            ' local is only set the first time through MoveNext() (see loc.1 below).
            testData = New CompilationTestData()
            comp.EmitToArray(testData:=testData)
            testData.GetMethodData("C.VB$StateMachine_4_M.MoveNext()").VerifyIL(
                "{
  // Code size      338 (0x152)
  .maxstack  3
  .locals init (Integer V_0,
                C._Closure$__4-0 V_1, //$VB$Closure_0
                Object V_2, //z
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_3,
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_4,
                System.Exception V_5)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C.VB$StateMachine_4_M.$State As Integer""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_0076
    IL_000a:  ldloc.0
    IL_000b:  ldc.i4.1
    IL_000c:  beq        IL_00e9
    IL_0011:  newobj     ""Sub C._Closure$__4-0..ctor()""
    IL_0016:  stloc.1
    IL_0017:  ldloc.1
    IL_0018:  ldarg.0
    IL_0019:  ldfld      ""C.VB$StateMachine_4_M.$VB$Local_x As Object""
    IL_001e:  stfld      ""C._Closure$__4-0.$VB$Local_x As Object""
    IL_0023:  ldarg.0
    IL_0024:  ldfld      ""C.VB$StateMachine_4_M.$VB$Me As C""
    IL_0029:  callvirt   ""Function C.F() As Object""
    IL_002e:  call       ""Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object""
    IL_0033:  ldloc.1
    IL_0034:  ldftn      ""Function C._Closure$__4-0._Lambda$__0(Object) As Boolean""
    IL_003a:  newobj     ""Sub System.Func(Of Object, Boolean)..ctor(Object, System.IntPtr)""
    IL_003f:  call       ""Function C.E(Object, System.Func(Of Object, Boolean)) As System.Threading.Tasks.Task(Of Object)""
    IL_0044:  callvirt   ""Function System.Threading.Tasks.Task(Of Object).GetAwaiter() As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0049:  stloc.3
    IL_004a:  ldloca.s   V_3
    IL_004c:  call       ""Function System.Runtime.CompilerServices.TaskAwaiter(Of Object).get_IsCompleted() As Boolean""
    IL_0051:  brtrue.s   IL_0092
    IL_0053:  ldarg.0
    IL_0054:  ldc.i4.0
    IL_0055:  dup
    IL_0056:  stloc.0
    IL_0057:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
    IL_005c:  ldarg.0
    IL_005d:  ldloc.3
    IL_005e:  stfld      ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0063:  ldarg.0
    IL_0064:  ldflda     ""C.VB$StateMachine_4_M.$Builder As System.Runtime.CompilerServices.AsyncTaskMethodBuilder""
    IL_0069:  ldloca.s   V_3
    IL_006b:  ldarg.0
    IL_006c:  call       ""Sub System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted(Of System.Runtime.CompilerServices.TaskAwaiter(Of Object), C.VB$StateMachine_4_M)(ByRef System.Runtime.CompilerServices.TaskAwaiter(Of Object), ByRef C.VB$StateMachine_4_M)""
    IL_0071:  leave      IL_0151
    IL_0076:  ldarg.0
    IL_0077:  ldc.i4.m1
    IL_0078:  dup
    IL_0079:  stloc.0
    IL_007a:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
    IL_007f:  ldarg.0
    IL_0080:  ldfld      ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0085:  stloc.3
    IL_0086:  ldarg.0
    IL_0087:  ldflda     ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_008c:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0092:  ldloca.s   V_3
    IL_0094:  call       ""Function System.Runtime.CompilerServices.TaskAwaiter(Of Object).GetResult() As Object""
    IL_0099:  ldloca.s   V_3
    IL_009b:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_00a1:  call       ""Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object""
    IL_00a6:  stloc.2
    IL_00a7:  ldarg.0
    IL_00a8:  ldfld      ""C.VB$StateMachine_4_M.$VB$Me As C""
    IL_00ad:  ldloc.2
    IL_00ae:  call       ""Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object""
    IL_00b3:  callvirt   ""Function C.G(Object) As System.Threading.Tasks.Task(Of Object)""
    IL_00b8:  callvirt   ""Function System.Threading.Tasks.Task(Of Object).GetAwaiter() As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_00bd:  stloc.s    V_4
    IL_00bf:  ldloca.s   V_4
    IL_00c1:  call       ""Function System.Runtime.CompilerServices.TaskAwaiter(Of Object).get_IsCompleted() As Boolean""
    IL_00c6:  brtrue.s   IL_0106
    IL_00c8:  ldarg.0
    IL_00c9:  ldc.i4.1
    IL_00ca:  dup
    IL_00cb:  stloc.0
    IL_00cc:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
    IL_00d1:  ldarg.0
    IL_00d2:  ldloc.s    V_4
    IL_00d4:  stfld      ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_00d9:  ldarg.0
    IL_00da:  ldflda     ""C.VB$StateMachine_4_M.$Builder As System.Runtime.CompilerServices.AsyncTaskMethodBuilder""
    IL_00df:  ldloca.s   V_4
    IL_00e1:  ldarg.0
    IL_00e2:  call       ""Sub System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted(Of System.Runtime.CompilerServices.TaskAwaiter(Of Object), C.VB$StateMachine_4_M)(ByRef System.Runtime.CompilerServices.TaskAwaiter(Of Object), ByRef C.VB$StateMachine_4_M)""
    IL_00e7:  leave.s    IL_0151
    IL_00e9:  ldarg.0
    IL_00ea:  ldc.i4.m1
    IL_00eb:  dup
    IL_00ec:  stloc.0
    IL_00ed:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
    IL_00f2:  ldarg.0
    IL_00f3:  ldfld      ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_00f8:  stloc.s    V_4
    IL_00fa:  ldarg.0
    IL_00fb:  ldflda     ""C.VB$StateMachine_4_M.$A0 As System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0100:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0106:  ldloca.s   V_4
    IL_0108:  call       ""Function System.Runtime.CompilerServices.TaskAwaiter(Of Object).GetResult() As Object""
    IL_010d:  pop
    IL_010e:  ldloca.s   V_4
    IL_0110:  initobj    ""System.Runtime.CompilerServices.TaskAwaiter(Of Object)""
    IL_0116:  leave.s    IL_013c
  }
  catch System.Exception
  {
    IL_0118:  dup
    IL_0119:  call       ""Sub Microsoft.VisualBasic.CompilerServices.ProjectData.SetProjectError(System.Exception)""
    IL_011e:  stloc.s    V_5
    IL_0120:  ldarg.0
    IL_0121:  ldc.i4.s   -2
    IL_0123:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
    IL_0128:  ldarg.0
    IL_0129:  ldflda     ""C.VB$StateMachine_4_M.$Builder As System.Runtime.CompilerServices.AsyncTaskMethodBuilder""
    IL_012e:  ldloc.s    V_5
    IL_0130:  call       ""Sub System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_0135:  call       ""Sub Microsoft.VisualBasic.CompilerServices.ProjectData.ClearProjectError()""
    IL_013a:  leave.s    IL_0151
  }
  IL_013c:  ldarg.0
  IL_013d:  ldc.i4.s   -2
  IL_013f:  dup
  IL_0140:  stloc.0
  IL_0141:  stfld      ""C.VB$StateMachine_4_M.$State As Integer""
  IL_0146:  ldarg.0
  IL_0147:  ldflda     ""C.VB$StateMachine_4_M.$Builder As System.Runtime.CompilerServices.AsyncTaskMethodBuilder""
  IL_014c:  call       ""Sub System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0151:  ret
}")
            WithRuntimeInstance(comp,
                Sub(runtime)
                    Dim context = CreateMethodContext(runtime, "C.VB$StateMachine_4_M.MoveNext()", atLineNumber:=999)
                    Dim errorMessage As String = Nothing
                    testData = New CompilationTestData()
                    Dim result = context.CompileExpression("If(z, x)", errorMessage, testData)
                    Assert.NotNull(result.Assembly)
                    Assert.Null(errorMessage)
                    testData.GetMethodData("<>x.<>m0").VerifyIL(
"{
  // Code size       12 (0xc)
  .maxstack  2
  .locals init (Integer V_0,
                C._Closure$__4-0 V_1, //$VB$Closure_0
                Object V_2, //z
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_3,
                System.Runtime.CompilerServices.TaskAwaiter(Of Object) V_4,
                System.Exception V_5)
  IL_0000:  ldloc.2
  IL_0001:  dup
  IL_0002:  brtrue.s   IL_000b
  IL_0004:  pop
  IL_0005:  ldarg.0
  IL_0006:  ldfld      ""C.VB$StateMachine_4_M.$VB$Local_x As Object""
  IL_000b:  ret
}")
                End Sub)
        End Sub
 
    End Class
 
End Namespace