File: Symbols\Metadata\PE\PEAssemblySymbol.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.Generic
Imports System.Collections.Immutable
Imports System.Collections.ObjectModel
Imports System.Linq.Enumerable
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports System.Runtime.InteropServices
Imports System.Reflection.Metadata.Ecma335
Imports System.Threading
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
 
    ''' <summary>
    ''' Represents an assembly imported from a PE.
    ''' </summary>
    ''' <remarks></remarks>
    Friend NotInheritable Class PEAssemblySymbol
        Inherits MetadataOrSourceAssemblySymbol
 
        ''' <summary>
        ''' An Assembly object providing metadata for the assembly.
        ''' </summary>
        ''' <remarks></remarks>
        Private ReadOnly _assembly As PEAssembly
 
        ''' <summary>
        ''' A MetadataDocumentationProvider providing XML documentation for this assembly.
        ''' </summary>
        Private ReadOnly _documentationProvider As DocumentationProvider
 
        ''' <summary>
        ''' The list of contained PEModuleSymbol objects.
        ''' The list doesn't use type ReadOnlyCollection(Of PEModuleSymbol) so that we
        ''' can return it from Modules property as is.
        ''' </summary>
        ''' <remarks></remarks>
        Private ReadOnly _modules As ImmutableArray(Of ModuleSymbol)
 
        ''' <summary>
        ''' An array of assemblies involved in canonical type resolution of
        ''' NoPia local types defined within this assembly. In other words, all 
        ''' references used by a compilation referencing this assembly.
        ''' The array and its content is provided by ReferenceManager and must not be modified.
        ''' </summary>
        Private _noPiaResolutionAssemblies As ImmutableArray(Of AssemblySymbol)
 
        ''' <summary>
        ''' 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.
        ''' The array and its content is provided by ReferenceManager and must not be modified.
        ''' </summary>
        Private _linkedReferencedAssemblies As ImmutableArray(Of AssemblySymbol)
 
        ''' <summary>
        ''' Assembly is /l-ed by compilation that is using it as a reference.
        ''' </summary>
        Private ReadOnly _isLinked As Boolean
 
        Private _lazyMightContainExtensionMethods As Byte = ThreeState.Unknown
 
        Private _lazyCustomAttributes As ImmutableArray(Of VisualBasicAttributeData)
 
        Private _lazyCachedCompilerFeatureRequiredDiagnosticInfo As DiagnosticInfo = ErrorFactory.EmptyDiagnosticInfo
 
        Private _lazyObsoleteAttributeData As ObsoleteAttributeData = ObsoleteAttributeData.Uninitialized
 
        Friend Sub New(assembly As PEAssembly, documentationProvider As DocumentationProvider,
                       isLinked As Boolean, importOptions As MetadataImportOptions)
            Debug.Assert(assembly IsNot Nothing)
            _assembly = assembly
 
            _documentationProvider = documentationProvider
 
            Dim modules(assembly.Modules.Length - 1) As ModuleSymbol
 
            For i As Integer = 0 To assembly.Modules.Length - 1 Step 1
                modules(i) = New PEModuleSymbol(Me, assembly.Modules(i), importOptions, i)
            Next
 
            _modules = modules.AsImmutableOrNull()
            _isLinked = isLinked
        End Sub
 
        Friend ReadOnly Property Assembly As PEAssembly
            Get
                Return _assembly
            End Get
        End Property
 
        Public Overrides ReadOnly Property Identity As AssemblyIdentity
            Get
                Return _assembly.Identity
            End Get
        End Property
 
        Public Overrides ReadOnly Property AssemblyVersionPattern As Version
            Get
                ' TODO: https://github.com/dotnet/roslyn/issues/9000
                Return Nothing
            End Get
        End Property
 
        Friend Overrides ReadOnly Property PublicKey As ImmutableArray(Of Byte)
            Get
                Return _assembly.Identity.PublicKey
            End Get
        End Property
 
        Friend Overrides Function GetGuidString(ByRef guidString As String) As Boolean
            Return Assembly.Modules(0).HasGuidAttribute(Assembly.Handle, guidString)
        End Function
 
        Friend Overrides Function AreInternalsVisibleToThisAssembly(potentialGiverOfAccess As AssemblySymbol) As Boolean
            Return MakeFinalIVTDetermination(potentialGiverOfAccess) = IVTConclusion.Match
        End Function
 
        Friend Overrides Function GetInternalsVisibleToPublicKeys(simpleName As String) As IEnumerable(Of ImmutableArray(Of Byte))
            Return Assembly.GetInternalsVisibleToPublicKeys(simpleName)
        End Function
 
        Friend Overrides Function GetInternalsVisibleToAssemblyNames() As IEnumerable(Of String)
            Return Assembly.GetInternalsVisibleToAssemblyNames()
        End Function
 
        Public Overloads Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData)
            If _lazyCustomAttributes.IsDefault Then
                PrimaryModule.LoadCustomAttributes(Me.Assembly.Handle, _lazyCustomAttributes)
            End If
            Return _lazyCustomAttributes
        End Function
 
        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return StaticCast(Of Location).From(PrimaryModule.MetadataLocation)
            End Get
        End Property
 
        Public Overrides ReadOnly Property MetadataToken As Integer
            Get
                Return MetadataTokens.GetToken(_assembly.Handle)
            End Get
        End Property
 
        Public Overrides ReadOnly Property Modules As ImmutableArray(Of ModuleSymbol)
            Get
                Return _modules
            End Get
        End Property
 
        Friend ReadOnly Property PrimaryModule As PEModuleSymbol
            Get
                Return DirectCast(Me.Modules(0), PEModuleSymbol)
            End Get
        End Property
 
        Public Overrides ReadOnly Property HasImportedFromTypeLibAttribute As Boolean
            Get
                Return PrimaryModule.Module.HasImportedFromTypeLibAttribute(Assembly.Handle, Nothing)
            End Get
        End Property
 
        Public Overrides ReadOnly Property HasPrimaryInteropAssemblyAttribute As Boolean
            Get
                Return PrimaryModule.Module.HasPrimaryInteropAssemblyAttribute(Assembly.Handle, Nothing, Nothing)
            End Get
        End Property
 
        ''' <summary>
        ''' Look up the assemblies to which the given metadata type Is forwarded.
        ''' </summary>
        ''' <param name="emittedName"></param>
        ''' <param name="ignoreCase">Pass true to look up fullName case-insensitively.  WARNING: more expensive.</param>
        ''' <param name="matchedName">Returns the actual casing of the matching name.</param>
        ''' <returns>
        ''' The assemblies to which the given type Is forwarded Or null, if there isn't one.
        ''' </returns>
        ''' <remarks>
        ''' The returned assemblies may also forward the type.
        ''' </remarks>
        Friend Function LookupAssembliesForForwardedMetadataType(ByRef emittedName As MetadataTypeName, ignoreCase As Boolean, <Out> ByRef matchedName As String) As (FirstSymbol As AssemblySymbol, SecondSymbol As AssemblySymbol)
            ' Look in the type forwarders of the primary module of this assembly, clr does not honor type forwarder		
            ' in non-primary modules.
 
            ' Examine the type forwarders, but only from the primary module.
            Return PrimaryModule.GetAssembliesForForwardedType(emittedName, ignoreCase, matchedName)
        End Function
 
        Friend Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
            Return PrimaryModule.GetForwardedTypes()
        End Function
 
        Friend Overrides Function TryLookupForwardedMetadataTypeWithCycleDetection(ByRef emittedName As MetadataTypeName, visitedAssemblies As ConsList(Of AssemblySymbol), ignoreCase As Boolean) As NamedTypeSymbol
            ' Check if it is a forwarded type.
            Dim matchedName As String = Nothing
            Dim forwardedToAssemblies = LookupAssembliesForForwardedMetadataType(emittedName, ignoreCase, matchedName)
 
            If forwardedToAssemblies.FirstSymbol IsNot Nothing Then
                If forwardedToAssemblies.SecondSymbol IsNot Nothing Then
                    ' Report the main module as that is the only one checked. clr does not honor type forwarders in non-primary modules.
                    Return CreateMultipleForwardingErrorTypeSymbol(emittedName, PrimaryModule, forwardedToAssemblies.FirstSymbol, forwardedToAssemblies.SecondSymbol)
                End If
 
                ' Don't bother to check the forwarded-to assembly if we've already seen it.
                If visitedAssemblies IsNot Nothing AndAlso visitedAssemblies.Contains(forwardedToAssemblies.FirstSymbol) Then
                    Return CreateCycleInTypeForwarderErrorTypeSymbol(emittedName)
                Else
                    visitedAssemblies = New ConsList(Of AssemblySymbol)(Me, If(visitedAssemblies, ConsList(Of AssemblySymbol).Empty))
 
                    If ignoreCase AndAlso Not String.Equals(emittedName.FullName, matchedName, StringComparison.Ordinal) Then
                        emittedName = MetadataTypeName.FromFullName(matchedName, emittedName.UseCLSCompliantNameArityEncoding, emittedName.ForcedArity)
                    End If
 
                    Return forwardedToAssemblies.FirstSymbol.LookupDeclaredOrForwardedTopLevelMetadataType(emittedName, visitedAssemblies)
                End If
            End If
 
            Return Nothing
        End Function
 
        Friend Overrides Function GetNoPiaResolutionAssemblies() As ImmutableArray(Of AssemblySymbol)
            Return _noPiaResolutionAssemblies
        End Function
 
        Friend Overrides Sub SetNoPiaResolutionAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
            _noPiaResolutionAssemblies = assemblies
        End Sub
 
        Friend Overrides Sub SetLinkedReferencedAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
            _linkedReferencedAssemblies = assemblies
        End Sub
 
        Friend Overrides Function GetLinkedReferencedAssemblies() As ImmutableArray(Of AssemblySymbol)
            Return _linkedReferencedAssemblies
        End Function
 
        Friend Overrides ReadOnly Property IsLinked As Boolean
            Get
                Return _isLinked
            End Get
        End Property
 
        Friend ReadOnly Property DocumentationProvider As DocumentationProvider
            Get
                Return _documentationProvider
            End Get
        End Property
 
        Public Overrides ReadOnly Property MightContainExtensionMethods As Boolean
            Get
                If _lazyMightContainExtensionMethods = ThreeState.Unknown Then
                    Dim primaryModuleSymbol = PrimaryModule
                    If primaryModuleSymbol.Module.HasExtensionAttribute(_assembly.Handle, ignoreCase:=True) Then
                        _lazyMightContainExtensionMethods = ThreeState.True
                    Else
                        _lazyMightContainExtensionMethods = ThreeState.False
                    End If
                End If
 
                Return _lazyMightContainExtensionMethods = ThreeState.True
            End Get
        End Property
 
        ''' <remarks>
        ''' This is for perf, not for correctness.
        ''' </remarks>
        Friend Overrides ReadOnly Property DeclaringCompilation As VisualBasicCompilation
            Get
                Return Nothing
            End Get
        End Property
 
        Public Overrides Function GetMetadata() As AssemblyMetadata
            Return _assembly.GetNonDisposableMetadata()
        End Function
 
        Friend Function GetCompilerFeatureRequiredDiagnosticInfo() As DiagnosticInfo
            If _lazyCachedCompilerFeatureRequiredDiagnosticInfo Is ErrorFactory.EmptyDiagnosticInfo Then
                Interlocked.CompareExchange(
                    _lazyCachedCompilerFeatureRequiredDiagnosticInfo,
                    DeriveCompilerFeatureRequiredAttributeDiagnostic(Me, PrimaryModule, _assembly.Handle, CompilerFeatureRequiredFeatures.None, New MetadataDecoder(PrimaryModule)),
                    ErrorFactory.EmptyDiagnosticInfo)
            End If
 
            Return _lazyCachedCompilerFeatureRequiredDiagnosticInfo
        End Function
 
        Public Overrides ReadOnly Property HasUnsupportedMetadata As Boolean
            Get
                Dim info = GetCompilerFeatureRequiredDiagnosticInfo()
                If info IsNot Nothing Then
                    Return info.Code = DirectCast(ERRID.ERR_UnsupportedCompilerFeature, Integer) OrElse MyBase.HasUnsupportedMetadata
                End If
 
                Return MyBase.HasUnsupportedMetadata
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
            Get
                If _lazyObsoleteAttributeData Is ObsoleteAttributeData.Uninitialized Then
                    Dim experimentalData = PrimaryModule.Module.TryDecodeExperimentalAttributeData(Assembly.Handle, New MetadataDecoder(PrimaryModule))
                    Interlocked.CompareExchange(_lazyObsoleteAttributeData, experimentalData, ObsoleteAttributeData.Uninitialized)
                End If
 
                Return _lazyObsoleteAttributeData
            End Get
        End Property
 
    End Class
End Namespace