|
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
Imports System.Collections.Immutable
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Xml.Linq
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
Imports TypeKind = Microsoft.CodeAnalysis.TypeKind
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Public Class AttributeTests_Conditional
Inherits BasicTestBase
#Region "Conditional Attribute Type tests"
#Region "Common Helpers"
Private Shared ReadOnly s_commonTestSource_ConditionalAttrDefs As String = <![CDATA[
Imports System
Imports System.Diagnostics
' Applied conditional attribute
<Conditional("cond1")> _
Public Class PreservedAppliedAttribute
Inherits Attribute
End Class
<Conditional("cond2")> _
Public Class OmittedAppliedAttribute
Inherits Attribute
End Class
' Inherited conditional attribute
<Conditional("cond3_dummy")> _
Public Class BasePreservedInheritedAttribute
Inherits Attribute
End Class
<Conditional("cond3")> _
Public Class PreservedInheritedAttribute
Inherits BasePreservedInheritedAttribute
End Class
<Conditional("cond4")> _
Public Class BaseOmittedInheritedAttribute
Inherits Attribute
End Class
<Conditional("cond5")> _
Public Class OmittedInheritedAttribute
Inherits BaseOmittedInheritedAttribute
End Class
' Multiple conditional attributes
<Conditional("cond6"), Conditional("cond7"), Conditional("cond8")> _
Public Class PreservedMultipleAttribute
Inherits Attribute
End Class
<Conditional("cond9")> _
Public Class BaseOmittedMultipleAttribute
Inherits Attribute
End Class
<Conditional("cond10"), Conditional("cond11")> _
Public Class OmittedMultipleAttribute
Inherits BaseOmittedMultipleAttribute
End Class
' Partially preserved applied conditional attribute
' This attribute has its conditional constant defined midway through the source file. Hence it is conditionally emitted in metadata only for some symbols.
<Conditional("condForPartiallyPreservedAppliedAttribute")> _
Public Class PartiallyPreservedAppliedAttribute
Inherits Attribute
End Class
]]>.Value
Private Shared ReadOnly s_commonTestSource_ConditionalAttributesApplied As String = <![CDATA[
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public MustInherit Class Z
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public Function m(<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> param1 As Integer) _
As <PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> Integer
#Const condForPartiallyPreservedAppliedAttribute = True
Return 0
End Function
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public f As Integer
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public Property p1() As <PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> Integer
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Get
Return m_p1
End Get
#Const condForPartiallyPreservedAppliedAttribute = False
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Set(value As Integer)
m_p1 = value
End Set
End Property
Private m_p1 As Integer
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public MustOverride ReadOnly Property p2() As <PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> Integer
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public MustOverride Property p3() As <PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> Integer
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public Event e As Action
End Class
#Const condForPartiallyPreservedAppliedAttribute = "TrueAgain"
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public Enum E
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
A = 1
End Enum
<PreservedAppliedAttribute, OmittedAppliedAttribute, PreservedInheritedAttribute, OmittedInheritedAttribute, PreservedMultipleAttribute, OmittedMultipleAttribute, PartiallyPreservedAppliedAttribute> _
Public Structure S
End Structure
Public Class Test
Public Shared Sub Main()
End Sub
End Class
]]>.Value
Private ReadOnly _commonValidatorForCondAttrType As Func(Of Boolean, Action(Of ModuleSymbol)) =
Function(isFromSource As Boolean) _
Sub(m As ModuleSymbol)
' Each Tuple indicates: <Attributes, hasPartiallyPreservedAppliedAttribute>
' PartiallyPreservedAppliedAttribute has its conditional constant defined midway through the source file.
' Hence this attribute is emitted in metadata only for some symbols.
Dim attributesArrayBuilder = ArrayBuilder(Of Tuple(Of ImmutableArray(Of VisualBasicAttributeData), Boolean)).GetInstance()
Dim classZ = m.GlobalNamespace.GetTypeMember("Z")
attributesArrayBuilder.Add(Tuple.Create(classZ.GetAttributes(), False))
Dim methodM = classZ.GetMember(Of MethodSymbol)("m")
attributesArrayBuilder.Add(Tuple.Create(methodM.GetAttributes(), False))
attributesArrayBuilder.Add(Tuple.Create(methodM.GetReturnTypeAttributes(), False))
Dim param1 = methodM.Parameters(0)
attributesArrayBuilder.Add(Tuple.Create(param1.GetAttributes(), False))
Dim fieldF = classZ.GetMember(Of FieldSymbol)("f")
attributesArrayBuilder.Add(Tuple.Create(fieldF.GetAttributes(), True))
Dim propP1 = classZ.GetMember(Of PropertySymbol)("p1")
attributesArrayBuilder.Add(Tuple.Create(propP1.GetAttributes(), True))
Dim propGetMethod = propP1.GetMethod
attributesArrayBuilder.Add(Tuple.Create(propGetMethod.GetAttributes(), True))
attributesArrayBuilder.Add(Tuple.Create(propGetMethod.GetReturnTypeAttributes(), True))
Dim propSetMethod = propP1.SetMethod
attributesArrayBuilder.Add(Tuple.Create(propSetMethod.GetAttributes(), False))
Assert.Equal(0, propSetMethod.GetReturnTypeAttributes().Length)
Assert.Equal(0, propSetMethod.Parameters(0).GetAttributes().Length)
Dim propP2 = classZ.GetMember(Of PropertySymbol)("p2")
attributesArrayBuilder.Add(Tuple.Create(propP2.GetAttributes(), False))
propGetMethod = propP2.GetMethod
Assert.Equal(0, propGetMethod.GetAttributes().Length)
attributesArrayBuilder.Add(Tuple.Create(propGetMethod.GetReturnTypeAttributes(), False))
Dim propP3 = classZ.GetMember(Of PropertySymbol)("p3")
attributesArrayBuilder.Add(Tuple.Create(propP3.GetAttributes(), False))
propGetMethod = propP3.GetMethod
Assert.Equal(0, propGetMethod.GetAttributes().Length)
attributesArrayBuilder.Add(Tuple.Create(propGetMethod.GetReturnTypeAttributes(), False))
propSetMethod = propP3.SetMethod
Assert.Equal(0, propSetMethod.GetAttributes().Length)
Assert.Equal(0, propSetMethod.GetReturnTypeAttributes().Length)
Assert.Equal(0, propSetMethod.Parameters(0).GetAttributes().Length)
Dim eventE = classZ.GetMember(Of EventSymbol)("e")
attributesArrayBuilder.Add(Tuple.Create(eventE.GetAttributes(), False))
If isFromSource Then
Assert.Equal(0, eventE.AssociatedField.GetAttributes().Length)
Assert.Equal(0, eventE.AddMethod.GetAttributes().Length)
Assert.Equal(0, eventE.RemoveMethod.GetAttributes().Length)
Else
AssertEx.Equal({"CompilerGeneratedAttribute"}, GetAttributeNames(eventE.AddMethod.GetAttributes()))
AssertEx.Equal({"CompilerGeneratedAttribute"}, GetAttributeNames(eventE.RemoveMethod.GetAttributes()))
End If
Assert.Equal(0, eventE.AddMethod.GetReturnTypeAttributes().Length)
Assert.Equal(0, eventE.RemoveMethod.GetReturnTypeAttributes().Length)
Dim enumE = m.GlobalNamespace.GetTypeMember("E")
attributesArrayBuilder.Add(Tuple.Create(enumE.GetAttributes(), True))
Dim fieldA = enumE.GetMember(Of FieldSymbol)("A")
attributesArrayBuilder.Add(Tuple.Create(fieldA.GetAttributes(), True))
Dim structS = m.GlobalNamespace.GetTypeMember("S")
attributesArrayBuilder.Add(Tuple.Create(structS.GetAttributes(), True))
For Each tup In attributesArrayBuilder
' PreservedAppliedAttribute and OmittedAppliedAttribute have applied conditional attributes, such that
' (a) PreservedAppliedAttribute is conditionally applied to symbols
' (b) OmittedAppliedAttribute is conditionally NOT applied to symbols
' PreservedInheritedAttribute and OmittedInheritedAttribute have inherited conditional attributes, such that
' (a) PreservedInheritedAttribute is conditionally applied to symbols
' (b) OmittedInheritedAttribute is conditionally NOT applied to symbols
' PreservedMultipleAttribute and OmittedMultipleAttribute have multiple applied/inherited conditional attributes, such that
' (a) PreservedMultipleAttribute is conditionally applied to symbols
' (b) OmittedMultipleAttribute is conditionally NOT applied to symbols
' PartiallyPreservedAppliedAttribute has its conditional constant defined midway through the source file.
' Hence this attribute is emitted in metadata only for some symbols.
Dim attributesArray As ImmutableArray(Of VisualBasicAttributeData) = tup.Item1
Dim actualAttributeNames = GetAttributeNames(attributesArray)
If isFromSource Then
' All attributes should be present for source symbols
AssertEx.SetEqual({"PreservedAppliedAttribute",
"OmittedAppliedAttribute",
"PreservedInheritedAttribute",
"OmittedInheritedAttribute",
"PreservedMultipleAttribute",
"OmittedMultipleAttribute",
"PartiallyPreservedAppliedAttribute"}, actualAttributeNames)
Else
Dim hasPartiallyPreservedAppliedAttribute = tup.Item2
Dim expectedAttributeNames As String()
If Not hasPartiallyPreservedAppliedAttribute Then
' Only PreservedAppliedAttribute, PreservedInheritedAttribute, PreservedMultipleAttribute should be emitted in metadata
expectedAttributeNames = {"PreservedAppliedAttribute",
"PreservedInheritedAttribute",
"PreservedMultipleAttribute"}
Else
' PartiallyPreservedAppliedAttribute must also be emitted in metadata
expectedAttributeNames = {"PreservedAppliedAttribute",
"PreservedInheritedAttribute",
"PreservedMultipleAttribute",
"PartiallyPreservedAppliedAttribute"}
End If
AssertEx.SetEqual(expectedAttributeNames, actualAttributeNames)
End If
Next
attributesArrayBuilder.Free()
End Sub
Private Sub TestConditionAttributeType_SameSource(condDefs As String, preprocessorSymbols As ImmutableArray(Of KeyValuePair(Of String, Object)))
' Same source file
Debug.Assert(Not preprocessorSymbols.IsDefault)
Dim parseOpts = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbols)
Dim testSource As String = condDefs & s_commonTestSource_ConditionalAttrDefs & s_commonTestSource_ConditionalAttributesApplied
Dim compilation = CreateCompilationWithMscorlib40({Parse(testSource, parseOpts)}, options:=TestOptions.ReleaseExe)
CompileAndVerify(compilation, sourceSymbolValidator:=_commonValidatorForCondAttrType(True), symbolValidator:=_commonValidatorForCondAttrType(False), expectedOutput:="")
End Sub
Private Sub TestConditionAttributeType_SameSource(condDefs As String)
TestConditionAttributeType_SameSource(condDefs, ImmutableArray.Create(Of KeyValuePair(Of String, Object))())
End Sub
Private Sub TestConditionAttributeType_DifferentSource(condDefsSrcFile1 As String, condDefsSrcFile2 As String)
TestConditionAttributeType_DifferentSource(condDefsSrcFile1, ImmutableArray.Create(Of KeyValuePair(Of String, Object))(), condDefsSrcFile2, ImmutableArray.Create(Of KeyValuePair(Of String, Object))())
End Sub
Private Sub TestConditionAttributeType_DifferentSource(condDefsSrcFile1 As String,
preprocessorSymbolsSrcFile1 As ImmutableArray(Of KeyValuePair(Of String, Object)),
condDefsSrcFile2 As String,
preprocessorSymbolsSrcFile2 As ImmutableArray(Of KeyValuePair(Of String, Object)))
Dim source1 As String = condDefsSrcFile1 & s_commonTestSource_ConditionalAttrDefs
Dim source2 As String = condDefsSrcFile2 & <![CDATA[
Imports System
Imports System.Diagnostics
]]>.Value & s_commonTestSource_ConditionalAttributesApplied
Debug.Assert(Not preprocessorSymbolsSrcFile1.IsDefault)
Dim parseOpts1 = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbolsSrcFile1)
Debug.Assert(Not preprocessorSymbolsSrcFile2.IsDefault)
Dim parseOpts2 = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbolsSrcFile2)
' Different source files, same compilation
Dim comp = CreateCompilationWithMscorlib40({Parse(source1, parseOpts1), Parse(source2, parseOpts2)}, options:=TestOptions.ReleaseExe)
CompileAndVerify(comp, sourceSymbolValidator:=_commonValidatorForCondAttrType(True), symbolValidator:=_commonValidatorForCondAttrType(False), expectedOutput:="")
' Different source files, different compilation
Dim comp1 = CreateCompilationWithMscorlib40({Parse(source1, parseOpts1)}, options:=TestOptions.ReleaseDll)
Dim comp2 = VisualBasicCompilation.Create("comp2", {Parse(source2, parseOpts2)}, {MscorlibRef, New VisualBasicCompilationReference(comp1)}, options:=TestOptions.ReleaseExe)
CompileAndVerify(comp2, sourceSymbolValidator:=_commonValidatorForCondAttrType(True), symbolValidator:=_commonValidatorForCondAttrType(False), expectedOutput:="")
End Sub
#End Region
#Region "Tests"
<Fact>
Public Sub TestConditionAttributeType_01_SourceDefines()
Dim conditionalDefs As String = <![CDATA[
#Const cond1 = 1
#Const cond3 = ""
#Const cond6 = True
]]>.Value
TestConditionAttributeType_SameSource(conditionalDefs)
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond2 = 1
#Const cond5 = ""
#Const cond7 = True
]]>.Value
TestConditionAttributeType_DifferentSource(conditionalDefsDummy, conditionalDefs)
End Sub
<Fact>
Public Sub TestConditionAttributeType_01_CommandLineDefines()
Dim preprocessorSymbols = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond1", 1),
New KeyValuePair(Of String, Object)("cond3", ""),
New KeyValuePair(Of String, Object)("cond6", True))
TestConditionAttributeType_SameSource(condDefs:="", preprocessorSymbols:=preprocessorSymbols)
Dim preprocessorSymbolsDummy = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond2", 1),
New KeyValuePair(Of String, Object)("cond5", ""),
New KeyValuePair(Of String, Object)("cond7", True))
TestConditionAttributeType_DifferentSource(condDefsSrcFile1:="", preprocessorSymbolsSrcFile1:=preprocessorSymbolsDummy, condDefsSrcFile2:="", preprocessorSymbolsSrcFile2:=preprocessorSymbols)
End Sub
<Fact>
Public Sub TestConditionAttributeType_02_SourceDefines()
Dim conditionalDefs As String = <![CDATA[
#Const cond1 = 1
#Const cond2 = 1.0 ' Decimal type value is not considered for CC constants.
#Const cond3 = ""
#Const cond4 = True ' Conditional attributes are not inherited from base type.
#Const cond5 = 1
#Const cond5 = Nothing ' The last definition holds for CC constants.
#Const cond6 = True
#Const cond7 = 0 ' One of the conditional symbol is zero, but other conditional symbols for the attribute type are defined.
#Const cond8 = 2 ' Multiple conditional symbols defined.
]]>.Value
TestConditionAttributeType_SameSource(conditionalDefs)
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond2 = 1
#Const cond3_dummy = 0
#Const cond5 = ""
#Const cond7 = True
#Const cond8 = True
#Const cond9 = True
#Const cond10 = True
#Const cond11 = True
]]>.Value
TestConditionAttributeType_DifferentSource(conditionalDefsDummy, conditionalDefs)
End Sub
<Fact>
Public Sub TestConditionAttributeType_02_CommandLineDefines()
' Mix and match source and command line defines.
Dim preprocessorSymbols = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond1", 1),
New KeyValuePair(Of String, Object)("cond2", 1.0),
New KeyValuePair(Of String, Object)("cond3", ""),
New KeyValuePair(Of String, Object)("cond4", True),
New KeyValuePair(Of String, Object)("cond5", 1))
Dim conditionalDefs As String = <![CDATA[
#Const cond5 = Nothing ' Source definition for CC constants overrides command line /define definitions.
#Const cond6 = True ' Mix match source and command line defines.
#Const cond7 = 0 ' One of the conditional symbol is zero, but other conditional symbols for the attribute type are defined.
#Const cond8 = 2 ' Multiple conditional symbols defined.
]]>.Value
TestConditionAttributeType_SameSource(conditionalDefs, preprocessorSymbols:=preprocessorSymbols)
' Mix and match source and command line defines.
Dim preprocessorSymbolsDummy = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond2", 1),
New KeyValuePair(Of String, Object)("cond3_dummy", 1))
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond5 = ""
#Const cond7 = True
#Const cond8 = True
#Const cond9 = True
#Const cond10 = True
#Const cond11 = True
]]>.Value
TestConditionAttributeType_DifferentSource(conditionalDefsDummy, preprocessorSymbolsDummy, conditionalDefs, preprocessorSymbols)
End Sub
<Fact>
Public Sub TestNestedTypeMember()
Dim source =
<compilation>
<file name="a.vb"><![CDATA[
Imports System
Imports System.Diagnostics
<Conditional(Outer.Nested.ConstStr)> _
<Outer> _
Class Outer
Inherits Attribute
Public Class Nested
Public Const ConstStr As String = "str"
End Class
End Class
]]>
</file>
</compilation>
CompileAndVerify(source)
End Sub
#End Region
#End Region
#Region "Conditional Method tests"
#Region "Common Helpers"
Private Shared ReadOnly s_commonTestSource_ConditionalMethodDefs As String = <![CDATA[
Imports System
Imports System.Diagnostics
Public Class BaseZ
<Conditional("cond3_base")> _
Public Overridable Sub PreservedCalls_InheritedConditional_Method()
System.Console.WriteLine("BaseZ.PreservedCalls_InheritedConditional_Method")
End Sub
<Conditional("cond4_base")> _
Public Overridable Sub OmittedCalls_InheritedConditional_Method()
System.Console.WriteLine("BaseZ.OmittedCalls_InheritedConditional_Method")
End Sub
End Class
Public Interface I
' Conditional attributes are ignored for interface methods, but respected for implementing methods.
<Conditional("dummy")>
Sub PartiallyPreservedCalls_Interface_Method()
End Interface
Public Class Z
Inherits BaseZ
Implements I
<Conditional("cond1")> _
Public Sub PreservedCalls_AppliedConditional_Method()
System.Console.WriteLine("Z.PreservedCalls_AppliedConditional_Method")
End Sub
<Conditional("cond2")> _
Public Sub OmittedCalls_AppliedConditional_Method()
System.Console.WriteLine("Z.OmittedCalls_AppliedConditional_Method")
End Sub
' Conditional symbols are not inherited by overriding methods in VB
<Conditional("cond3")> _
Public Overrides Sub PreservedCalls_InheritedConditional_Method()
System.Console.WriteLine("Z.PreservedCalls_InheritedConditional_Method")
End Sub
#Const cond4_base = "Conditional symbols are not inherited by overriding methods in VB"
<Conditional("cond4")> _
Public Overrides Sub OmittedCalls_InheritedConditional_Method()
System.Console.WriteLine("Z.OmittedCalls_InheritedConditional_Method")
End Sub
<Conditional("cond5"), Conditional("cond6")> _
Public Sub PreservedCalls_MultipleConditional_Method()
System.Console.WriteLine("Z.PreservedCalls_MultipleConditional_Method")
End Sub
<Conditional("cond7"), Conditional("cond8")> _
Public Sub OmittedCalls_MultipleConditional_Method()
System.Console.WriteLine("Z.OmittedCalls_MultipleConditional_Method")
End Sub
' Conditional attributes are ignored for interface methods, but respected for implementing methods.
<Conditional("cond9")>
Public Sub PartiallyPreservedCalls_Interface_Method() Implements I.PartiallyPreservedCalls_Interface_Method
System.Console.WriteLine("Z.PartiallyPreservedCalls_Interface_Method")
End Sub
' Conditional attributes are ignored for functions
<Conditional("cond10")>
Public Function PreservedCalls_Function() As Integer
System.Console.WriteLine("Z.PreservedCalls_Function")
Return 0
End Function
<Conditional(""), Conditional(Nothing)> _
Public Sub OmittedCalls_AlwaysFalseConditional_Method()
System.Console.WriteLine("Z.OmittedCalls_AlwaysFalseConditional_Method")
End Sub
<Conditional("condForPartiallyPreservedAppliedAttribute")>
Public Sub PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(i As Integer)
System.Console.WriteLine("Z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method" & i)
End Sub
End Class
]]>.Value
Private Shared ReadOnly s_commonTestSource_ConditionalMethodCalls As String = <![CDATA[
Module Module1
Public Sub Main()
Dim z = New Z()
z.PreservedCalls_AppliedConditional_Method()
z.OmittedCalls_AppliedConditional_Method()
z.PreservedCalls_InheritedConditional_Method()
z.OmittedCalls_InheritedConditional_Method()
z.PreservedCalls_MultipleConditional_Method()
z.OmittedCalls_MultipleConditional_Method()
z.OmittedCalls_AlwaysFalseConditional_Method()
z.PartiallyPreservedCalls_Interface_Method() ' Omitted
DirectCast(z, I).PartiallyPreservedCalls_Interface_Method() ' Preserved
Console.WriteLine(z.PreservedCalls_Function())
' Second and fourth calls are preserved, first, third and fifth calls are omitted.
z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(1)
# Const condForPartiallyPreservedAppliedAttribute = True
z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(2)
# Const condForPartiallyPreservedAppliedAttribute = 0
z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(3)
# Const condForPartiallyPreservedAppliedAttribute = "TrueAgain"
z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(4)
# Const condForPartiallyPreservedAppliedAttribute = Nothing
z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method(5)
End Sub
End Module
]]>.Value
Private Shared ReadOnly s_commonExpectedOutput_ConditionalMethodsTest As String =
"Z.PreservedCalls_AppliedConditional_Method" & Environment.NewLine &
"Z.PreservedCalls_InheritedConditional_Method" & Environment.NewLine &
"Z.PreservedCalls_MultipleConditional_Method" & Environment.NewLine &
"Z.PartiallyPreservedCalls_Interface_Method" & Environment.NewLine &
"Z.PreservedCalls_Function" & Environment.NewLine &
"0" & Environment.NewLine &
"Z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method2" & Environment.NewLine &
"Z.PartiallyPreservedCalls_PartiallyPreservedAppliedAttribute_Method4" & Environment.NewLine
Private Sub TestConditionalMethod_SameSource(condDefs As String)
TestConditionalMethod_SameSource(condDefs, ImmutableArray.Create(Of KeyValuePair(Of String, Object))())
End Sub
Private Sub TestConditionalMethod_SameSource(condDefs As String, preprocessorSymbols As ImmutableArray(Of KeyValuePair(Of String, Object)))
' Same source file
Debug.Assert(Not preprocessorSymbols.IsDefault)
Dim parseOpts = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbols)
Dim testSource As String = condDefs & s_commonTestSource_ConditionalMethodDefs & s_commonTestSource_ConditionalMethodCalls
Dim comp = VisualBasicCompilation.Create(GetUniqueName(), {Parse(testSource, parseOpts)}, {MscorlibRef, SystemCoreRef, MsvbRef})
CompileAndVerify(comp, expectedOutput:=s_commonExpectedOutput_ConditionalMethodsTest)
End Sub
Private Sub TestConditionalMethod_DifferentSource(condDefsSrcFile1 As String, condDefsSrcFile2 As String)
TestConditionalMethod_DifferentSource(condDefsSrcFile1, ImmutableArray.Create(Of KeyValuePair(Of String, Object))(), condDefsSrcFile2, ImmutableArray.Create(Of KeyValuePair(Of String, Object))())
End Sub
Private Sub TestConditionalMethod_DifferentSource(condDefsSrcFile1 As String,
preprocessorSymbolsSrcFile1 As ImmutableArray(Of KeyValuePair(Of String, Object)),
condDefsSrcFile2 As String,
preprocessorSymbolsSrcFile2 As ImmutableArray(Of KeyValuePair(Of String, Object)))
Dim source1 As String = condDefsSrcFile1 & s_commonTestSource_ConditionalMethodDefs
Dim source2 As String = condDefsSrcFile2 & <![CDATA[
Imports System
Imports System.Diagnostics
]]>.Value & s_commonTestSource_ConditionalMethodCalls
Debug.Assert(Not preprocessorSymbolsSrcFile1.IsDefault)
Dim parseOpts1 = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbolsSrcFile1)
Debug.Assert(Not preprocessorSymbolsSrcFile2.IsDefault)
Dim parseOpts2 = VisualBasicParseOptions.Default.WithPreprocessorSymbols(preprocessorSymbolsSrcFile2)
' Different source files, same compilation
Dim comp = VisualBasicCompilation.Create(GetUniqueName(), {Parse(source1, parseOpts1), Parse(source2, parseOpts2)}, {MscorlibRef, MsvbRef}, TestOptions.ReleaseExe)
CompileAndVerify(comp, expectedOutput:=s_commonExpectedOutput_ConditionalMethodsTest)
' Different source files, different compilation
Dim comp1 = VisualBasicCompilation.Create(GetUniqueName(), {Parse(source1, parseOpts1)}, {MscorlibRef, MsvbRef}, TestOptions.ReleaseDll)
Dim comp2 = VisualBasicCompilation.Create(GetUniqueName(), {Parse(source2, parseOpts2)}, {MscorlibRef, MsvbRef, comp1.ToMetadataReference()}, TestOptions.ReleaseExe)
CompileAndVerify(comp2, expectedOutput:=s_commonExpectedOutput_ConditionalMethodsTest)
End Sub
#End Region
#Region "Tests"
<Fact>
Public Sub TestConditionalMethod_01_SourceDefines()
Dim conditionalDefs As String = <![CDATA[
#Const cond1 = 1
#Const cond3 = ""
#Const cond5 = True
]]>.Value
TestConditionalMethod_SameSource(conditionalDefs)
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond2 = 1
#Const cond5 = ""
#Const cond7 = True
]]>.Value
TestConditionalMethod_DifferentSource(conditionalDefsDummy, conditionalDefs)
End Sub
<Fact>
Public Sub TestConditionalMethod_01_CommandLineDefines()
Dim preprocessorSymbols = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond1", 1),
New KeyValuePair(Of String, Object)("cond3", ""),
New KeyValuePair(Of String, Object)("cond5", True))
TestConditionalMethod_SameSource(condDefs:="", preprocessorSymbols:=preprocessorSymbols)
Dim preprocessorSymbolsDummy = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond2", 1),
New KeyValuePair(Of String, Object)("cond5", ""),
New KeyValuePair(Of String, Object)("cond7", True))
TestConditionalMethod_DifferentSource(condDefsSrcFile1:="", preprocessorSymbolsSrcFile1:=preprocessorSymbolsDummy, condDefsSrcFile2:="", preprocessorSymbolsSrcFile2:=preprocessorSymbols)
End Sub
<Fact>
Public Sub TestConditionalMethod_02_SourceDefines()
Dim conditionalDefs As String = <![CDATA[
#Const cond1 = 1
#Const cond2 = 1.0 ' Decimal type value is not considered for CC constants.
#Const cond3 = ""
#Const cond4_base = True ' Conditional attributes are not inherited from base type.
#Const cond5 = 1
#Const cond5 = 0 ' One of the conditional symbol is zero, but other conditional symbols for the attribute type are defined.
#Const cond6 = True
#Const cond7 = 0
#Const cond3 = True ' The last definition holds for CC constants.
]]>.Value
TestConditionalMethod_SameSource(conditionalDefs)
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond2 = 1
#Const cond3_dummy = 0
#Const cond5 = ""
#Const cond7 = True
#Const cond8 = True
#Const cond9 = True
#Const cond10 = True
#Const cond11 = True
]]>.Value
TestConditionalMethod_DifferentSource(conditionalDefsDummy, conditionalDefs)
End Sub
<Fact>
Public Sub TestConditionalMethod_02_CommandLineDefines()
' Mix and match source and command line defines.
Dim preprocessorSymbols = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond1", 1),
New KeyValuePair(Of String, Object)("cond2", 1.0),
New KeyValuePair(Of String, Object)("cond3", ""),
New KeyValuePair(Of String, Object)("cond4_base", True),
New KeyValuePair(Of String, Object)("cond5", 1))
Dim conditionalDefs As String = <![CDATA[
#Const cond5 = 0 ' One of the conditional symbol is zero, but other conditional symbols for the attribute type are defined.
#Const cond6 = True
#Const cond7 = 0
#Const cond3 = True ' The last definition holds for CC constants.
]]>.Value
TestConditionalMethod_SameSource(conditionalDefs, preprocessorSymbols)
' Mix and match source and command line defines.
Dim preprocessorSymbolsDummy = ImmutableArray.Create(Of KeyValuePair(Of String, Object))(New KeyValuePair(Of String, Object)("cond2", 1),
New KeyValuePair(Of String, Object)("cond3_dummy", 0),
New KeyValuePair(Of String, Object)("cond5", True))
Dim conditionalDefsDummy As String = <![CDATA[
#Const cond7 = True
#Const cond8 = True
#Const cond9 = True
#Const cond10 = True
#Const cond11 = True
]]>.Value
TestConditionalMethod_DifferentSource(conditionalDefsDummy, preprocessorSymbolsDummy, conditionalDefs, preprocessorSymbols)
End Sub
<WorkItem(546089, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546089")>
<Fact>
Public Sub CaseInsensitivityTest()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Module Test
<System.Diagnostics.Conditional("VAR4")>
Sub Sub1()
Console.WriteLine("Sub1 Called")
End Sub
Sub Main()
#Const var4 = True
Sub1()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(source, expectedOutput:=<![CDATA[Sub1 Called]]>)
End Sub
<WorkItem(546089, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546089")>
<Fact>
Public Sub CaseInsensitivityTest_02()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Module Test
<System.Diagnostics.Conditional("VAR4")>
Sub Sub1()
Console.WriteLine("Sub1 Called")
End Sub
#Const VAR4 = False
Sub Main()
#Const var4 = True
Sub1()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(source, expectedOutput:=<![CDATA[Sub1 Called]]>)
End Sub
<WorkItem(546094, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546094")>
<Fact>
Public Sub ConditionalAttributeOnPropertySetter()
Dim source =
<compilation>
<file name="a.vb">
Imports System
Class TestClass
WriteOnly Property goo() As String
<Diagnostics.Conditional("N")>
Set(ByVal Value As String)
Console.WriteLine("Property Called")
End Set
End Property
End Class
Module M1
Sub Main()
Dim t As New TestClass()
t.goo = "abds"
End Sub
End Module
</file>
</compilation>
CompileAndVerify(source, expectedOutput:=<![CDATA[Property Called]]>)
End Sub
#End Region
<WorkItem(1003274, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1003274")>
<Fact>
Public Sub ConditionalAttributeInNetModule()
Const source = "
Imports System.Diagnostics
Class C
Sub M()
N1()
N2()
End Sub
<Conditional(""Defined"")>
Sub N1()
End Sub
<Conditional(""Undefined"")>
Sub N2()
End Sub
End Class
"
Dim parseOptions As New VisualBasicParseOptions(preprocessorSymbols:={New KeyValuePair(Of String, Object)("Defined", True)})
Dim comp = CreateCompilationWithMscorlib40({VisualBasicSyntaxTree.ParseText(source, parseOptions)}, options:=TestOptions.ReleaseModule)
CompileAndVerify(comp, verify:=Verification.Fails).VerifyIL("C.M", "
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""Sub C.N1()""
IL_0006: ret
}
")
End Sub
#End Region
End Class
End Namespace
|