|
' 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.Generic
Imports System.Text
Imports System.Xml.Linq
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
Public Class EnumTests
Inherits BasicTestBase
' The value of first enumerator, and the value of each successive enumerator
<Fact>
Public Sub ValueOfFirst()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum Suits
ValueA
ValueB
ValueC
ValueD
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Suits", 0, 1, 2, 3)
End Sub
' The value can be explicated initialized
<Fact>
Public Sub ExplicateInit()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Suits
ValueA = -1
ValueB = 2
ValueC = 3
ValueD = 4
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Suits", -1, 2, 3, 4)
End Sub
' The value can be explicated and implicit initialized
<Fact>
Public Sub MixedInit()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Suits
ValueA
ValueB = 10
ValueC
ValueD
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Suits", 0, 10, 11, 12)
End Sub
' Using shared field of an enum member does not cause evaluation cycle
<Fact>
Public Sub MixedInitShared()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Suits
ValueA
ValueB = 10
ValueC = Suits.ValueC.ValueB + 1
ValueD
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Suits", 0, 10, 11, 12)
End Sub
' Enumerator initializers must be of integral or enumeration type
<WorkItem(539945, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539945")>
<Fact>
Public Sub OutOfUnderlyingRange()
Dim text =
<compilation name="C">
<file name="a.vb">
Option Strict Off
Public Enum Suits As Byte
ValueA = "3" ' Can't implicitly convert
ValueB = 2.2 ' Can implicitly convert
ValueC = 257 ' Out of underlying range
End Enum
</file>
</compilation>
' There are diagnostics for these values (see EnumErrorsInValues test),
' but as long as the value is constant (including the needed conversion), the constant value is used
' (see conversion of 2.2 vs. conversion of "3").
Dim fields = VerifyEnumsValue(text, "Suits", SpecialType.System_Byte, Nothing, CByte(2), Nothing)
fields.First.DeclaringCompilation.AssertTheseDiagnostics(
<expected>
BC30060: Conversion from 'String' to 'Byte' cannot occur in a constant expression.
ValueA = "3" ' Can't implicitly convert
~~~
BC30439: Constant expression not representable in type 'Byte'.
ValueC = 257 ' Out of underlying range
~~~
</expected>)
text =
<compilation name="C">
<file name="a.vb">
Option Strict On
Public Enum Suits As Byte
ValueA = "3" ' Can't implicitly convert
ValueB = 2.2 ' Can't implicitly convert: [Option Strict On] disallows implicit conversion
ValueC = 257 ' Out of underlying range
End Enum
</file>
</compilation>
' There are diagnostics for these values (see EnumErrorsInValues test),
' but as long as the value is constant (including the needed conversion), the constant value is used
' (see conversion of 2.2 vs. conversion of "3").
fields = VerifyEnumsValue(text, "Suits", SpecialType.System_Byte, Nothing, CByte(2), Nothing)
fields.First.DeclaringCompilation.AssertTheseDiagnostics(
<expected>
BC30512: Option Strict On disallows implicit conversions from 'String' to 'Byte'.
ValueA = "3" ' Can't implicitly convert
~~~
BC30512: Option Strict On disallows implicit conversions from 'Double' to 'Byte'.
ValueB = 2.2 ' Can't implicitly convert: [Option Strict On] disallows implicit conversion
~~~
BC30439: Constant expression not representable in type 'Byte'.
ValueC = 257 ' Out of underlying range
~~~
</expected>)
text =
<compilation name="C">
<file name="a.vb">
Enum Suits As Short
a
b
c
d = -65536
e
f
End Enum
</file>
</compilation>
fields = VerifyEnumsValue(text, "Suits", SpecialType.System_Int16, CShort(0), CShort(1), CShort(2), Nothing, Nothing, Nothing)
fields.First.DeclaringCompilation.AssertTheseDiagnostics(
<expected>
BC30439: Constant expression not representable in type 'Short'.
d = -65536
~~~~~~
</expected>)
End Sub
<Fact>
Public Sub EnumErrorsInValues()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Suits As Byte
ValueA = "3" ' Can't implicitly convert
ValueB = 2.2 ' Can implicitly convert
ValueC = 257 ' Out of underlying range
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
BC30060: Conversion from 'String' to 'Byte' cannot occur in a constant expression.
ValueA = "3" ' Can't implicitly convert
~~~
BC30439: Constant expression not representable in type 'Byte'.
ValueC = 257 ' Out of underlying range
~~~
</errors>)
comp = CompilationUtils.CreateCompilationWithMscorlib40(text, options:=TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.On))
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
BC30512: Option Strict On disallows implicit conversions from 'String' to 'Byte'.
ValueA = "3" ' Can't implicitly convert
~~~
BC30512: Option Strict On disallows implicit conversions from 'Double' to 'Byte'.
ValueB = 2.2 ' Can implicitly convert
~~~
BC30439: Constant expression not representable in type 'Byte'.
ValueC = 257 ' Out of underlying range
~~~
</errors>)
End Sub
<Fact()>
Public Sub ExplicitAssociated()
Dim text =
<compilation name="C">
<file name="a.vb">
Class C(Of T)
Const field As Integer = 100
Private Enum TestEnum
A
B = A ' another member
C = D ' another member
D = CByte(11) ' type can be implicitly converted to underlying type
F = 3 + 5 ' expression
G = field ' const field
TestEnum ' its own type name
var ' contextual keyword
T ' Type parameter
End Enum
Private Enum EnumB
B = TestEnum.T
End Enum
End Class
</file>
</compilation>
VerifyEnumsValue(text, "C.TestEnum", 0, 0, 11, 11, 8, 100, 101, 102, 103)
VerifyEnumsValue(text, "C.EnumB", 103)
text =
<compilation name="C">
<file name="a.vb">
Class c1
Public Shared StaticField As Integer = 10
Public Shared ReadOnly ReadonlyField As Integer = 100
Private Enum EnumTest
A = StaticField
B = ReadonlyField
End Enum
End Class
</file>
</compilation>
VerifyEnumsValue(text, "c1.EnumTest", SpecialType.System_Int32, Nothing, Nothing)
End Sub
' No enum-body
<Fact>
Public Sub NoEnumBody()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum Figure
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Figure")
End Sub
' No identifier
<Fact>
Public Sub BC30203ERR_ExpectedIdentifier_NoIDForEnum()
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(
<compilation name="BadEmptyEnum1">
<file name="a.vb">
Enum
One
Two
Three
End Enum
</file>
</compilation>)
CompilationUtils.AssertTheseParseDiagnostics(comp, <ERRORS>
BC30203: Identifier expected.
Enum
~
</ERRORS>)
End Sub
<Fact>
Public Sub EnumTypeCharMismatch()
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(
<compilation name="EnumTypeCharMismatch">
<file name="a.vb">
Enum E As Integer
X
Y = E.X%
Z = E.X$
End Enum
</file>
</compilation>)
CompilationUtils.AssertTheseDiagnostics(comp, <ERRORS>
BC30277: Type character '$' does not match declared data type 'Integer'.
Z = E.X$
~~
</ERRORS>)
End Sub
<Fact>
Public Sub EnumTypeCharMismatch1()
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(
<compilation name="EnumTypeCharMismatch">
<file name="a.vb">
Imports System
Module M1
Enum E As Integer
X = Int32%.MinValue
Y = E%.X
Z = E$.X
End Enum
End Module
</file>
</compilation>)
CompilationUtils.AssertTheseDiagnostics(comp, <ERRORS>
BC30277: Type character '$' does not match declared data type 'Integer'.
Z = E$.X
~~
</ERRORS>)
End Sub
' Same identifier for enum members
<Fact>
Public Sub SameIDForEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum TestEnum
One
One
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "TestEnum", 0, 1)
End Sub
' Modifiers for enum
<WorkItem(539944, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539944")>
<Fact>
Public Sub BC30396ERR_BadEnumFlags1_ModifiersForEnum()
Dim compilation1 = CompilationUtils.CreateCompilationWithMscorlib40(
<compilation name="C">
<file name="a.vb">
Class Program
Protected Enum Figure1
One = 1
End Enum ' OK
New Public Enum Figure2
Zero = 0
End Enum ' new + protection modifier is Not OK
Private MustInherit Enum Figure3
Zero
End Enum ' abstract not valid
Private Private Enum Figure4
One = 1
End Enum ' Duplicate modifier is not OK
Private Public Enum Figure5
End Enum ' More than one protection modifiers is not OK
Private NotInheritable Enum Figure0
Zero
End Enum ' sealed not valid
Private Shadows Enum Figure
Zero
End Enum ' OK
End Class
</file>
</compilation>)
Dim expectedErrors1 = <errors>
BC30035: Syntax error.
New Public Enum Figure2
~~~
BC30188: Declaration expected.
Zero = 0
~~~~
BC30184: 'End Enum' must be preceded by a matching 'Enum'.
End Enum ' new + protection modifier is Not OK
~~~~~~~~
BC30396: 'MustInherit' is not valid on an Enum declaration.
Private MustInherit Enum Figure3
~~~~~~~~~~~
BC30178: Specifier is duplicated.
Private Private Enum Figure4
~~~~~~~
BC30176: Only one of 'Public', 'Private', 'Protected', 'Friend', 'Protected Friend', or 'Private Protected' can be specified.
Private Public Enum Figure5
~~~~~~
BC30280: Enum 'Figure5' must contain at least one member.
Private Public Enum Figure5
~~~~~~~
BC30396: 'NotInheritable' is not valid on an Enum declaration.
Private NotInheritable Enum Figure0
~~~~~~~~~~~~~~
</errors>
CompilationUtils.AssertTheseDiagnostics(compilation1, expectedErrors1)
End Sub
' Modifiers for enum member
<Fact>
Public Sub ModifiersForEnumMember()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum ColorA
Public Red
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "ColorA")
text =
<compilation name="C">
<file name="a.vb">
Enum ColorA
Private Sub goo()
End Sub
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "ColorA")
End Sub
' Flag Attribute and Enumerate a Enum
<Fact>
Public Sub FlagOnEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
<System.Flags>
Public Enum Suits
ValueA = 1
ValueB = 2
ValueC = 4
ValueD = 8
Combi = ValueA Or ValueB
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Suits", 1, 2, 4, 8, 3)
End Sub
' Customer Attribute on Enum declaration
<Fact>
Public Sub AttributeOnEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Class Attr1
Inherits System.Attribute
End Class
<Attr1> _
Enum Figure
One
Two
Three
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Figure", 0, 1, 2)
End Sub
<Fact()>
Public Sub ConvertOnEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Class c1
Public Enum Suits
ValueA = 1
ValueB = 2
ValueC = 4
ValueD = 2
ValueE = 2
End Enum
Shared Sub Main()
Dim S As Suits = CType(2, Suits)
Console.WriteLine(S = Suits.ValueB)
Console.WriteLine(S = Suits.ValueE)
Dim S1 As Suits = CType(-1, Suits)
Console.WriteLine(S1.ToString()) ' 255
End Sub
End Class
</file>
</compilation>
VerifyEnumsValue(text, "c1.Suits", 1, 2, 4, 2, 2)
Dim expectedOutput = <![CDATA[True
True
-1
]]>
Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(text, TestOptions.ReleaseExe)
CompileAndVerify(comp, expectedOutput)
End Sub
' Enum used in switch
<Fact>
Public Sub SwitchInEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Class c1
Public Enum Suits
ValueA = 2
ValueB
ValueC = 2
End Enum
Public Sub Main()
Dim s As Suits
Select Case s
Case Suits.ValueA
Exit Select
Case Suits.ValueB
Exit Select
Case Suits.ValueC
Exit Select
Case Else
Exit Select
End Select
End Sub
End Class
</file>
</compilation>
VerifyEnumsValue(text, "c1.Suits", 2, 3, 2)
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors></errors>)
End Sub
' The literal 0 implicitly converts to any enum type.
<Fact>
Public Sub ZeroInEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Class c1
Private Enum Gender As Byte
Male = 2
End Enum
Public Shared Sub Main(args As String())
Dim s As Gender = 0
Console.WriteLine(s)
s = -0
Console.WriteLine(s)
s = 0.0
Console.WriteLine(s)
End Sub
End Class
</file>
</compilation>
CompileAndVerify(text, expectedOutput:="0" & Environment.NewLine & "0" & Environment.NewLine & "0" & Environment.NewLine)
End Sub
' Derived.
<Fact>
Public Sub BC30628ERR_StructCantInherit_DerivedFromEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Suits
ValueA = 2
ValueB
ValueC = 2
End Enum
Structure S1
Inherits Suits
End Structure
Interface I1
Inherits Suits
End Interface
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors>
BC30628: Structures cannot have 'Inherits' statements.
Inherits Suits
~~~~~~~~~~~~~~
BC30354: Interface can inherit only from another interface.
Inherits Suits
~~~~~
</errors>)
End Sub
' Enums can Not be declared in nested enum declaration
<WorkItem(539943, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539943")>
<Fact>
Public Sub BC30619ERR_InvInsideEndsEnum_NestedFromEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Num
Enum Figure
Zero
End Enum
End Enum
</file>
</compilation>
VerifyEnumsValue(text, "Num")
VerifyEnumsValue(text, "Figure", 0)
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
BC30185: 'Enum' must end with a matching 'End Enum'.
Public Enum Num
~~~~~~~~~~~~~~~
BC30280: Enum 'Num' must contain at least one member.
Public Enum Num
~~~
BC30619: Statement cannot appear within an Enum body. End of Enum assumed.
Enum Figure
~~~~~~~~~~~
BC30184: 'End Enum' must be preceded by a matching 'Enum'.
End Enum
~~~~~~~~
</errors>)
End Sub
' Enums can be declared anywhere
<Fact>
Public Sub DeclEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Namespace ns
Enum Gender
Male
End Enum
End Namespace
Structure B
Private Enum Gender
Male
End Enum
End Structure
</file>
</compilation>
VerifyEnumsValue(text, "ns.Gender", 0)
VerifyEnumsValue(text, "B.Gender", 0)
End Sub
' Enums obey local scope rules
<Fact>
Public Sub DeclEnum_01()
Dim text =
<compilation name="C">
<file name="a.vb">
Namespace ns
Enum E1
yes = 1
no = yes - 1
End Enum
Public Class mine
Public Enum E1
yes = 1
no = yes - 1
End Enum
End Class
End Namespace
</file>
</compilation>
VerifyEnumsValue(text, "ns.E1", 1, 0)
VerifyEnumsValue(text, "ns.mine.E1", 1, 0)
End Sub
<Fact()>
Public Sub NullableOfEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum EnumB As Long
Num = 1000
End Enum
Class c1
Public Shared Sub Main()
Dim a As EnumB = 0
Dim c As System.Nullable(Of EnumB) = Nothing
a = CType(c, EnumB)
End Sub
End Class
</file>
</compilation>
VerifyEnumsValue(text, "EnumB", 1000L)
CompileAndVerify(text)
End Sub
' Operator on null and enum
<Fact>
Public Sub OperatorOnNullableAndEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
class c1
Private e As MyEnum = Nothing And MyEnum.One
End Class
enum MyEnum
One
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors></errors>)
End Sub
' Operator on enum
<Fact>
Public Sub OperatorOnEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Class c1
Public Shared Sub Main(args As String())
Dim e1 As Enum1 = e1 + 5L
Dim e2 As Enum2 = e1 + e2
e1 = Enum1.A1 + Enum1.B1
Dim b1 As Boolean = e1 = 1
Dim b7 As Boolean = e1 = e2
e1 += 1 ' OK
e2 -= 1 ' OK
e1 = e1 Xor Enum1.A1 ' OK
e1 = e1 Xor Enum1.B1 ' OK
End Sub
End Class
Public Enum Enum1
A1 = 1
B1 = 2
End Enum
Public Enum Enum2 As Byte
A2
B2
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors></errors>)
End Sub
' Operator on enum member
<Fact>
Public Sub OperatorOnEnumMember()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Class c1
Public Shared Sub Main(args As String())
Dim s As E = E.one
Dim b1 = E.three > E.two
Dim b2 = E.three < E.two
Dim b3 = E.three = E.two
Dim b4 = E.three <> E.two
Dim b5 = s > E.two
Dim b6 = s < E.two
Dim b7 = s = E.two
Dim b8 = s <> E.two
Console.WriteLine(b1)
Console.WriteLine(b2)
Console.WriteLine(b3)
Console.WriteLine(b4)
Console.WriteLine(b5)
Console.WriteLine(b6)
Console.WriteLine(b7)
Console.WriteLine(b8)
End Sub
End Class
Public Enum E
one = 1
two = 2
three = 3
End Enum
</file>
</compilation>
CompileAndVerify(text, expectedOutput:="True" & Environment.NewLine & "False" & Environment.NewLine & "False" & Environment.NewLine & "True" & Environment.NewLine & "False" & Environment.NewLine & "True" & Environment.NewLine & "False" & Environment.NewLine & "True" & Environment.NewLine)
End Sub
' CLS-Compliant
<Fact>
Public Sub CLSCompliantOnEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
<Assembly: System.CLSCompliant(True)>
Public Class c1
Public Enum COLORS As UInteger
RED
GREEN
BLUE
End Enum
End Class
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
VerifyEnumsValue(comp, "c1.COLORS", SpecialType.System_UInt32, 0UI, 1UI, 2UI)
End Sub
' No Base type after 'As'
<WorkItem(528031, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528031")>
<Fact>
Public Sub BC30182ERR_UnrecognizedType_NoUnderlyingTypeForEnum()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Figure As
One
Two
Three
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseParseDiagnostics(comp, <errors>
BC30182: Type expected.
Public Enum Figure As
~
</errors>)
VerifyEnumsValue(comp, "Figure", SpecialType.System_Int32, 0, 1, 2)
End Sub
' All integral type could be as BASE type
<WorkItem(539945, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539945")>
<Fact>
Public Sub BC30650ERR_InvalidEnumBase_BaseType()
Dim text =
<compilation name="C">
<file name="a.vb">
Public Enum Figure As System.Int64
One
Two
Three
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors></errors>)
VerifyEnumsValue(comp, "Figure", SpecialType.System_Int64, CLng(0), CLng(1), CLng(2))
text =
<compilation name="C">
<file name="a.vb">
Class C
End Class
Enum Figure As C
One
Two
Three
End Enum
</file>
</compilation>
comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors>
BC30650: Enums must be declared as an integral type.
Enum Figure As C
~
</errors>)
VerifyEnumsValue(comp, "Figure", SpecialType.System_Int32, 0, 1, 2)
End Sub
' 'partial' as Enum name
<Fact>
Public Sub partialAsEnumName()
Dim text =
<compilation name="C">
<file name="a.vb">
Partial Class EnumPartial
Friend Enum [partial]
ONE
End Enum
Dim M As [partial]
End Class
</file>
</compilation>
VerifyEnumsValue(text, "EnumPartial.partial", 0)
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
Dim classEnum = TryCast(comp.SourceModule.GlobalNamespace.GetMembers("EnumPartial").Single(), NamedTypeSymbol)
Dim member = TryCast(classEnum.GetMembers("M").Single(), FieldSymbol)
Assert.Equal(TypeKind.Enum, member.Type.TypeKind)
End Sub
' Enum as an optional parameter
<Fact()>
Public Sub EnumAsOptionalParameter()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum ABC
a
b
c
End Enum
Class c1
Public Function Goo(Optional o As ABC = ABC.a Or ABC.b) As Integer
Return 0
End Function
Public Function Moo(Optional o As Object = ABC.a) As Integer
Return 1
End Function
End Class
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDeclarationDiagnostics(comp, <errors></errors>)
End Sub
<WorkItem(540427, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540427")>
<Fact>
Public Sub EnumInitializerCircularReference()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum Enum1
A = B + 1
B
End Enum
</file>
</compilation>
CompilationUtils.CreateCompilationWithMscorlib40(text).VerifyDiagnostics(Diagnostic(ERRID.ERR_CircularEvaluation1, "A").WithArguments("A"))
End Sub
<WorkItem(540526, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540526")>
<Fact>
Public Sub EnumBadMember()
Dim text =
<compilation>
<file name="a.vb">
Enum E
[A
End Enum
</file>
</compilation>
CompilationUtils.CreateCompilationWithMscorlib40(text).VerifyDiagnostics(
Diagnostic(ERRID.ERR_MissingEndEnum, "Enum E"),
Diagnostic(ERRID.ERR_InvInsideEndsEnum, ""),
Diagnostic(ERRID.ERR_MissingEndBrack, "[A"),
Diagnostic(ERRID.ERR_InvalidEndEnum, "End Enum"),
Diagnostic(ERRID.ERR_BadEmptyEnum1, "E").WithArguments("E"))
End Sub
<WorkItem(540526, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540526")>
<Fact>
Public Sub EnumBadMember2()
Dim text =
<compilation>
<file name="a.vb">
Enum E
goo:
End Enum
</file>
</compilation>
CompilationUtils.CreateCompilationWithMscorlib40(text).VerifyDiagnostics(
Diagnostic(ERRID.ERR_InvInsideEnum, "goo:"))
End Sub
<WorkItem(540557, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540557")>
<Fact>
Public Sub EnumInDifferentFile()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Imports Color
Module M1
Dim passed As Boolean
Dim m_clr As Color
Property Clr As Color
Get
Return m_clr
End Get
Set(value As Color)
m_clr = value
End Set
End Property
End Module
</file>
<file name="color.vb">
Public Enum Color
red
green
blue
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(text)
CompilationUtils.AssertNoErrors(comp)
Dim globalNS = comp.SourceModule.GlobalNamespace
Dim M1 = DirectCast(globalNS.GetMembers("M1").First(), TypeSymbol)
Dim Clr = DirectCast(M1.GetMembers("Clr").First(), PropertySymbol)
Dim Color = Clr.Type
Assert.Equal("Color", Color.Name)
End Sub
<Fact>
Public Sub EnumMemberInitMustBeConstant()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Class A
Public Const X As Integer = 1
End Class
Class B
Sub New(x As Action)
End Sub
Sub New(x As Integer)
End Sub
Public Const X As Integer = 2
End Class
Class C
Sub New(x As Integer)
End Sub
Public Const X As Integer = 3
End Class
Class D
Sub New(x As Func(Of Integer))
End Sub
Public Const X As Integer = 4
End Class
Module M
Public Enum Bar As Integer
ValueWorks1 = new C(23).X
ValueWorks2 = new A().X
ValueWorks3 = 23 + new A().X
ValueWorks4 = if(nothing, 23)
ValueWorks5 = if(23 = 42, 23, 42)
ValueWorks6 = if(new A().X = 0, 23, 42)
ValueWorks7 = if(new A(), nothing).X
ValueWorks8 = if(23 = 42, 23, new A().X)
ValueWorks9 = if(23 = 42, new A().X, 42)
ValueWorks10 = New B(Sub() Exit Sub).X
ValueWorks11 = New D(Function() 23).X
ValueDoesntWork1 = goo()
End Enum
Public Function goo() As Integer
Return 23
End Function
public sub main()
end sub
End Module
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(text)
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks1 = new C(23).X
~~~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks2 = new A().X
~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks3 = 23 + new A().X
~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks6 = if(new A().X = 0, 23, 42)
~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks7 = if(new A(), nothing).X
~~~~~~~~~~~~~~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks8 = if(23 = 42, 23, new A().X)
~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks9 = if(23 = 42, new A().X, 42)
~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks10 = New B(Sub() Exit Sub).X
~~~~~~~~~~~~~~~~~~~~~~~
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueWorks11 = New D(Function() 23).X
~~~~~~~~~~~~~~~~~~~~~~
BC30059: Constant expression is required.
ValueDoesntWork1 = goo()
~~~~~
</errors>)
End Sub
''' bug 8151
<Fact>
Public Sub EnumMemberWithNonConstInitializationAndSelfDependency()
Dim text =
<compilation name="C">
<file name="a.vb">
Imports System
Class D
Sub New(x As Func(Of Integer))
End Sub
Public Const X As Integer = 4
End Class
Module M
Public Enum Bar As Integer
ValueDoesntWork2
ValueDoesntWork3 = New D(Function() ValueDoesntWork2).X
ValueDoesntWork4 = New D(Function() ValueDoesntWork4).X
End Enum
public sub main()
end sub
End Module
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(text)
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
ValueDoesntWork3 = New D(Function() ValueDoesntWork2).X
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30500: Constant 'ValueDoesntWork4' cannot depend on its own value.
ValueDoesntWork4 = New D(Function() ValueDoesntWork4).X
~~~~~~~~~~~~~~~~
</errors>)
End Sub
' The value can be used off an enum member
<WorkItem(541364, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541364")>
<Fact>
Public Sub EnumUseQualified()
Dim text =
<compilation name="C">
<file name="a.vb">
Enum Y
X
Y = Y.X
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
CompilationUtils.AssertTheseDiagnostics(comp, <errors>
</errors>)
VerifyEnumsValue(text, "Y", 0, 0)
End Sub
<WorkItem(750553, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/750553")>
<Fact>
Public Sub InvalidEnumUnderlyingType()
Dim text =
<compilation>
<file name="a.vb">
Class C(Of T As Structure)
Enum E As T
A
End Enum
End Class
</file>
</compilation>
Dim errors =
<errors>
BC30650: Enums must be declared as an integral type.
Enum E As T
~
</errors>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
comp.AssertTheseDiagnostics(errors)
Dim tree = comp.SyntaxTrees(0)
Dim model = comp.GetSemanticModel(tree)
Dim diagnostics = model.GetDeclarationDiagnostics()
AssertTheseDiagnostics(diagnostics, errors)
Dim decl = tree.GetCompilationUnitRoot().DescendantNodes().OfType(Of EnumBlockSyntax).Single()
Dim symbol = model.GetDeclaredSymbol(decl)
Dim type = symbol.EnumUnderlyingType
Assert.Equal(type.SpecialType, SpecialType.System_Int32)
End Sub
<Fact, WorkItem(895284, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/895284")>
Public Sub CircularDefinition_Explicit()
' Bug#895284 Roslyn gives extra error BC30060:
' Conversion from 'E2' to 'Integer' cannot occur in a constant expression.
' Per field
Dim source =
<compilation>
<file name="a.vb">
Enum E1
M10 = 1
M11 = CType(M10, Integer) + 1
M12 = CType(M11, Integer) + 1
End Enum
Enum E2
M20 = CType(M22, Integer) + 1
M21 = CType(M20, Integer) + 1
M22 = CType(M21, Integer) + 1
End Enum
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(source)
comp.AssertTheseDiagnostics(<errors>
BC30500: Constant 'M20' cannot depend on its own value.
M20 = CType(M22, Integer) + 1
~~~
BC30060: Conversion from 'E2' to 'Integer' cannot occur in a constant expression.
M21 = CType(M20, Integer) + 1
~~~
BC30060: Conversion from 'E2' to 'Integer' cannot occur in a constant expression.
M22 = CType(M21, Integer) + 1
~~~
</errors>)
End Sub
<Fact>
Public Sub CircularDefinitionManyMembers_Implicit()
' Enum E
' M0 = Mn + 1
' M1
' ...
' Mn
' End Enum
Dim source = GenerateEnum(6000, Function(i, n) If(i = 0, String.Format("M{0} + 1", n - 1), ""))
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(source)
comp.AssertTheseDiagnostics(<errors>
BC30500: Constant 'M0' cannot depend on its own value.
M0 = M5999 + 1
~~
</errors>)
End Sub
<Fact,
WorkItem(123937, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=123937"),
WorkItem(886047, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/886047")>
Public Sub CircularDefinitionManyMembers_Explicit()
' Enum E
' M0 = Mn + 1
' M1 = M0 + 1
' ...
' Mn = Mn-1 + 1
' End Enum
' Dev12 crashes at ~300 members.
Const bug123937IsFixed = False
Dim count As Integer = 2
If bug123937IsFixed Then
count = 6000
End If
Dim source = GenerateEnum(count, Function(i, n) String.Format("M{0} + 1", If(i = 0, n - 1, i - 1)))
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(source)
' Note, native compiler doesn't report BC30060, we should try to suppress it too.
comp.AssertTheseDiagnostics(<errors>
BC30500: Constant 'M0' cannot depend on its own value.
M0 = M1 + 1
~~
BC30060: Conversion from 'E' to 'Integer' cannot occur in a constant expression.
M1 = M0 + 1
~~
</errors>)
End Sub
<Fact,
WorkItem(123937, "https://devdiv.visualstudio.com/defaultcollection/DevDiv/_workitems#_a=edit&id=123937"),
WorkItem(886047, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/886047")>
Public Sub InvertedDefinitionManyMembers_Explicit()
' Enum E
' M0 = M1 - 1
' M1 = M2 - 1
' ...
' Mn = n
' End Enum
' Dev12 crashes at ~300 members.
Const bug123937IsFixed = False
Dim count As Integer = 20
If bug123937IsFixed Then
count = 6000
End If
Dim source = GenerateEnum(count, Function(i, n) If(i < n - 1, String.Format("M{0} - 1", i + 1), i.ToString()))
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(source)
comp.AssertTheseDiagnostics(<errors/>)
End Sub
''' <summary>
''' Generate:
''' <code>
''' Enum E
''' M0 = ...
''' M1 = ...
''' ...
''' Mn = ...
''' End Enum
''' </code>
''' </summary>
Private Shared Function GenerateEnum(n As Integer, getMemberValue As Func(Of Integer, Integer, String)) As XElement
Dim builder As New StringBuilder()
builder.AppendLine("Enum E")
For i = 0 To n - 1
builder.Append(String.Format(" M{0}", i))
Dim value = getMemberValue(i, n)
If Not String.IsNullOrEmpty(value) Then
builder.Append(" = ")
builder.Append(value)
End If
builder.AppendLine()
Next
builder.AppendLine("End Enum")
Return <compilation>
<file name="a.vb"><%= builder.ToString() %></file>
</compilation>
End Function
Private Shared Function VerifyEnumsValue(text As XElement, enumName As String, ParamArray expectedEnumValues As Object()) As List(Of Symbol)
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
Return VerifyEnumsValue(comp, enumName, If(expectedEnumValues.Any() AndAlso expectedEnumValues.First().GetType() Is GetType(Long), SpecialType.System_Int64, SpecialType.System_Int32), expectedEnumValues)
End Function
Private Shared Function VerifyEnumsValue(text As XElement, enumName As String, underlyingType As SpecialType, ParamArray expectedEnumValues As Object()) As List(Of Symbol)
Dim comp = CompilationUtils.CreateCompilationWithMscorlib40(text)
Return VerifyEnumsValue(comp, enumName, underlyingType, expectedEnumValues)
End Function
Private Shared Function VerifyEnumsValue(comp As VisualBasicCompilation, enumName As String, underlyingType As SpecialType, ParamArray expectedEnumValues As Object()) As List(Of Symbol)
Dim symEnum = TryCast(GetSymbolByFullName(comp, enumName), NamedTypeSymbol)
Assert.NotNull(symEnum)
Dim type = symEnum.EnumUnderlyingType
Assert.NotNull(type)
Assert.Equal(underlyingType, type.SpecialType)
Dim fields = symEnum.GetMembers().OfType(Of FieldSymbol).Cast(Of Symbol)()
Assert.Equal(expectedEnumValues.Length, fields.Count - 1)
For count = 0 To fields.Count - 1
Dim field = DirectCast(fields(count), FieldSymbol)
Dim fieldDefinition = DirectCast(field.GetCciAdapter(), Cci.IFieldDefinition)
If count = 0 Then
Assert.Equal(field.Name, "value__")
Assert.False(field.IsShared)
Assert.False(field.IsConst)
Assert.False(field.IsReadOnly)
Assert.Equal(field.DeclaredAccessibility, Accessibility.Public)
Assert.Equal(field.Type.SpecialType, underlyingType)
Assert.True(fieldDefinition.IsSpecialName)
Assert.True(fieldDefinition.IsRuntimeSpecial)
Else
Assert.Equal(expectedEnumValues(count - 1), field.ConstantValue)
Assert.True(field.IsShared)
Assert.True(field.IsConst)
Assert.False(fieldDefinition.IsSpecialName)
Assert.False(fieldDefinition.IsRuntimeSpecial)
End If
Next
Return fields.ToList()
End Function
Private Shared Function GetSymbolByFullName(compilation As VisualBasicCompilation, memberName As String) As Symbol
Dim names As String() = memberName.Split("."c)
Dim currentSymbol As Symbol = compilation.GlobalNamespace
For Each name In names
Assert.True(TypeOf currentSymbol Is NamespaceOrTypeSymbol, String.Format("{0} does not have members", currentSymbol.ToDisplayString()))
Dim currentContainer = DirectCast(currentSymbol, NamespaceOrTypeSymbol)
Dim members = currentContainer.GetMembers(name)
Assert.True(members.Length > 0, String.Format("No members named {0} inside {1}", name, currentSymbol.ToDisplayString()))
Assert.True(members.Length <= 1, String.Format("Multiple members named {0} inside {1}", name, currentSymbol.ToDisplayString()))
currentSymbol = members.First()
Next
Return currentSymbol
End Function
<WorkItem(45625, "https://github.com/dotnet/roslyn/issues/45625")>
<Fact>
Public Sub UseSiteError_01()
Dim sourceA =
"
public class A
End Class
"
Dim comp = CreateCompilation(sourceA, assemblyName:="UseSiteError_sourceA")
Dim refA = comp.EmitToImageReference()
Dim sourceB =
"
public class B( Of T)
public enum E
F
end enum
end class
public class C
public const F as B(Of A).E = Nothing
end class
"
comp = CreateCompilation(sourceB, references:={refA})
Dim refB = comp.EmitToImageReference()
Dim sourceC =
"
class Program
Shared Sub Main()
const x As Integer = CType(Not C.F, Integer)
System.Console.WriteLine(x)
End Sub
end class
"
comp = CreateCompilation(sourceC, references:={refB})
comp.AssertTheseDiagnostics(
<expected>
BC30652: Reference required to assembly 'UseSiteError_sourceA, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' containing the type 'A'. Add one to your project.
const x As Integer = CType(Not C.F, Integer)
~~~
</expected>)
Dim tree = comp.SyntaxTrees(0)
Dim model = comp.GetSemanticModel(tree)
Dim expr = tree.GetRoot().DescendantNodes().Single(Function(n) n.Kind() = SyntaxKind.NotExpression)
Dim value = model.GetConstantValue(expr)
Assert.True(value.HasValue)
Assert.Equal(-1, value.Value)
End Sub
<WorkItem(45625, "https://github.com/dotnet/roslyn/issues/45625")>
<Fact>
Public Sub UseSiteError_02()
Dim sourceA =
"
public class A
End Class
"
Dim comp = CreateCompilation(sourceA, assemblyName:="UseSiteError_sourceA")
Dim refA = comp.EmitToImageReference()
Dim sourceB =
"
public class B( Of T)
public enum E
F
end enum
end class
public class C
public const F as B(Of A).E = Nothing
end class
"
comp = CreateCompilation(sourceB, references:={refA})
Dim refB = comp.EmitToImageReference()
Dim sourceC =
"
Option Infer On
class Program
Shared Sub Main()
Dim x = Not C.F
System.Console.WriteLine(x)
End Sub
end class
"
comp = CreateCompilation(sourceC, references:={refB}, options:=TestOptions.ReleaseExe)
comp.AssertTheseDiagnostics(
<expected>
BC30652: Reference required to assembly 'UseSiteError_sourceA, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' containing the type 'A'. Add one to your project.
Dim x = Not C.F
~~~
</expected>)
comp = CreateCompilation(sourceC, references:={refB}, options:=TestOptions.DebugExe)
comp.AssertTheseDiagnostics(
<expected>
BC30652: Reference required to assembly 'UseSiteError_sourceA, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' containing the type 'A'. Add one to your project.
Dim x = Not C.F
~~~
</expected>)
End Sub
<Fact>
<WorkItem(50163, "https://github.com/dotnet/roslyn/issues/50163")>
Public Sub LongDependencyChain()
Dim text As New StringBuilder()
text.AppendLine(
"
Enum Test
Item0 = 1
")
For i As Integer = 1 To 2000
text.AppendLine()
text.AppendFormat(" Item{1} = Item{0} + 1", i - 1, i)
Next
text.AppendLine(
"
End Enum
")
Dim comp = CreateCompilation(text.ToString())
Dim item2000 = comp.GetMember(Of FieldSymbol)("Test.Item2000")
Assert.Equal(2001, item2000.ConstantValue)
End Sub
<Fact>
<WorkItem(52624, "https://github.com/dotnet/roslyn/issues/52624")>
Public Sub Issue52624()
Dim source1 =
"
Public Enum SyntaxKind As UShort
None = 0
List = GreenNode.ListKind
End Enum
"
Dim source2 =
"
Friend Class GreenNode
Public Const ListKind = 1
End Class
"
For i As Integer = 1 To 1000
Dim comp = CreateCompilation({source1, source2}, options:=TestOptions.DebugDll)
comp.VerifyDiagnostics()
Dim listKind = comp.GlobalNamespace.GetMember(Of FieldSymbol)("GreenNode.ListKind")
Assert.Equal(1, listKind.ConstantValue)
Assert.Equal("System.Int32", listKind.Type.ToTestDisplayString())
Dim list = comp.GlobalNamespace.GetMember(Of FieldSymbol)("SyntaxKind.List")
Assert.Equal(1US, list.ConstantValue)
Assert.Equal("SyntaxKind", list.Type.ToTestDisplayString())
Next
End Sub
End Class
End Namespace
|