|
' 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.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
Imports VB = Microsoft.CodeAnalysis.VisualBasic
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Public Class IFOperatorTest
Inherits BasicTestBase
' Every argument could not be empty
<Fact>
Public Sub ArgumentCouldNotEmpty()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ArgumentCouldNotEmpty">
<file name="a.vb">
Option Infer Off
Module Program
Sub Main(args As String())
Dim X = 1
Dim Y = 1
Dim S = If(True, , Y = Y + 1)
S = If(True, X = X + 1, )
S = If(, X = X + 1, Y = Y + 1)
S = If(True)
S = If()
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, "Object")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", Nothing, "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="Y", ReadOutsideSymbol:="X, Y", WrittenInsideSymbol:="",
WrittenOutsideSymbol:="args, S, X, Y", AlwaysAssignedSymbol:="", DataFlowsInSymbol:="",
DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Object", Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", Nothing)
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="X", ReadOutsideSymbol:="X, Y", WrittenInsideSymbol:="",
WrittenOutsideSymbol:="args, S, X, Y", AlwaysAssignedSymbol:="", DataFlowsInSymbol:="X",
DataFlowsOutSymbol:="", index:=2)
'3
semanticInfos = GetSemanticInfos(compilation1, 3)
SemanticInfoTypeTest(semanticInfos, Nothing, "Object", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, Nothing, "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 3)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="X, Y", ReadOutsideSymbol:="X, Y", WrittenInsideSymbol:="",
WrittenOutsideSymbol:="args, S, X, Y", AlwaysAssignedSymbol:="", DataFlowsInSymbol:="X, Y",
DataFlowsOutSymbol:="", index:=3)
'4
semanticInfos = GetSemanticInfos(compilation1, 4)
Assert.Null(semanticInfos)
'5
semanticInfos = GetSemanticInfos(compilation1, 5)
Assert.Null(semanticInfos)
End Sub
' Can't declare variable in argument
<Fact>
Public Sub DeclVarInArgument()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="DeclVarInArgument">
<file name="a.vb">
Option Infer Off
Module Program
Sub Main(args As String())
Dim X = 1
Dim Y = 1
Dim S1 = If(Dim B = True, X = X + 1, Y = Y + 1)
Dim S2 = If(True,dim x1 = 2,dim y1 =3)
Dim S3 = If(True, X = 2,dim y1 = 3)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, Nothing, "Object", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, Nothing, "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="X, Y", ReadOutsideSymbol:="X",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, S1, S2, S3, X, Y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="X, Y", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="X, Y",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, S1, S2, S3, X, Y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="", index:=2)
'3
semanticInfos = GetSemanticInfos(compilation1, 3)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Object", Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", Nothing)
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 3)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="X", ReadOutsideSymbol:="X, Y",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, S1, S2, S3, X, Y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="X", DataFlowsOutSymbol:="", index:=3)
End Sub
' Conditional operator could not as statement
<Fact>
Public Sub ConditionalOperatorAsStatement()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ConditionalOperatorAsStatement">
<file name="a.vb">
Module Program
Sub Main(args As String())
Dim X = 1
Dim y = 1
If (1 > 2,x = x + 1,Y = Y+1) 'invalid
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
Assert.Null(semanticInfos)
End Sub
' Conditional operator as parameter
<Fact>
Public Sub ConditionalOperatorAsParameter()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ConditionalOperatorAsParameter">
<file name="a.vb">
Option Infer Off
Module Program
Sub Main(args As String())
Dim a0 As Boolean = False
Dim a1 As Integer = 0
Dim a2 As Long = 1
Dim b0 = a0
Dim b1 = a1
Dim b2 = a2
Console.WriteLine((If(b0, b1, b2)) <> (If(a0, a1, a2)))
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Object", "Object", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingValue, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="b0, b1, b2", ReadOutsideSymbol:="a0, a1, a2",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="a0, a1, a2, args, b0, b1, b2",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="b0, b1, b2", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "Long")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Long", "Long")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningNumeric, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="a0, a1, a2", ReadOutsideSymbol:="a0, a1, a2, b0, b1, b2",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="a0, a1, a2, args, b0, b1, b2",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="a0, a1, a2", DataFlowsOutSymbol:="", index:=2)
End Sub
' 'Goto' is Invalid in expression
<Fact>
Public Sub GotoInConditionalOperator()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="GotoInConditionalOperator">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim s = If(True, GoTo lab1, GoTo lab2)
lab1:
s = 1
lab2:
s = 2
Dim s1 = If(True, return, return)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, s1",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, s1",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="", index:=2)
End Sub
' Function call in return expression
<Fact>
Public Sub FunctionCallAsArgument()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation>
<file name="a.vb">
imports System
Module Program
Sub Main(args As String())
Dim x = If(True, Console.WriteLine(0), Console.WriteLine(1))
Dim y = If(True, fun_void(), fun_int(1))
Dim z = If(True, fun_Exception(1), fun_int(1))
Dim r = If(True, fun_long(0), fun_int(1))
Dim s = If(False, fun_long(0), fun_int(1))
End Sub
Private Sub fun_void()
Return
End Sub
Private Function fun_int(x As Integer) As Integer
Return x
End Function
Private Function fun_long(x As Integer) As Long
Return CLng(x)
End Function
Private Function fun_Exception(x As Integer) As Exception
Return New Exception()
End Function
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Void", "Void")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(2).ImplicitConversion.Kind)
'ClassfiConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, r, s, x, y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Void", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
'ClassfiConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, r, s, x, y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="",
DataFlowsOutSymbol:="", index:=2)
'3
semanticInfos = GetSemanticInfos(compilation1, 3)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Exception", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 3)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, r, s, x, y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="",
DataFlowsOutSymbol:="", index:=3)
'4
semanticInfos = GetSemanticInfos(compilation1, 4)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Long", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Long", "Long")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningNumeric, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 4)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, r, s, x, y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="",
DataFlowsOutSymbol:="", index:=4)
'5
semanticInfos = GetSemanticInfos(compilation1, 5)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Long", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Long", "Long")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningNumeric, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 5)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, r, s, x, y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="",
DataFlowsOutSymbol:="", index:=5)
End Sub
' Query works in return argument
<Fact>
Public Sub QueryAsArgument()
Dim compilation1 = CreateCompilationWithMscorlib40AndReferences(
<compilation name="QueryAsArgument">
<file name="a.vb">
Option Infer On
Imports System.Linq
Module Program
Sub Main(args As String())
Dim arr As String() = New String() {"aaa", "bbb", "ccc"}
Dim arr_int As Integer() = New Integer() {111, 222, 333}
Dim s = If(True, (From x In arr Select x).ToList(), From y As Integer In arr_int Select y)
End Sub
End Module
</file>
</compilation>, {SystemCoreRef})
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Collections.Generic.List(Of String)", "System.Collections.Generic.IEnumerable(Of Integer)")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="arr, arr_int, x, y", ReadOutsideSymbol:="",
WrittenInsideSymbol:="x, x, y, y", WrittenOutsideSymbol:="args, arr, arr_int, s",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="arr, arr_int", DataFlowsOutSymbol:="", variablesDeclared:="x, x, y, y")
End Sub
' Lambda works in return argument
<WorkItem(528700, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528700")>
<Fact>
Public Sub LambdaAsArgument()
Dim compilation1 = CreateCompilationWithMscorlib40AndReferences(
<compilation name="QueryAsArgument">
<file name="a.vb">
Option Infer On
Option Strict On
Imports System
Module Program
Sub Main(args As String())
Dim Y = 2
Dim S = If(True, DirectCast(Function(z As Integer) As Integer
System.Console.WriteLine("SUB")
Return z * z
End Function, Func(Of Integer, Integer)), Y + 1)
S = If(False, _
Sub(Z As Integer)
System.Console.WriteLine("SUB")
End Sub, Y + 1)
System.Console.WriteLine(S)
End Sub
End Module
</file>
</compilation>, {SystemCoreRef})
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Func(Of Integer, Integer)", "Integer")
'SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference Or ConversionKind.DelegateRelaxationLevelWideningToNonLambda, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, variablesDeclared:="z", ReadInsideSymbol:="Y, z", ReadOutsideSymbol:="S, Y",
WrittenInsideSymbol:="z", WrittenOutsideSymbol:="args, S, Y, Z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference Or ConversionKind.DelegateRelaxationLevelWideningToNonLambda, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, variablesDeclared:="Z", ReadInsideSymbol:="Y", ReadOutsideSymbol:="S, Y, z",
WrittenInsideSymbol:="Z", WrittenOutsideSymbol:="args, S, Y, z",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="", index:=2)
End Sub
' Conflict variable name declare in IF
<Fact>
Public Sub VariableNameConflict_1()
Dim compilation1 = CreateCompilationWithMscorlib40AndReferences(
<compilation name="VariableNameConflict">
<file name="a.vb">
Option Infer On
Imports System.Linq
Imports System
Module Program
Sub Main(args As String())
Dim arr As String() = New String() {"aaa", "bbb", "ccc"}
Dim arr_int As Integer() = New Integer() {111, 222, 333}
Dim x = 1
Dim s = If(True, (From x In arr Select x).ToList(), From y As Integer In arr_int Select y)
End Sub
End Module
</file>
</compilation>, {SystemCoreRef})
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Collections.Generic.List(Of String)", "System.Collections.Generic.IEnumerable(Of Integer)")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="arr, arr_int, x, y", ReadOutsideSymbol:="",
WrittenInsideSymbol:="x, x, y, y", WrittenOutsideSymbol:="args, arr, arr_int, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="arr, arr_int", DataFlowsOutSymbol:="", variablesDeclared:="x, x, y, y")
End Sub
' Conflict variable name declare in IF
<WorkItem(528700, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528700")>
<Fact>
Public Sub VariableNameConflict_2()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="VariableNameConflict">
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim X = 1
Dim Y = 1
Dim S = If(True, DirectCast(Function(x As Integer) As Integer
Return 0
End Function, Func(Of Integer, Integer)), Y = Y + 1)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Func(Of Integer, Integer)", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference Or ConversionKind.DelegateRelaxationLevelWideningToNonLambda, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, variablesDeclared:="x", ReadInsideSymbol:="Y", ReadOutsideSymbol:="",
WrittenInsideSymbol:="x", WrittenOutsideSymbol:="args, S, X, Y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Object initializer's in a ternary expression
<Fact>
Public Sub ObjInit()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ObjInit">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim f1 As New Goo(), f2 As New Goo(), f3 As New Goo()
Dim b As Boolean = True
f3 = If(b, f1 = New Goo(), f2 = New Goo())
b = False
f3 = If(b, f1 = New Goo(), f2 = New Goo())
End Sub
End Module
Class Goo
Public i As Integer
End Class
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "?", "?")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="b, f1, f2", ReadOutsideSymbol:="b, f1, f2",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, b, f1, f2, f3",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="b, f1, f2", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "?", "?")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="b, f1, f2", ReadOutsideSymbol:="b, f1, f2",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, b, f1, f2, f3",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="b, f1, f2", DataFlowsOutSymbol:="", index:=2)
End Sub
' Multiple conditional operator in expression
<Fact>
Public Sub MultipleConditional()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="MultipleConditional">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim S = If(False, 1, If(True, 2, 3))
Console.Write(S)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="S",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, S",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="S",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, S",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Arguments are of types: bool, constant, enum
<Fact>
Public Sub EnumAsArguments()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="EnumAsArguments">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim testResult = If(True, 0, color.Blue)
Console.WriteLine(testResult)
testResult = If(True, 5, color.Blue)
Console.WriteLine(testResult)
End Sub
End Module
Enum color
Red
Green
Blue
End Enum
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "color")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Numeric Or ConversionKind.Widening Or ConversionKind.InvolvesEnumTypeConversions, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="testResult",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, testResult",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "color")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Numeric Or ConversionKind.Widening Or ConversionKind.InvolvesEnumTypeConversions, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="testResult",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, testResult",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Arguments are of types: bool, IEnumerable<int> and int[]
<Fact()>
Public Sub IEnumerableAsArguments()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="IEnumerableAsArguments">
<file name="a.vb">
Imports System
Imports System.Linq
Module Program
Sub Main(args As String())
Dim testResult = If(True, Enumerable.Empty(Of Integer)(), {1})
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "?", Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer()", "Integer()")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(Nothing, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Widening, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, testResult",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Implicit conversion between Enum and null
<WorkItem(542116, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542116")>
<Fact()>
Public Sub ImplicitConversion()
Dim compilationDef =
<compilation name="ImplicitConversion">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim x = goo(0)
System.Console.WriteLine(x)
'Blue
Dim y = goo(1)
System.Console.WriteLine(y)
'Red
End Sub
Private Function goo(x As color) As color
Dim dd = Function()
Return If((x = color.Red), color.Blue, Nothing)
End Function
Return (dd())
End Function
End Module
Enum color
Red
Green
Blue
End Enum
</file>
</compilation>
Dim verifier = CompileAndVerify(compilationDef,
expectedOutput:=
<![CDATA[
2
0
]]>)
Dim compilation1 = DirectCast(verifier.Compilation, VisualBasicCompilation)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "color", Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "color", "color")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningNothingLiteral, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="dd",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="dd, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Implicit type conversion on conditional
<Fact>
Public Sub ImplicitConversionForConditional()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ImplicitConversionForConditional">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim valueFromDatabase As Object
Dim result As Decimal
valueFromDatabase = DBNull.Value
result = CDec(If(valueFromDatabase IsNot DBNull.Value, valueFromDatabase, 0))
result = (If(valueFromDatabase IsNot DBNull.Value, CDec(valueFromDatabase), CDec(0)))
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="valueFromDatabase", ReadOutsideSymbol:="valueFromDatabase",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, result, valueFromDatabase",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="valueFromDatabase", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Decimal", "Decimal")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Decimal", "Decimal")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, index:=2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="valueFromDatabase", ReadOutsideSymbol:="valueFromDatabase",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, result, valueFromDatabase",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="valueFromDatabase", DataFlowsOutSymbol:="", index:=2)
End Sub
' Implicitly typed arrays used in arguments
<Fact()>
Public Sub ImplicitlyTypedArraysUsedAsarguments()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="ImplicitlyTypedArraysUsedAsarguments">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim a As Integer()
a = Nothing
a = If(True, {1, 2, 3}, {2, 3, 4})
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", Nothing, Nothing)
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Integer()", "Integer()")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Widening, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Widening, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="a, args",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
End Sub
' Nullable bool type can be conditional-argument
<Fact()>
Public Sub NullableAsarguments()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="NullableAsarguments">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim b As Boolean? = Nothing
Dim result = If(b, 0, 1)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean?", "Integer", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean?", "Integer", "Integer")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="b", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, b, result",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="b", DataFlowsOutSymbol:="")
End Sub
' Not boolean type as conditional-argument
<Fact>
Public Sub NotBooleanAsConditionalArgument()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="NotBooleanAsConditionalArgument">
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim x = 1
Dim s = If("", x, 2)
'invalid
s = If("True", x, 2)
'valid
s = If("1", x, 2)
'valid
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "String", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingString, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "String", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingString, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="", index:=2)
'3
semanticInfos = GetSemanticInfos(compilation1, 3)
SemanticInfoTypeTest(semanticInfos, "String", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingString, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 3)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="", index:=3)
End Sub
' Not boolean type as conditional-argument
<Fact>
Public Sub NotBooleanAsConditionalArgument_1()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="NotBooleanAsConditionalArgument">
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim x = 1
Dim s = If(color.Green, x, 2)
'1
s = If(color.Red, x, 2)
'2
End Sub
End Module
Public Enum color
Red
Blue
Green
End Enum
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "color", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingBoolean Or ConversionKind.InvolvesEnumTypeConversions, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "color", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingBoolean Or ConversionKind.InvolvesEnumTypeConversions, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="", index:=2)
End Sub
<Fact>
Public Sub FunctionWithNoReturnType()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="FunctionWithNoReturnType">
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim x = 1
Dim s = If(fun1(), x, 2)
s = If(sub1(), x, 2)
End Sub
Private Sub sub1()
End Sub
Private Function fun1()
End Function
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Object", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.NarrowingValue, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Void", "Object", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.DelegateRelaxationLevelNone, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x", ReadOutsideSymbol:="x",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, x",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="", index:=2)
End Sub
' General type as argument
<Fact>
Public Sub GeneralTypeAsArgument()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="GeneralTypeAsArgument">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
End Sub
Private Function fun(Of T)(Parm1 As T) As T
Dim temp As T
Return If(temp, temp, 1)
End Function
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "T", "T", "Integer")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.DelegateRelaxationLevelNone, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningTypeParameter, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="temp", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="Parm1",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="temp", DataFlowsOutSymbol:="")
End Sub
' General Method as argument
<Fact>
Public Sub GeneralMethodAsArgument()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="GeneralMethodAsArgument">
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Dim x As Integer = 1
Dim y As Object = 0
Dim s = If(True, fun(x), y)
Dim s1 = If(False, sub1(x), y)
End Sub
Private Function fun(Of T)(Parm1 As T) As T
Return Parm1
End Function
Private Sub sub1(Of T)(Parm1 As T)
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Integer", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningValue, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x, y", ReadOutsideSymbol:="x, y",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, s1, x, y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="x", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Void", "Object")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Object", "Object")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(0, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="x, y", ReadOutsideSymbol:="x, y",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, s, s1, x, y",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="y", DataFlowsOutSymbol:="", index:=2)
End Sub
' IF operator on Try Catch
<Fact()>
Public Sub TryCatch()
Dim compilation1 = CreateCompilationWithMscorlib40(
<compilation name="TryCatch">
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim inside = 0
Try
Throw New Exception
Catch ex As Exception When If(False, CType(Nothing, Boolean?), True)
inside = 1
End Try
End Sub
Sub goo()
Try
Dim s_a As Exception
Dim s_b As New InvalidCastException
Throw If(False, s_a, s_b)
Catch ex As InvalidCastException
End Try
End Sub
End Module
</file>
</compilation>, OutputKind.ConsoleApplication)
'1
Dim semanticInfos = GetSemanticInfos(compilation1, 1)
SemanticInfoTypeTest(semanticInfos, "Boolean", "Boolean?", "Boolean")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "Boolean?", "Boolean?")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningNullable, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="args, ex, inside",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="")
'2
semanticInfos = GetSemanticInfos(compilation1, 2)
SemanticInfoTypeTest(semanticInfos, "Boolean", "System.Exception", "System.InvalidCastException")
SemanticInfoConvertedTypeTest(semanticInfos, "Boolean", "System.Exception", "System.Exception")
Assert.Equal(ConversionKind.Identity, semanticInfos(0).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.Identity, semanticInfos(1).ImplicitConversion.Kind)
Assert.Equal(ConversionKind.WideningReference, semanticInfos(2).ImplicitConversion.Kind)
ClassifyConversionTest(compilation1, 2)
AnalyzeRegionDataFlowTestForeach(compilation1, ReadInsideSymbol:="s_a, s_b", ReadOutsideSymbol:="",
WrittenInsideSymbol:="", WrittenOutsideSymbol:="ex, s_b",
AlwaysAssignedSymbol:="", DataFlowsInSymbol:="", DataFlowsOutSymbol:="", index:=2)
End Sub
Private Function GetSemanticInfos(compilation As VisualBasicCompilation, index As Integer) As List(Of SemanticInfoSummary)
Dim model = GetModel(compilation)
Dim ternaryExpression = GetTernaryConditionalExpression(compilation, index)
If (ternaryExpression Is Nothing) Then
Return Nothing
End If
Dim conditionExpression = ternaryExpression.Condition
Dim whenTrueExpression = ternaryExpression.WhenTrue
Dim whenFalseExpression = ternaryExpression.WhenFalse
Dim ConditionSemanticInfo = model.GetSemanticInfoSummary(conditionExpression)
Dim whenTrueSemanticInfo = model.GetSemanticInfoSummary(whenTrueExpression)
Dim whenFalseSemanticInfo = model.GetSemanticInfoSummary(whenFalseExpression)
Dim semanticInfos As List(Of SemanticInfoSummary) = New List(Of SemanticInfoSummary)()
semanticInfos.Add(ConditionSemanticInfo)
semanticInfos.Add(whenTrueSemanticInfo)
semanticInfos.Add(whenFalseSemanticInfo)
Return semanticInfos
End Function
Private Sub SemanticInfoTypeTest(semanticInfos As List(Of SemanticInfoSummary), ParamArray names As String())
Dim i = 0
For Each semanticInfo In semanticInfos
If names(i) Is Nothing Then
Assert.Null(semanticInfo.Type)
Else
If names(i) Is Nothing Then
Assert.Null(semanticInfo.Type)
Else
Assert.Equal(names(i), semanticInfo.Type.ToDisplayString())
End If
End If
i += 1
Next
End Sub
Private Sub SemanticInfoConvertedTypeTest(semanticInfos As List(Of SemanticInfoSummary), ParamArray names As String())
Dim i = 0
If names(0) Is Nothing Then
Assert.Null(semanticInfos(0).Type)
Else
If semanticInfos(0).Type IsNot Nothing AndAlso (semanticInfos(0).Type.ToDisplayString() <> "Void" AndAlso
semanticInfos(1).ConvertedType IsNot Nothing AndAlso
semanticInfos(2).ConvertedType IsNot Nothing AndAlso
semanticInfos(1).ConvertedType.ToDisplayString() <> "Void" AndAlso
semanticInfos(2).ConvertedType.ToDisplayString() <> "Void" AndAlso
semanticInfos(1).ConvertedType.TypeKind <> TypeKind.TypeParameter AndAlso
semanticInfos(2).ConvertedType.TypeKind <> TypeKind.TypeParameter) Then
Assert.Equal(semanticInfos(1).ConvertedType.ToDisplayString(), semanticInfos(2).ConvertedType.ToDisplayString())
End If
End If
For Each semanticInfo In semanticInfos
If names(i) Is Nothing Then
Assert.Null(semanticInfo.Type)
Else
Assert.Equal(names(i), semanticInfo.ConvertedType.ToDisplayString())
End If
i += 1
Next
End Sub
Private Function AnalyzeRegionDataFlowTestForeach(compilation As VisualBasicCompilation,
ReadInsideSymbol As String, ReadOutsideSymbol As String, WrittenInsideSymbol As String,
WrittenOutsideSymbol As String, AlwaysAssignedSymbol As String,
DataFlowsInSymbol As String, DataFlowsOutSymbol As String, Optional variablesDeclared As String = "",
Optional index As Integer = 1) As DataFlowAnalysis
Dim node = GetTernaryConditionalExpression(compilation, index)
Dim model = GetModel(compilation)
Dim analyze = model.AnalyzeDataFlow(node)
Assert.Equal(variablesDeclared, GetSymbolNamesSortedAndJoined(analyze.VariablesDeclared))
Assert.Equal(ReadInsideSymbol, GetSymbolNamesSortedAndJoined(analyze.ReadInside))
Assert.Equal(ReadOutsideSymbol, GetSymbolNamesSortedAndJoined(analyze.ReadOutside))
Assert.Equal(WrittenInsideSymbol, GetSymbolNamesSortedAndJoined(analyze.WrittenInside))
Assert.Equal(WrittenOutsideSymbol, GetSymbolNamesSortedAndJoined(analyze.WrittenOutside))
Assert.Equal(AlwaysAssignedSymbol, GetSymbolNamesSortedAndJoined(analyze.AlwaysAssigned))
Assert.Equal(DataFlowsOutSymbol, GetSymbolNamesSortedAndJoined(analyze.DataFlowsOut))
Return analyze
End Function
Private Function ClassifyConversionTest(compilation As VisualBasicCompilation, Optional index As Integer = 1) As List(Of Conversion)
Dim model = GetModel(compilation)
Dim ternaryExpression = GetTernaryConditionalExpression(compilation, index)
If (ternaryExpression Is Nothing) Then
Return Nothing
End If
Dim conditionExpression = ternaryExpression.Condition
Dim whenTrueExpression = ternaryExpression.WhenTrue
Dim whenFalseExpression = ternaryExpression.WhenFalse
Dim expressions = New List(Of ExpressionSyntax)()
expressions.Add(conditionExpression)
expressions.Add(whenTrueExpression)
expressions.Add(whenFalseExpression)
expressions = expressions.Where(Function(x) x.IsMissing = False).ToList()
Dim convs = New List(Of Conversion)()
For Each expression In expressions
Dim semanticInfo = model.GetSemanticInfoSummary(expression)
Dim conv = model.ClassifyConversion(expression, semanticInfo.ConvertedType)
convs.Add(conv)
If (conv.Kind = ConversionKind.Identity) Then
Assert.True(conv.Exists)
Assert.True(conv.IsIdentity)
End If
If semanticInfo.Type Is Nothing Then
Assert.True(Conversions.IsWideningConversion(semanticInfo.ImplicitConversion.Kind))
ElseIf (semanticInfo.Type.ToDisplayString() <> "?" And semanticInfo.Type.ToDisplayString() <> "Void" And semanticInfo.ConvertedType.ToDisplayString() <> "?" And semanticInfo.ConvertedType.ToDisplayString() <> "Void") Then
Assert.Equal(conv.Kind, semanticInfo.ImplicitConversion.Kind)
End If
Next
Return convs
End Function
Private Function GetSymbolNamesSortedAndJoined(Of T As ISymbol)(symbols As IEnumerable(Of T)) As String
Return String.Join(", ", symbols.Select(Function(symbol) symbol.Name).OrderBy(Function(name) name))
End Function
Private Function GetModel(compilation As VisualBasicCompilation) As SemanticModel
Dim tree = compilation.SyntaxTrees.First
Dim model = compilation.GetSemanticModel(tree)
Return model
End Function
Private Function GetTernaryConditionalExpression(compilation As VisualBasicCompilation, index As Integer) As TernaryConditionalExpressionSyntax
Dim tree = compilation.SyntaxTrees.First
Dim node = tree.FindNodeOrTokenByKind(SyntaxKind.TernaryConditionalExpression, index).AsNode()
'Dim expressions = node.ChildNodes.Select(Function(x) TryCast(x, ExpressionSyntax)).Where(Function(x) x IsNot Nothing)
Dim ternaryExpression = TryCast(node, TernaryConditionalExpressionSyntax)
Return ternaryExpression
End Function
End Class
End Namespace
|