/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Test/Emit/Attributes/AttributeTests_Conditional.vb
806 строк
40 KB
Tomáš Matoušek
Refactoring of extension methods in source packages (#78620) - take 2 (#78894)
26 июн 2025, 18:42
Не верифицирован
26 июн 2025, 18:42
05fc006
Код
Авторство
О чём код?
' 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.Reflection Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Roslyn.Test.Utilities 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