File: SymbolsTests\Metadata\PE\NoPiaLocalHideAndTypeSubstitutionTests.vb
Web Access
Project: src\src\Compilers\VisualBasic\Test\Symbol\Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.Symbol.UnitTests)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Roslyn.Test.Utilities
Imports System.Collections.Immutable
Imports System.Runtime.CompilerServices
 
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE
 
    Public Class NoPiaLocalHideAndTypeSubstitutionTests
        Inherits BasicTestBase
 
        <Fact>
        Public Sub NoPiaTypeEquivalenceBetweenPIATypeInExternalAndLocalAssembly()
            ' Verify type equivalence between PIA type in external assembly and local assembly
            Dim localConsumerCompilationDef =
<compilation name="Dummy">
    <file name="Dummy.vb">
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateCompilationWithMscorlib40(localConsumerCompilationDef)
            localConsumer = localConsumer.AddReferences(TestReferences.SymbolsTests.NoPia.Pia1, TestReferences.SymbolsTests.NoPia.LocalTypes1)
 
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Assert.Equal(1, localConsumerRefsAsm.First(Function(arg) arg.Name = "LocalTypes1").Modules.FirstOrDefault().GetReferencedAssemblies().Length)
            Assert.Equal(1, localConsumerRefsAsm.First(Function(arg) arg.Name = "LocalTypes1").Modules.FirstOrDefault().GetReferencedAssemblySymbols().Length)
            Assert.Equal(localConsumerRefsAsm.First(Function(arg) arg.Name = "mscorlib"), localConsumerRefsAsm.First(Function(arg) arg.Name = "LocalTypes1").Modules.FirstOrDefault().GetReferencedAssemblySymbols().ElementAt(0))
            Dim canonicalType1 = localConsumerRefsAsm.First(Function(arg) arg.Name = "Pia1").GlobalNamespace.GetTypeMembers("I1").[Single]()
            Dim canonicalType2 = localConsumerRefsAsm.First(Function(arg) arg.Name = "Pia1").GlobalNamespace.GetMembers("NS1").OfType(Of NamespaceSymbol)().[Single]().GetTypeMembers("I2").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "LocalTypes1").GlobalNamespace.GetTypeMembers("LocalTypes1").[Single]()
            Dim methodSymbol As MethodSymbol = classLocalType.GetMembers("Test1").OfType(Of MethodSymbol)().[Single]()
            Dim param As ImmutableArray(Of ParameterSymbol) = methodSymbol.Parameters
            Assert.Same(canonicalType1, param.[Where](Function(arg) arg.[Type].Name = "I1").[Select](Function(arg) arg).[Single]().[Type])
            Assert.Same(canonicalType2, param.[Where](Function(arg) arg.[Type].Name = "I2").[Select](Function(arg) arg).[Single]().[Type])
        End Sub
 
        <Fact>
        Public Sub NoPIALocalTypesEquivalentToEachOtherStructAsMethodParameterType()
            'Structure - As method parameter type in external assembly (test this by passing the parameter with a variable which was declared in the current assembly)
 
            Dim compilationDef =
<compilation name="Dummy">
    <file name="Dummy.vb">
Module TypeSubstitution
 
    Dim myOwnVar As FooStruct = Nothing
 
    public Sub Main()
        myOwnVar = new FooStruct()
        myOwnVar.Structure = -1
        ExternalAsm1.Scen1(myOwnVar)
    End Sub
End Module
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateEmptyCompilationWithReferences(
                                    compilationDef,
                                    {TestReferences.SymbolsTests.NoPia.GeneralPia,
                                     TestReferences.SymbolsTests.NoPia.ExternalAsm1})
 
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Assert.Equal(3, localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").Modules.FirstOrDefault().GetReferencedAssemblies().Length)
            Assert.Equal(3, localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").Modules.FirstOrDefault().GetReferencedAssemblySymbols().Length)
            Dim canonicalType = localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").GlobalNamespace.GetTypeMembers("FooStruct").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumer.GlobalNamespace.GetTypeMembers("TypeSubstitution").[Single]()
            Dim localFieldSymbol As FieldSymbol = classLocalType.GetMembers("myOwnVar").OfType(Of FieldSymbol)().[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("ExternalAsm1").[Single]()
            Dim refMethodSymbol As MethodSymbol = classRefLocalType.GetMembers("Scen1").OfType(Of MethodSymbol)().[Single]()
            Dim param As ImmutableArray(Of ParameterSymbol) = refMethodSymbol.Parameters
            Dim missing As NoPiaMissingCanonicalTypeSymbol = DirectCast(param.First().[Type], NoPiaMissingCanonicalTypeSymbol)
            Assert.Same(localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1"), missing.EmbeddingAssembly)
            Assert.Null(missing.Guid)
            Assert.Equal(canonicalType.ToTestDisplayString(), missing.FullTypeName)
            Assert.Equal("f9c2d51d-4f44-45f0-9eda-c9d599b58257", missing.Scope)
            Assert.Equal(canonicalType.ToTestDisplayString(), missing.Identifier)
            Assert.Same(canonicalType, localFieldSymbol.[Type])
            Assert.IsType(Of NoPiaMissingCanonicalTypeSymbol)(param(0).[Type])
        End Sub
 
        <Fact>
        Public Sub NoPIALocalTypesEquivalentToEachOtherInterfaceAsMethodParameterType()
            'Same as previous scenario but with Interface
 
            Dim compilationDef =
<compilation name="Dummy">
    <file name="Dummy.vb">
class ICBase 
 Inherits InheritanceConflict.IBase
 
    public Function Bar() As Integer
        return -2
    End Function
 
    public Sub ConflictMethod(x As Integer)
    End Sub
 
    public Sub Foo()
    End Sub
 
    'public string this[object x]
    '{
    '    get { return null; }
    '    set { }
    '}
End Class
 
Module TypeSubstitution
 
    Dim myOwnRef As InheritanceConflict.IBase =Nothing
    public Sub Main()
        myOwnRef = new ICBase()
        ExternalAsm1.Scen2(myOwnRef)
    End Sub
End Module
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateEmptyCompilationWithReferences(compilationDef,
                                                                                 {TestReferences.SymbolsTests.NoPia.GeneralPia,
                                                                                  TestReferences.SymbolsTests.NoPia.ExternalAsm1})
 
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Dim canonicalType = localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").GlobalNamespace.ChildNamespace("InheritanceConflict")
            Dim canonicalTypeInter = canonicalType.GetTypeMembers("IBase").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumer.GlobalNamespace.GetTypeMembers("TypeSubstitution").[Single]()
            Dim localFieldSymbol As FieldSymbol = classLocalType.GetMembers("myOwnRef").OfType(Of FieldSymbol)().[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("ExternalAsm1").[Single]()
            Dim refMethodSymbol As MethodSymbol = classRefLocalType.GetMembers("Scen2").OfType(Of MethodSymbol)().[Single]()
            Dim param As ImmutableArray(Of ParameterSymbol) = refMethodSymbol.Parameters
            Assert.Same(canonicalTypeInter, localFieldSymbol.[Type])
            Assert.Same(canonicalTypeInter, param.First().[Type])
            Assert.IsAssignableFrom(GetType(VisualBasic.Symbols.Metadata.PE.PENamedTypeSymbol), param.First().[Type])
        End Sub
 
        <Fact>
        Public Sub NoPIALocalTypesEquivalentToEachOtherEnumAsReturnTypeInExternalAssembly()
            'Enum - As return type in external assembly
 
            Dim compilationDef =
<compilation name="Dummy">
    <file name="Dummy.vb">
Module TypeSubstitution
 
    Dim myLocalType As FooEnum = 0
 
    public Sub Main()
       FooEnum myLocalType = 0
       myLocalType = ExternalAsm1.Scen3(5)
    End Sub
End Module
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateEmptyCompilationWithReferences(compilationDef,
                                                                                 {TestReferences.SymbolsTests.NoPia.GeneralPia,
                                                                                  TestReferences.SymbolsTests.NoPia.ExternalAsm1})
 
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Dim canonicalType = localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").GlobalNamespace.GetTypeMembers("FooEnum").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumer.GlobalNamespace.GetTypeMembers("TypeSubstitution").[Single]()
            Dim localFieldSymbol As FieldSymbol = classLocalType.GetMembers("myLocalType").OfType(Of FieldSymbol)().[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("ExternalAsm1").[Single]()
            Dim methodSymbol As MethodSymbol = classRefLocalType.GetMembers("Scen3").OfType(Of MethodSymbol)().[Single]()
            Dim missing As NoPiaMissingCanonicalTypeSymbol = DirectCast(methodSymbol.ReturnType, NoPiaMissingCanonicalTypeSymbol)
            Assert.Same(localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1"), missing.EmbeddingAssembly)
            Assert.Null(missing.Guid)
            Assert.Equal(canonicalType.ToTestDisplayString(), missing.FullTypeName)
            Assert.Equal("f9c2d51d-4f44-45f0-9eda-c9d599b58257", missing.Scope)
            Assert.Equal(canonicalType.ToTestDisplayString(), missing.Identifier)
            Assert.Same(canonicalType, localFieldSymbol.[Type])
            Assert.IsType(Of NoPiaMissingCanonicalTypeSymbol)(methodSymbol.ReturnType)
        End Sub
 
        <Fact>
        <WorkItem(531054, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems?_a=edit&id=531054")>
        Public Sub NoPIALocalTypesEquivalentToEachOtherInterfaceAsReturnTypeInExternalAssembly()
            ' Interface - As property in external assembly
            Dim localTypeSource =
<compilation><file>
class TypeSubstitution
    Dim myLocalType As ISubFuncProp = ExternalAsm1.Scen4
End Class
</file></compilation>
            Dim localConsumer = CreateEmptyCompilationWithReferences(localTypeSource, references:={TestReferences.SymbolsTests.NoPia.GeneralPia, TestReferences.SymbolsTests.NoPia.ExternalAsm1})
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Dim canonicalType = localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").GlobalNamespace.GetTypeMembers("ISubFuncProp").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumer.GlobalNamespace.GetTypeMembers("TypeSubstitution").[Single]()
            Dim localFieldSymbol As FieldSymbol = classLocalType.GetMembers("myLocalType").OfType(Of FieldSymbol)().[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("ExternalAsm1").[Single]()
            Dim propertySymbol = classRefLocalType.GetMembers("Scen4").OfType(Of PropertySymbol)().[Single]()
            Dim propertyType = propertySymbol.Type
            Assert.Equal(canonicalType.ToTestDisplayString(), propertyType.Name)
            Assert.Same(canonicalType, localFieldSymbol.[Type])
            Assert.IsAssignableFrom(Of VisualBasic.Symbols.Metadata.PE.PENamedTypeSymbol)(propertySymbol.Type)
        End Sub
 
        <Fact>
        <WorkItem(531054, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems?_a=edit&id=531054")>
        Public Sub NoPIALocalTypesEquivalentToEachOtherDelegateAsReturnTypeInExternalAssembly()
            'Same as previous scenario but with Delegate
            Dim localTypeSource =
<compilation><file>
class TypeSubstitution
    Dim myLocalType As GeneralEventScenario.EventHandler = ExternalAsm1.Scen5
End Class 
</file></compilation>
            Dim localConsumer = CreateEmptyCompilationWithReferences(localTypeSource, references:={TestReferences.SymbolsTests.NoPia.GeneralPia, TestReferences.SymbolsTests.NoPia.ExternalAsm1})
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Dim canonicalType = localConsumerRefsAsm(0).GlobalNamespace.ChildNamespace("GeneralEventScenario")
            Dim canonicalTypeInter = canonicalType.GetTypeMembers("EventHandler").[Single]()
            Dim classLocalType As NamedTypeSymbol = localConsumer.GlobalNamespace.GetTypeMembers("TypeSubstitution").[Single]()
            Dim localFieldSymbol As FieldSymbol = classLocalType.GetMembers("myLocalType").OfType(Of FieldSymbol)().[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("ExternalAsm1").[Single]()
            Dim propertySymbol = classRefLocalType.GetMembers("Scen5").OfType(Of PropertySymbol)().[Single]()
            Dim missing As NoPiaMissingCanonicalTypeSymbol = DirectCast(propertySymbol.Type, NoPiaMissingCanonicalTypeSymbol)
            Assert.Same(localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1"), missing.EmbeddingAssembly)
            Assert.Null(missing.Guid)
            Assert.Equal("f9c2d51d-4f44-45f0-9eda-c9d599b58257", missing.Scope)
            Assert.Equal("GeneralEventScenario.EventHandler", missing.Identifier)
            Assert.Same(canonicalTypeInter, localFieldSymbol.[Type])
            Assert.IsType(Of NoPiaMissingCanonicalTypeSymbol)(propertySymbol.Type)
        End Sub
 
        <Fact>
        Public Sub NoPIATypeSubstitutionForClassThatImplementNoPiaInterface()
            'Check type substitution when a class implement a PIA interface
            Dim compilationDef =
<compilation name="Dummy">
    <file name="Dummy.vb">
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateEmptyCompilationWithReferences(compilationDef,
                {TestReferences.SymbolsTests.NoPia.GeneralPia, TestReferences.SymbolsTests.NoPia.ExternalAsm1})
 
            Dim localConsumerRefsAsm = localConsumer.[Assembly].GetNoPiaResolutionAssemblies()
            Dim canonicalType = localConsumerRefsAsm.First(Function(arg) arg.Name = "GeneralPia").GlobalNamespace.GetTypeMembers("ISubFuncProp").[Single]()
            Dim classRefLocalType As NamedTypeSymbol = localConsumerRefsAsm.First(Function(arg) arg.Name = "ExternalAsm1").GlobalNamespace.GetTypeMembers("SubFuncProp").[Single]()
            Dim methodSymbol As MethodSymbol = classRefLocalType.GetMembers("Foo").OfType(Of MethodSymbol)().[Single]()
            Dim interfaceType = classRefLocalType.Interfaces.First()
            Assert.Same(canonicalType, interfaceType)
            Assert.IsType(Of VisualBasic.Symbols.Metadata.PE.PENamedTypeSymbol)(interfaceType)
        End Sub
 
        <Fact>
        Public Sub NoPiaTypeSubstitutionWithHandAuthoredLocalType()
            ' Try to apply attributes to the local type that indicates that the type is intended to be used for type equivalence. 
            Dim compilationDef1 =
<compilation name="Dummy1">
    <file><![CDATA[
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices

Public Class LocalTypes1
    Public Function Test1() As I1
        Return Nothing
    End Function
End Class

<ComImport, Guid("27E3e649-994b-4F58-b3c6-f8089a5f2c01"), TypeIdentifier, CompilerGenerated, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface I1
End Interface
    ]]></file>
</compilation>
 
            Dim localType = CreateCompilationWithMscorlib40(compilationDef1)
 
            Dim compilationDef2 =
<compilation name="Dummy2">
    <file>
    </file>
</compilation>
 
            Dim localConsumer = CompilationUtils.CreateEmptyCompilationWithReferences(compilationDef2,
                {TestReferences.SymbolsTests.NoPia.Pia1, New VisualBasicCompilationReference(localType)})
 
            Dim localConsumerRefsAsm = localConsumer.Assembly.GetNoPiaResolutionAssemblies()
            Dim importedTypeComp2 = localConsumerRefsAsm.First(Function(arg) arg.Name = "Dummy1").GlobalNamespace.GetTypeMembers("LocalTypes1").Single()
            Dim embeddedType = importedTypeComp2.GetMembers("Test1").OfType(Of MethodSymbol)().Single()
            Dim importedTypeAsm = localConsumerRefsAsm.First(Function(arg) arg.Name = "Pia1").GlobalNamespace.GetTypeMembers("I1").Single()
 
            Assert.Same(embeddedType.ReturnType, importedTypeAsm)
            Assert.Equal(SymbolKind.NamedType, embeddedType.ReturnType.Kind)
        End Sub
 
    End Class
 
    Friend Module Extensions
 
        <Extension()>
        Public Function ChildNamespace(ns As NamespaceSymbol, name As String) As NamespaceSymbol
            Return ns.GetMembers().AsEnumerable().
                Where(Function(n) n.Name.Equals(name)).
                       Cast(Of NamespaceSymbol)().
                       Single()
        End Function
    End Module
 
End Namespace