File: Symbols\Metadata\PE\PENestedNamespaceSymbol.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.Threading
Imports System.Reflection
Imports System.Reflection.Metadata
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
 
    ''' <summary>
    ''' The class to represent all, but Global, namespaces imported from a PE/module.
    ''' Namespaces that differ only by casing in name are merged.
    ''' </summary>
    ''' <remarks></remarks>
    Friend NotInheritable Class PENestedNamespaceSymbol
        Inherits PENamespaceSymbol
 
        ''' <summary>
        ''' The parent namespace. There is always one, Global namespace contains all
        ''' top level namespaces. 
        ''' </summary>
        ''' <remarks></remarks>
        Friend ReadOnly m_ContainingNamespaceSymbol As PENamespaceSymbol
 
        ''' <summary>
        ''' The name of the namespace.
        ''' </summary>
        ''' <remarks></remarks>
        Protected ReadOnly m_Name As String
 
        ''' <summary>
        ''' The sequence of groups of TypeDef row ids for types contained within the namespace, 
        ''' recursively including those from nested namespaces. The row ids are grouped by the 
        ''' fully-qualified namespace name in case-sensitive manner. There could be multiple groups 
        ''' for each fully-qualified namespace name. The groups are sorted by their key  
        ''' in case-insensitive manner. Empty string is used as namespace name for types 
        ''' immediately contained within Global namespace. Therefore, all types in this namespace, if any, 
        ''' will be in several first IGroupings.
        ''' 
        ''' This member is initialized by constructor and is cleared in EnsureAllMembersLoaded 
        ''' as soon as symbols for children are created.
        ''' </summary>
        ''' <remarks></remarks>
        Private _typesByNS As IEnumerable(Of IGrouping(Of String, TypeDefinitionHandle))
 
        ''' <summary>
        ''' Constructor.
        ''' </summary>
        ''' <param name="name">
        ''' Name of the namespace, must be not empty.
        ''' </param>
        ''' <param name="containingNamespace">
        ''' Containing namespace.
        ''' </param>
        ''' <param name="typesByNS">
        ''' The sequence of groups of TypeDef row ids for types contained within the namespace, 
        ''' recursively including those from nested namespaces. The row ids are grouped by the 
        ''' fully-qualified namespace name in case-sensitive manner. There could be multiple groups 
        ''' for each fully-qualified namespace name. The groups are sorted by their key  
        ''' in case-insensitive manner. Empty string is used as namespace name for types 
        ''' immediately contained within Global namespace. Therefore, all types in this namespace, if any, 
        ''' will be in several first IGroupings.
        ''' </param>
        ''' <remarks></remarks>
        Friend Sub New(
            name As String,
            containingNamespace As PENamespaceSymbol,
            typesByNS As IEnumerable(Of IGrouping(Of String, TypeDefinitionHandle))
        )
            Debug.Assert(name IsNot Nothing)
            Debug.Assert(containingNamespace IsNot Nothing)
            Debug.Assert(typesByNS IsNot Nothing)
 
            m_ContainingNamespaceSymbol = containingNamespace
            m_Name = name
            _typesByNS = typesByNS
        End Sub
 
        Public Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return m_ContainingNamespaceSymbol
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ContainingPEModule As PEModuleSymbol
            Get
                Return m_ContainingNamespaceSymbol.ContainingPEModule
            End Get
        End Property
 
        Public Overrides ReadOnly Property Name As String
            Get
                Return m_Name
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsGlobalNamespace As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingAssembly As AssemblySymbol
            Get
                Return ContainingPEModule.ContainingAssembly
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingModule As ModuleSymbol
            Get
                Return m_ContainingNamespaceSymbol.ContainingPEModule
            End Get
        End Property
 
        Protected Overrides Sub EnsureAllMembersLoaded()
            Dim typesByNS = Volatile.Read(_typesByNS)
 
            If typesByNS Is Nothing Then
                Debug.Assert(m_lazyTypes IsNot Nothing AndAlso m_lazyMembers IsNot Nothing)
            Else
                LoadAllMembers(typesByNS)
                Interlocked.Exchange(_typesByNS, Nothing)
            End If
        End Sub
 
        ''' <summary>
        ''' Calculate declared accessibility of most accessible type within this namespace or within a containing namespace recursively.
        ''' Expected to be called at most once per namespace symbol, unless there is a race condition.
        ''' 
        ''' Valid return values:
        '''     Friend,
        '''     Public,
        '''     NotApplicable - if there are no types.
        ''' </summary>
        Protected Overrides Function GetDeclaredAccessibilityOfMostAccessibleDescendantType() As Accessibility
            Dim typesByNS As IEnumerable(Of IGrouping(Of String, TypeDefinitionHandle)) = _typesByNS
 
            If typesByNS IsNot Nothing AndAlso m_lazyTypes Is Nothing Then
                ' Calculate this without creating symbols for children
                Dim [module] = ContainingPEModule.Module
                Dim result As Accessibility = Accessibility.NotApplicable
 
                For Each group As IGrouping(Of String, TypeDefinitionHandle) In typesByNS
                    For Each typeDef As TypeDefinitionHandle In group
                        Dim flags As TypeAttributes
 
                        Try
                            flags = [module].GetTypeDefFlagsOrThrow(typeDef)
                        Catch mrEx As BadImageFormatException
                        End Try
 
                        Select Case (flags And TypeAttributes.VisibilityMask)
                            Case TypeAttributes.Public
                                Return Accessibility.Public
 
                            Case TypeAttributes.NotPublic
                                result = Accessibility.Friend
 
                            Case Else
                                Debug.Assert(False, "Unexpected!!!")
                        End Select
                    Next
                Next
 
                Return result
            Else
                Return MyBase.GetDeclaredAccessibilityOfMostAccessibleDescendantType()
            End If
        End Function
 
        ''' <remarks>
        ''' This is for perf, not for correctness.
        ''' </remarks>
        Friend Overrides ReadOnly Property DeclaringCompilation As VisualBasicCompilation
            Get
                Return Nothing
            End Get
        End Property
    End Class
 
End Namespace