File: Symbols\AssemblySymbol.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.Concurrent
Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.Collections
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Symbols
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
 
    ''' <summary>
    ''' Represents a .NET assembly. An assembly consists of one or more modules.
    ''' </summary>
    Friend MustInherit Class AssemblySymbol
        Inherits Symbol
        Implements IAssemblySymbol, IAssemblySymbolInternal
 
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        ' Changes to the public interface of this class should remain synchronized with the C# version of Symbol.
        ' Do not make any changes to the public interface without making the corresponding change
        ' to the C# version.
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
        ''' <summary>
        ''' The system assembly, which provides primitive types like Object, String, etc., e.g. mscorlib.dll. 
        ''' The value is provided by ReferenceManager and must not be modified. For SourceAssemblySymbol, non-missing 
        ''' coreLibrary must match one of the referenced assemblies returned by GetReferencedAssemblySymbols() method of 
        ''' the main module. If there is no existing assembly that can be used as a source for the primitive types, 
        ''' the value is a Compilation.MissingCorLibrary. 
        ''' </summary>
        Private _corLibrary As AssemblySymbol
 
        ''' <summary>
        ''' The system assembly, which provides primitive types like Object, String, etc., e.g. mscorlib.dll. 
        ''' The value is a MissingAssemblySymbol if none of the referenced assemblies can be used as a source for the 
        ''' primitive types and the owning assembly cannot be used as the source too. Otherwise, it is one of 
        ''' the referenced assemblies returned by GetReferencedAssemblySymbols() method or the owning assembly.
        ''' </summary>
        Friend ReadOnly Property CorLibrary As AssemblySymbol
            Get
                Return _corLibrary
            End Get
        End Property
 
        Private ReadOnly Property IAssemblySymbolInternal_CorLibrary As IAssemblySymbolInternal Implements IAssemblySymbolInternal.CorLibrary
            Get
                Return CorLibrary
            End Get
        End Property
 
        ''' <summary>
        ''' A helper method for ReferenceManager to set the system assembly, which provides primitive 
        ''' types like Object, String, etc., e.g. mscorlib.dll. 
        ''' </summary>
        ''' <param name="corLibrary"></param>
        Friend Sub SetCorLibrary(corLibrary As AssemblySymbol)
            Debug.Assert(_corLibrary Is Nothing)
            _corLibrary = corLibrary
        End Sub
 
        ''' <summary>
        ''' Simple name of the assembly. 
        ''' </summary>
        ''' <remarks>
        ''' This is equivalent to <see cref="Identity"/>.<see cref="AssemblyIdentity.Name"/>, but may be 
        ''' much faster to retrieve for source code assemblies, since it does not require binding the assembly-level
        ''' attributes that contain the version number and other assembly information.
        ''' </remarks>
        Public Overrides ReadOnly Property Name As String
            Get
                Return Identity.Name
            End Get
        End Property
 
        ''' <summary>
        ''' True if the assembly contains interactive code.
        ''' </summary>
        Public Overridable ReadOnly Property IsInteractive As Boolean Implements IAssemblySymbol.IsInteractive
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' If this symbol represents a metadata assembly returns the underlying <see cref="AssemblyMetadata"/>.
        ''' 
        ''' Otherwise, this returns <see langword="Nothing"/>.
        ''' </summary>
        Public MustOverride Function GetMetadata() As AssemblyMetadata Implements IAssemblySymbol.GetMetadata
 
        ''' <summary>
        ''' Get the name of this assembly.
        ''' </summary>
        Public MustOverride ReadOnly Property Identity As AssemblyIdentity Implements IAssemblySymbol.Identity, IAssemblySymbolInternal.Identity
 
        Public MustOverride ReadOnly Property AssemblyVersionPattern As Version Implements IAssemblySymbolInternal.AssemblyVersionPattern
 
        ''' <summary>
        ''' Target architecture of the machine.
        ''' </summary>
        Friend ReadOnly Property Machine As System.Reflection.PortableExecutable.Machine
            Get
                Return Modules(0).Machine
            End Get
        End Property
 
        ''' <summary>
        ''' Indicates that this PE file makes Win32 calls. See CorPEKind.pe32BitRequired for more information (http://msdn.microsoft.com/en-us/library/ms230275.aspx).
        ''' </summary>
        Friend ReadOnly Property Bit32Required As Boolean
            Get
                Return Modules(0).Bit32Required
            End Get
        End Property
 
        ''' <summary>
        ''' Gets a read-only list of all the modules in this assembly. (There must be at least one.) The first one is the main module
        ''' that holds the assembly manifest.
        ''' </summary>
        Public MustOverride ReadOnly Property Modules As ImmutableArray(Of ModuleSymbol)
 
        ''' <summary>
        ''' Gets the merged root namespace that contains all namespaces and types defined in the modules
        ''' of this assembly. If there is just one module in this assembly, this property just returns the 
        ''' GlobalNamespace of that module.
        ''' </summary>
        Public MustOverride ReadOnly Property GlobalNamespace As NamespaceSymbol
 
        ''' <summary>
        ''' Given a namespace symbol, returns the corresponding assembly specific namespace symbol
        ''' </summary>
        Friend Function GetAssemblyNamespace(namespaceSymbol As NamespaceSymbol) As NamespaceSymbol
            If namespaceSymbol.IsGlobalNamespace Then
                Return Me.GlobalNamespace
            End If
 
            Dim container As NamespaceSymbol = namespaceSymbol.ContainingNamespace
 
            If container Is Nothing Then
                Return Me.GlobalNamespace
            End If
 
            If namespaceSymbol.Extent.Kind = NamespaceKind.Assembly AndAlso namespaceSymbol.ContainingAssembly = Me Then
                Return namespaceSymbol
            End If
 
            Dim assemblyContainer As NamespaceSymbol = GetAssemblyNamespace(container)
 
            If assemblyContainer Is container Then
                ' Trivial case, container isn't merged.
                Return namespaceSymbol
            End If
 
            If assemblyContainer Is Nothing Then
                Return Nothing
            End If
 
            Return assemblyContainer.GetNestedNamespace(namespaceSymbol.Name)
        End Function
 
        Public NotOverridable Overrides ReadOnly Property Kind As SymbolKind
            Get
                Return SymbolKind.Assembly
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property ContainingAssembly As AssemblySymbol
            Get
                Return Nothing
            End Get
        End Property
 
        Friend Overrides Function Accept(Of TArgument, TResult)(visitor As VisualBasicSymbolVisitor(Of TArgument, TResult), arg As TArgument) As TResult
            Return visitor.VisitAssembly(Me, arg)
        End Function
 
        Friend Sub New()
            ' Only the compiler can create AssemblySymbols.
        End Sub
 
        ''' <summary>
        ''' Does this symbol represent a missing assembly.
        ''' </summary>
        Friend MustOverride ReadOnly Property IsMissing As Boolean
 
        Public NotOverridable Overrides ReadOnly Property DeclaredAccessibility As Accessibility
            Get
                Return Accessibility.NotApplicable
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsMustOverride As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsNotOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsOverrides As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property IsShared As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
            Get
                Return ImmutableArray(Of SyntaxReference).Empty
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return Nothing
            End Get
        End Property
 
        Public MustOverride ReadOnly Property HasImportedFromTypeLibAttribute As Boolean
 
        Public MustOverride ReadOnly Property HasPrimaryInteropAssemblyAttribute As Boolean
 
        ''' <summary>
        ''' Lookup a top level type referenced from metadata, names should be
        ''' compared case-sensitively.
        ''' </summary>
        ''' <param name="emittedName">
        ''' Full type name, possibly with generic name mangling.
        ''' </param>
        Friend MustOverride Function LookupDeclaredTopLevelMetadataType(ByRef emittedName As MetadataTypeName) As NamedTypeSymbol
 
        ''' <summary>
        ''' Lookup a top level type referenced from metadata, names should be
        ''' compared case-sensitively.  Detect cycles during lookup.
        ''' </summary>
        ''' <param name="emittedName">
        ''' Full type name, possibly with generic name mangling.
        ''' </param>
        ''' <param name="visitedAssemblies">
        ''' List of assemblies lookup has already visited (since type forwarding can introduce cycles).
        ''' </param>
        Friend MustOverride Function LookupDeclaredOrForwardedTopLevelMetadataType(ByRef emittedName As MetadataTypeName, visitedAssemblies As ConsList(Of AssemblySymbol)) As NamedTypeSymbol
 
        ''' <summary>
        ''' Returns the type symbol for a forwarded type based its canonical CLR metadata name.
        ''' The name should refer to a non-nested type. If type with this name Is Not forwarded,
        ''' null Is returned.
        ''' </summary>
        Public Function ResolveForwardedType(fullyQualifiedMetadataName As String) As NamedTypeSymbol
            If fullyQualifiedMetadataName Is Nothing Then
                Throw New ArgumentNullException(NameOf(fullyQualifiedMetadataName))
            End If
 
            Dim emittedName = MetadataTypeName.FromFullName(fullyQualifiedMetadataName)
            Return TryLookupForwardedMetadataType(emittedName, ignoreCase:=False)
        End Function
 
        ''' <summary>
        ''' Look up the given metadata type, if it Is forwarded.
        ''' </summary>
        Friend Function TryLookupForwardedMetadataType(ByRef emittedName As MetadataTypeName, ignoreCase As Boolean) As NamedTypeSymbol
            Return TryLookupForwardedMetadataTypeWithCycleDetection(emittedName, visitedAssemblies:=Nothing, ignoreCase:=ignoreCase)
        End Function
 
        ''' <summary>
        ''' Look up the given metadata type, if it is forwarded.
        ''' </summary>
        Friend Overridable Function TryLookupForwardedMetadataTypeWithCycleDetection(ByRef emittedName As MetadataTypeName, visitedAssemblies As ConsList(Of AssemblySymbol), ignoreCase As Boolean) As NamedTypeSymbol
            Return Nothing
        End Function
 
        Friend Function CreateCycleInTypeForwarderErrorTypeSymbol(ByRef emittedName As MetadataTypeName) As ErrorTypeSymbol
            Dim diagInfo As DiagnosticInfo = New DiagnosticInfo(MessageProvider.Instance, ERRID.ERR_TypeFwdCycle2, emittedName.FullName, Me)
            Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(Me.Modules(0), emittedName, diagInfo)
        End Function
 
        Friend Function CreateMultipleForwardingErrorTypeSymbol(ByRef emittedName As MetadataTypeName, forwardingModule As ModuleSymbol, destination1 As AssemblySymbol, destination2 As AssemblySymbol) As ErrorTypeSymbol
            Dim diagnosticInfo = New DiagnosticInfo(MessageProvider.Instance, ERRID.ERR_TypeForwardedToMultipleAssemblies, forwardingModule, Me, emittedName.FullName, destination1, destination2)
            Return New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(forwardingModule, emittedName, diagnosticInfo)
        End Function
 
        Friend MustOverride Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
 
        ''' <summary>
        ''' Lookup declaration for predefined CorLib type in this Assembly. Only valid if this 
        ''' assembly is the Cor Library
        ''' </summary>
        ''' <param name="type"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Friend MustOverride Function GetDeclaredSpecialType(type As ExtendedSpecialType) As NamedTypeSymbol
 
        ''' <summary>
        ''' Register declaration of predefined CorLib type in this Assembly.
        ''' </summary>
        ''' <param name="corType"></param>
        Friend Overridable Sub RegisterDeclaredSpecialType(corType As NamedTypeSymbol)
            Throw ExceptionUtilities.Unreachable
        End Sub
 
        ''' <summary>
        ''' Continue looking for declaration of predefined CorLib type in this Assembly
        ''' while symbols for new type declarations are constructed.
        ''' </summary>
        Friend Overridable ReadOnly Property KeepLookingForDeclaredSpecialTypes As Boolean
            Get
                Throw ExceptionUtilities.Unreachable
            End Get
        End Property
 
        Public Function SupportsRuntimeCapability(capability As RuntimeCapability) As Boolean
            ' Keep in sync with C#'s AssemblySymbol.SupportsRuntimeCapability
            Select Case capability
                Case RuntimeCapability.ByRefFields
                    Return Me.RuntimeSupportsByRefFields
                Case RuntimeCapability.CovariantReturnsOfClasses
                    Return Me.RuntimeSupportsCovariantReturnsOfClasses
                Case RuntimeCapability.DefaultImplementationsOfInterfaces
                    Return Me.RuntimeSupportsDefaultInterfaceImplementation
                Case RuntimeCapability.NumericIntPtr
                    Return Me.RuntimeSupportsNumericIntPtr
                Case RuntimeCapability.UnmanagedSignatureCallingConvention
                    Return Me.RuntimeSupportsUnmanagedSignatureCallingConvention
                Case RuntimeCapability.VirtualStaticsInInterfaces
                    Return Me.RuntimeSupportsVirtualStaticsInInterfaces
                Case RuntimeCapability.InlineArrayTypes
                    Return Me.RuntimeSupportsInlineArrayTypes
                Case RuntimeCapability.ByRefLikeGenerics
                    Return Me.RuntimeSupportsByRefLikeGenerics
            End Select
 
            Return False
        End Function
 
        Private ReadOnly Property RuntimeSupportsByRefFields As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsByRefFields
                Return RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__ByRefFields)
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsCovariantReturnsOfClasses As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsCovariantReturnsOfClasses
                Return RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__CovariantReturnsOfClasses) AndAlso
                       GetSpecialType(SpecialType.System_Runtime_CompilerServices_PreserveBaseOverridesAttribute).IsClassType()
            End Get
        End Property
 
        ''' <summary>
        ''' Figure out if the target runtime supports default interface implementation.
        ''' </summary>
        Friend ReadOnly Property RuntimeSupportsDefaultInterfaceImplementation As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsDefaultInterfaceImplementation
                Return RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__DefaultImplementationsOfInterfaces)
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsNumericIntPtr As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsNumericIntPtr
 
                ' CorLibrary should never be null, but that invariant Is broken in some cases for MissingAssemblySymbol.
                ' Tracked by https://github.com/dotnet/roslyn/issues/61262
                Return CorLibrary IsNot Nothing AndAlso
                       RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__NumericIntPtr)
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsUnmanagedSignatureCallingConvention As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsUnmanagedSignatureCallingConvention
                Return RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__UnmanagedSignatureCallingConvention)
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsVirtualStaticsInInterfaces As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsStaticAbstractMembersInInterfaces
                Return RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__VirtualStaticsInInterfaces)
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsInlineArrayTypes As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsInlineArrayTypes
                Return GetSpecialTypeMember(SpecialMember.System_Runtime_CompilerServices_InlineArrayAttribute__ctor) IsNot Nothing
            End Get
        End Property
 
        Private ReadOnly Property RuntimeSupportsByRefLikeGenerics As Boolean
            Get
                ' Keep in sync with C#'s AssemblySymbol.RuntimeSupportsByRefLikeGenerics
                ' CorLibrary should never be null, but that invariant Is broken in some cases for MissingAssemblySymbol.
                ' Tracked by https://github.com/dotnet/roslyn/issues/61262
                Return CorLibrary IsNot Nothing AndAlso
                       RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__ByRefLikeGenerics)
            End Get
        End Property
 
        Private Function RuntimeSupportsFeature(feature As SpecialMember) As Boolean
            Debug.Assert(SpecialMembers.GetDescriptor(feature).DeclaringSpecialType = SpecialType.System_Runtime_CompilerServices_RuntimeFeature)
 
            Dim runtimeFeature = GetSpecialType(SpecialType.System_Runtime_CompilerServices_RuntimeFeature)
            Return runtimeFeature.IsClassType() AndAlso runtimeFeature.IsMetadataAbstract AndAlso runtimeFeature.IsMetadataSealed AndAlso
                   GetSpecialTypeMember(feature) IsNot Nothing
        End Function
 
        ''' <summary>
        ''' Return an array of assemblies involved in canonical type resolution of
        ''' NoPia local types defined within this assembly. In other words, all 
        ''' references used by previous compilation referencing this assembly.
        ''' </summary>
        ''' <returns></returns>
        Friend MustOverride Function GetNoPiaResolutionAssemblies() As ImmutableArray(Of AssemblySymbol)
        Friend MustOverride Sub SetNoPiaResolutionAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
 
        ''' <summary>
        ''' Return an array of assemblies referenced by this assembly, which are linked (/l-ed) by 
        ''' each compilation that is using this AssemblySymbol as a reference. 
        ''' If this AssemblySymbol is linked too, it will be in this array too.
        ''' </summary>
        Friend MustOverride Function GetLinkedReferencedAssemblies() As ImmutableArray(Of AssemblySymbol)
        Friend MustOverride Sub SetLinkedReferencedAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
 
        ''' <summary>
        ''' Assembly is /l-ed by compilation that is using it as a reference.
        ''' </summary>
        Friend MustOverride ReadOnly Property IsLinked As Boolean
 
        ''' <summary>
        ''' Returns true and a string from the first GuidAttribute on the assembly, 
        ''' the string might be null or an invalid guid representation. False, 
        ''' if there is no GuidAttribute with string argument.
        ''' </summary>
        Friend MustOverride Function GetGuidString(ByRef guidString As String) As Boolean
 
        Public MustOverride ReadOnly Property TypeNames As ICollection(Of String) Implements IAssemblySymbol.TypeNames
 
        Public MustOverride ReadOnly Property NamespaceNames As ICollection(Of String) Implements IAssemblySymbol.NamespaceNames
 
        ''' <summary>
        ''' An empty list means there was no IVT attribute with matching <paramref name="simpleName"/>.
        ''' An IVT attribute without a public key setting is represented by an entry that is empty in the returned list
        ''' </summary>
        ''' <param name="simpleName"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Friend MustOverride Function GetInternalsVisibleToPublicKeys(simpleName As String) As IEnumerable(Of ImmutableArray(Of Byte))
 
        Friend MustOverride Function GetInternalsVisibleToAssemblyNames() As IEnumerable(Of String)
 
        Friend MustOverride Function AreInternalsVisibleToThisAssembly(other As AssemblySymbol) As Boolean
 
        ''' <summary>
        ''' Get symbol for predefined type from Cor Library used by this assembly.
        ''' </summary>
        ''' <param name="type"></param>
        ''' <returns>The symbol for the pre-defined type or Nothing if the type is not defined in the core library</returns>
        ''' <remarks></remarks>
        Friend Function GetSpecialType(type As ExtendedSpecialType) As NamedTypeSymbol
            If CInt(type) <= SpecialType.None OrElse CInt(type) >= InternalSpecialType.NextAvailable Then
                Throw New ArgumentOutOfRangeException(NameOf(type), $"Unexpected SpecialType: '{CInt(type)}'.")
            End If
 
            Return CorLibrary.GetDeclaredSpecialType(type)
        End Function
 
        ''' <summary>
        ''' The NamedTypeSymbol for the .NET System.Object type, which could have a TypeKind of
        ''' Error if there was no COR Library in a compilation using the assembly.
        '''</summary>
        Friend ReadOnly Property ObjectType As NamedTypeSymbol
            Get
                Return GetSpecialType(SpecialType.System_Object)
            End Get
        End Property
 
        ''' <summary>
        ''' Get symbol for predefined type from Cor Library used by this assembly.
        ''' </summary>
        ''' <param name="type"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Friend Function GetPrimitiveType(type As Microsoft.Cci.PrimitiveTypeCode) As NamedTypeSymbol
            Return GetSpecialType(SpecialTypes.GetTypeFromMetadataName(type))
        End Function
 
        ''' <summary>
        ''' Lookup a type within the assembly using its canonical CLR metadata name (names are compared case-sensitively).
        ''' </summary>
        ''' <param name="fullyQualifiedMetadataName">
        ''' </param>
        ''' <returns>
        ''' Symbol for the type or null if type cannot be found or is ambiguous. 
        ''' </returns>
        Public Function GetTypeByMetadataName(fullyQualifiedMetadataName As String) As NamedTypeSymbol
            Return GetTypeByMetadataName(fullyQualifiedMetadataName, includeReferences:=False, isWellKnownType:=False, conflicts:=Nothing)
        End Function
 
        Private Shared ReadOnly s_nestedTypeNameSeparators As Char() = {"+"c}
 
        ''' <summary>
        ''' Lookup a type within the assembly using its canonical CLR metadata name (names are compared case-sensitively).
        ''' </summary>
        ''' <param name="metadataName"></param>
        ''' <param name="includeReferences">
        ''' If search within assembly fails, lookup in assemblies referenced by the primary module.
        ''' For source assembly, this is equivalent to all assembly references given to compilation.
        ''' </param>
        ''' <param name="isWellKnownType">
        ''' Extra restrictions apply when searching for a well-known type.  In particular, the type must be public.
        ''' </param>
        ''' <param name="useCLSCompliantNameArityEncoding">
        ''' While resolving the name, consider only types following CLS-compliant generic type names and arity encoding (ECMA-335, section 10.7.2).
        ''' I.e. arity is inferred from the name and matching type must have the same emitted name and arity.
        ''' </param>
        ''' <param name="ignoreCorLibraryDuplicatedTypes">
        ''' When set, any duplicate coming from corlib is ignored.
        ''' </param>
        ''' <param name="conflicts">
        ''' In cases a type could not be found because of ambiguity, we return two of the candidates that caused the ambiguity.
        ''' </param>
        ''' <returns></returns>
        Friend Function GetTypeByMetadataName(metadataName As String, includeReferences As Boolean, isWellKnownType As Boolean, <Out> ByRef conflicts As (AssemblySymbol, AssemblySymbol),
                                              Optional useCLSCompliantNameArityEncoding As Boolean = False, Optional ignoreCorLibraryDuplicatedTypes As Boolean = False) As NamedTypeSymbol
 
            If metadataName Is Nothing Then
                Throw New ArgumentNullException(NameOf(metadataName))
            End If
 
            Dim type As NamedTypeSymbol
            Dim mdName As MetadataTypeName
 
            If metadataName.Contains("+"c) Then
 
                Dim parts() As String = metadataName.Split(s_nestedTypeNameSeparators)
                Debug.Assert(parts.Length > 0)
                mdName = MetadataTypeName.FromFullName(parts(0), useCLSCompliantNameArityEncoding)
                type = GetTopLevelTypeByMetadataName(mdName, includeReferences, isWellKnownType, conflicts)
 
                If type Is Nothing Then
                    Return Nothing
                End If
 
                Debug.Assert(Not type.IsErrorType())
 
                Dim i As Integer = 1
 
                While i < parts.Length
                    mdName = MetadataTypeName.FromTypeName(parts(i))
                    type = type.LookupMetadataType(mdName)
 
                    If type Is Nothing Then
                        Return Nothing
                    End If
 
                    Debug.Assert(Not type.IsErrorType())
 
                    If isWellKnownType AndAlso Not IsValidWellKnownType(type) Then
                        Return Nothing
                    End If
 
                    i += 1
                End While
            Else
                mdName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding)
                type = GetTopLevelTypeByMetadataName(mdName, includeReferences, isWellKnownType, conflicts,
                                                     ignoreCorLibraryDuplicatedTypes:=ignoreCorLibraryDuplicatedTypes)
            End If
 
            Debug.Assert(If(Not type?.IsErrorType(), True))
            Return type
        End Function
 
        ''' <summary>
        ''' Lookup a top level type within the assembly or one of the assemblies referenced by the primary module, 
        ''' names are compared case-sensitively. In case of ambiguity, type from this assembly wins,
        ''' otherwise Nothing is returned.
        ''' </summary>
        ''' <returns>
        ''' Symbol for the type or Nothing if type cannot be found or ambiguous. 
        ''' </returns>
        Friend Function GetTopLevelTypeByMetadataName(ByRef metadataName As MetadataTypeName, includeReferences As Boolean, isWellKnownType As Boolean, <Out> ByRef conflicts As (AssemblySymbol, AssemblySymbol),
                                                      Optional ignoreCorLibraryDuplicatedTypes As Boolean = False) As NamedTypeSymbol
            conflicts = Nothing
            Dim result As NamedTypeSymbol
 
            ' First try this assembly
            result = Me.LookupDeclaredTopLevelMetadataType(metadataName)
            Debug.Assert(If(Not result?.IsErrorType(), True))
 
            If isWellKnownType AndAlso Not IsValidWellKnownType(result) Then
                result = Nothing
            End If
 
            If IsAcceptableMatchForGetTypeByNameAndArity(result) Then
                Return result
            End If
 
            result = Nothing
 
            If Not includeReferences Then
                Return result
            End If
 
            ' Then try corlib, when finding a result there means we've found the final result
            Dim skipCorLibrary = False
 
            If CorLibrary IsNot Me AndAlso
                Not CorLibrary.IsMissing AndAlso
                Not ignoreCorLibraryDuplicatedTypes Then
 
                Dim corLibCandidate As NamedTypeSymbol = CorLibrary.LookupDeclaredTopLevelMetadataType(metadataName)
                Debug.Assert(If(Not corLibCandidate?.IsErrorType(), True))
                skipCorLibrary = True
 
                If IsValidCandidate(corLibCandidate, isWellKnownType) Then
                    Return corLibCandidate
                End If
            End If
 
            ' Lookup in references
            Dim references As ImmutableArray(Of AssemblySymbol) = Me.Modules(0).GetReferencedAssemblySymbols()
 
            For i As Integer = 0 To references.Length - 1 Step 1
                Debug.Assert(Not (TypeOf Me Is SourceAssemblySymbol AndAlso references(i).IsMissing)) ' Non-source assemblies can have missing references
                Dim reference = references(i)
 
                If skipCorLibrary AndAlso reference Is CorLibrary Then
                    Continue For
                End If
 
                Dim candidate As NamedTypeSymbol = reference.LookupDeclaredTopLevelMetadataType(metadataName)
                Debug.Assert(If(Not candidate?.IsErrorType(), True))
 
                If Not IsValidCandidate(candidate, isWellKnownType) OrElse
                        TypeSymbol.Equals(candidate, result, TypeCompareKind.ConsiderEverything) Then
 
                    Continue For
                End If
 
                If result IsNot Nothing Then
                    ' Ambiguity
                    If ignoreCorLibraryDuplicatedTypes Then
                        If IsInCorLib(candidate) Then
                            ' ignore candidate
                            Continue For
                        End If
                        If IsInCorLib(result) Then
                            ' drop previous result
                            result = candidate
                            Continue For
                        End If
                    End If
 
                    conflicts = (result.ContainingAssembly, candidate.ContainingAssembly)
                    Return Nothing
                End If
 
                result = candidate
            Next
 
            Debug.Assert(If(Not result?.IsErrorType(), True))
            Return result
        End Function
 
        Private Function IsValidCandidate(candidate As NamedTypeSymbol, isWellKnownType As Boolean) As Boolean
 
            Return (Not isWellKnownType OrElse IsValidWellKnownType(candidate)) AndAlso
                IsAcceptableMatchForGetTypeByNameAndArity(candidate) AndAlso
                Not candidate.IsHiddenByVisualBasicEmbeddedAttribute() AndAlso
                Not candidate.IsHiddenByCodeAnalysisEmbeddedAttribute()
        End Function
 
        Private Function IsInCorLib(type As NamedTypeSymbol) As Boolean
            Return type.ContainingAssembly Is CorLibrary
        End Function
 
        Friend Shared Function IsAcceptableMatchForGetTypeByNameAndArity(candidate As NamedTypeSymbol) As Boolean
            Return candidate IsNot Nothing AndAlso (candidate.Kind <> SymbolKind.ErrorType OrElse Not (TypeOf candidate Is MissingMetadataTypeSymbol))
        End Function
 
        ''' <summary>
        ''' If this property returns false, it is certain that there are no extension
        ''' methods (from language perspective) inside this assembly. If this property returns true, 
        ''' it is highly likely (but not certain) that this type contains extension methods. 
        ''' This property allows the search for extension methods to be narrowed much more quickly.
        ''' 
        ''' !!! Note that this property can mutate during lifetime of the symbol !!!
        ''' !!! from True to False, as we learn more about the assembly.         !!! 
        ''' </summary>
        Public MustOverride ReadOnly Property MightContainExtensionMethods As Boolean Implements IAssemblySymbol.MightContainExtensionMethods
 
        Friend MustOverride ReadOnly Property PublicKey As ImmutableArray(Of Byte)
 
        Friend Function IsValidWellKnownType(result As NamedTypeSymbol) As Boolean
            If result Is Nothing OrElse result.TypeKind = TypeKind.Error Then
                Return False
            End If
 
            Debug.Assert(result.ContainingType Is Nothing OrElse IsValidWellKnownType(result.ContainingType),
                         "Checking the containing type is the caller's responsibility.")
 
            Return result.DeclaredAccessibility = Accessibility.Public OrElse IsSymbolAccessible(result, Me)
        End Function
 
#Region "IAssemblySymbol"
 
        Private ReadOnly Property IAssemblySymbol_GlobalNamespace As INamespaceSymbol Implements IAssemblySymbol.GlobalNamespace
            Get
                Return Me.GlobalNamespace
            End Get
        End Property
 
        Private Function IAssemblySymbol_GivesAccessTo(assemblyWantingAccess As IAssemblySymbol) As Boolean Implements IAssemblySymbol.GivesAccessTo
            If Equals(Me, assemblyWantingAccess) Then
                Return True
            End If
 
            Dim myKeys = Me.GetInternalsVisibleToPublicKeys(assemblyWantingAccess.Name)
 
            ' We have an easy out here. Suppose the assembly wanting access is
            ' being compiled as a module. You can only strong-name an assembly. So we are going to optimistically
            ' assume that it Is going to be compiled into an assembly with a matching strong name, if necessary
            If myKeys.Any() AndAlso assemblyWantingAccess.IsNetModule() Then
                Return True
            End If
 
            For Each key In myKeys
                Dim conclusion As IVTConclusion = Me.Identity.PerformIVTCheck(assemblyWantingAccess.Identity.PublicKey, key)
                Debug.Assert(conclusion <> IVTConclusion.NoRelationshipClaimed)
                If conclusion = IVTConclusion.Match Then
                    ' Note that C# includes  OrElse conclusion = IVTConclusion.OneSignedOneNot
                    Return True
                End If
            Next
 
            Return False
        End Function
 
        Private ReadOnly Property IAssemblySymbol_Modules As IEnumerable(Of IModuleSymbol) Implements IAssemblySymbol.Modules
            Get
                Return ImmutableArray(Of IModuleSymbol).CastUp(Me.Modules)
            End Get
        End Property
 
        Private Function IAssemblySymbol_ResolveForwardedType(metadataName As String) As INamedTypeSymbol Implements IAssemblySymbol.ResolveForwardedType
            Return Me.ResolveForwardedType(metadataName)
        End Function
 
        Private Function IAssemblySymbol_GetForwardedTypes() As ImmutableArray(Of INamedTypeSymbol) Implements IAssemblySymbol.GetForwardedTypes
            Return ImmutableArrayExtensions.AsImmutable(Of INamedTypeSymbol)(GetAllTopLevelForwardedTypes().OrderBy(Function(t) t.ToDisplayString(SymbolDisplayFormat.QualifiedNameArityFormat)))
        End Function
 
        Private Function IAssemblySymbol_GetTypeByMetadataName(metadataName As String) As INamedTypeSymbol Implements IAssemblySymbol.GetTypeByMetadataName
            Return Me.GetTypeByMetadataName(metadataName)
        End Function
 
        Public Overrides Sub Accept(visitor As SymbolVisitor)
            visitor.VisitAssembly(Me)
        End Sub
 
        Public Overrides Function Accept(Of TResult)(visitor As SymbolVisitor(Of TResult)) As TResult
            Return visitor.VisitAssembly(Me)
        End Function
 
        Public Overrides Function Accept(Of TArgument, TResult)(visitor As SymbolVisitor(Of TArgument, TResult), argument As TArgument) As TResult
            Return visitor.VisitAssembly(Me, argument)
        End Function
 
        Public Overrides Sub Accept(visitor As VisualBasicSymbolVisitor)
            visitor.VisitAssembly(Me)
        End Sub
 
        Public Overrides Function Accept(Of TResult)(visitor As VisualBasicSymbolVisitor(Of TResult)) As TResult
            Return visitor.VisitAssembly(Me)
        End Function
 
        Private Function IAssemblySymbolInternal_GetInternalsVisibleToPublicKeys(simpleName As String) As IEnumerable(Of ImmutableArray(Of Byte)) Implements IAssemblySymbolInternal.GetInternalsVisibleToPublicKeys
            Return GetInternalsVisibleToPublicKeys(simpleName)
        End Function
 
        Private Function IAssemblySymbolInternal_GetInternalsVisibleToAssemblyNames() As IEnumerable(Of String) Implements IAssemblySymbolInternal.GetInternalsVisibleToAssemblyNames
            Return GetInternalsVisibleToAssemblyNames()
        End Function
 
        Private Function IAssemblySymbolInternal_AreInternalsVisibleToThisAssembly(other As IAssemblySymbolInternal) As Boolean Implements IAssemblySymbolInternal.AreInternalsVisibleToThisAssembly
            Return AreInternalsVisibleToThisAssembly(DirectCast(other, AssemblySymbol))
        End Function
 
#End Region
 
    End Class
End Namespace