File: Symbols\NamespaceOrTypeSymbol.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.Threading
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    ''' <summary>
    ''' Represents either a namespace or a type.
    ''' </summary>
    Friend MustInherit Class NamespaceOrTypeSymbol
        Inherits Symbol
        Implements INamespaceOrTypeSymbol, INamespaceOrTypeSymbolInternal
 
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        ' Changes to the public interface of this class should remain synchronized with the C# version.
        ' Do not make any changes to the public interface without making the corresponding change
        ' to the C# version.
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
        ''' <summary>
        ''' Returns true if this symbol is a namespace. If its not a namespace, it must be a type.
        ''' </summary>
        Public ReadOnly Property IsNamespace As Boolean Implements INamespaceOrTypeSymbol.IsNamespace
            Get
                Return Kind = SymbolKind.Namespace
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if this symbols is a type. Equivalent to Not IsNamespace.
        ''' </summary>
        Public ReadOnly Property IsType As Boolean Implements INamespaceOrTypeSymbol.IsType
            Get
                Return Not IsNamespace
            End Get
        End Property
 
        ''' <summary>
        ''' Get all the members of this symbol.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the members of this symbol. If this symbol has no members,
        ''' returns an empty ImmutableArray. Never returns Nothing.</returns>
        Public MustOverride Function GetMembers() As ImmutableArray(Of Symbol)
 
        ''' <summary>
        ''' Get all the members of this symbol. The members may not be in a particular order, and the order
        ''' may not be stable from call-to-call.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the members of this symbol. If this symbol has no members,
        ''' returns an empty ImmutableArray. Never returns null.</returns>
        Friend Overridable Function GetMembersUnordered() As ImmutableArray(Of Symbol)
 
            '' Default implementation Is to use ordered version. When performance indicates, we specialize to have
            '' separate implementation.
 
            Return GetMembers().ConditionallyDeOrder()
        End Function
 
        ''' <summary>
        ''' Get all the members of this symbol that have a particular name.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the members of this symbol with the given name. If there are
        ''' no members with this name, returns an empty ImmutableArray. The result is deterministic (i.e. the same
        ''' from call to call and from compilation to compilation). Members of the same kind appear in the result
        ''' in the same order in which they appeared at their origin (metadata or source).
        ''' Never returns Nothing.</returns>
        Public MustOverride Function GetMembers(name As String) As ImmutableArray(Of Symbol)
 
        ''' <summary>
        ''' Get all the type members of this symbol. The types may not be in a particular order, and the order
        ''' may not be stable from call-to-call.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the type members of this symbol. If this symbol has no type members,
        ''' returns an empty ImmutableArray. Never returns null.</returns>
        Friend Overridable Function GetTypeMembersUnordered() As ImmutableArray(Of NamedTypeSymbol)
 
            '' Default implementation Is to use ordered version. When performance indicates, we specialize to have
            '' separate implementation.
 
            Return GetTypeMembers().ConditionallyDeOrder()
        End Function
 
        ''' <summary>
        ''' Get all the members of this symbol that are types.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the types that are members of this symbol. If this symbol has no type members,
        ''' returns an empty ImmutableArray. Never returns Nothing.</returns>
        Public MustOverride Function GetTypeMembers() As ImmutableArray(Of NamedTypeSymbol)
 
        ''' <summary>
        ''' Get all the members of this symbol that are types that have a particular name, and any arity.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the types that are members of this symbol with the given name. 
        ''' If this symbol has no type members with this name,
        ''' returns an empty ImmutableArray. Never returns Nothing.</returns>
        Public MustOverride Function GetTypeMembers(name As String) As ImmutableArray(Of NamedTypeSymbol)
 
        ''' <summary>
        ''' Get all the members of this symbol that are types that have a particular name and arity.
        ''' </summary>
        ''' <returns>An ImmutableArray containing all the types that are members of this symbol with the given name and arity.
        ''' If this symbol has no type members with this name and arity,
        ''' returns an empty ImmutableArray. Never returns Nothing.</returns>
        Public Overridable Function GetTypeMembers(name As String, arity As Integer) As ImmutableArray(Of NamedTypeSymbol)
            ' default implementation does a post-filter. We can override this if its a performance burden, but 
            ' experience is that it won't be.
            Return GetTypeMembers(name).WhereAsArray(Function(type, arity_) type.Arity = arity_, arity)
        End Function
 
        ' Only the compiler can create new instances.
        Friend Sub New()
        End Sub
 
        ''' <summary>
        ''' Returns true if this symbol was declared as requiring an override; i.e., declared
        ''' with the "MustOverride" modifier. Never returns true for types. 
        ''' </summary>
        ''' <returns>
        ''' Always returns False.
        ''' </returns>
        Public NotOverridable Overrides ReadOnly Property IsMustOverride As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if this symbol was declared to override a base class members and was
        ''' also restricted from further overriding; i.e., declared with the "NotOverridable"
        ''' modifier. Never returns true for types.
        ''' </summary>
        ''' <returns>
        ''' Always returns False.
        ''' </returns>
        Public NotOverridable Overrides ReadOnly Property IsNotOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if this member is overridable, has an implementation,
        ''' and does not override a base class member; i.e., declared with the "Overridable"
        ''' modifier. Does not return true for members declared as MustOverride or Overrides.
        ''' </summary>
        ''' <returns>
        ''' Always returns False.
        ''' </returns>
        Public NotOverridable Overrides ReadOnly Property IsOverridable As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if this symbol was declared to override a base class members; i.e., declared
        ''' with the "Overrides" modifier. Still returns true if the members was declared
        ''' to override something, but (erroneously) no member to override exists.
        ''' </summary>
        ''' <returns>
        ''' Always returns False.
        ''' </returns>
        Public NotOverridable Overrides ReadOnly Property IsOverrides As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' This is a helper method shared between NamedTypeSymbol and NamespaceSymbol.
        ''' 
        ''' Its purpose is to add names of probable extension methods found in membersByName parameter
        ''' to nameSet parameter. Method's viability check is delegated to overridable method
        ''' AddExtensionMethodLookupSymbolsInfoViabilityCheck, which is overridden by RetargetingNamedtypeSymbol
        ''' and RetargetingNamespaceSymbol in order to perform the check on corresponding RetargetingMethodSymbol.
        ''' 
        ''' Returns true if there were extension methods among the members, 
        ''' regardless whether their names were added into the set. 
        ''' </summary>
        Friend Function AddExtensionMethodLookupSymbolsInfo(
            nameSet As LookupSymbolsInfo,
            options As LookupOptions,
            originalBinder As Binder,
            membersByName As IEnumerable(Of KeyValuePair(Of String, ImmutableArray(Of Symbol)))
        ) As Boolean
            Dim haveSeenExtensionMethod As Boolean = False
 
            For Each pair As KeyValuePair(Of String, ImmutableArray(Of Symbol)) In membersByName
 
                ' TODO: Should we check whether nameSet already contains pair.Key and
                '       go to the next pair? If we do that the, haveSeenExtensionMethod == false,
                '       won't actually mean that there are no extension methods in membersByName.
 
                For Each member As Symbol In pair.Value
                    If member.Kind = SymbolKind.Method Then
                        Dim method = DirectCast(member, MethodSymbol)
 
                        If method.MayBeReducibleExtensionMethod Then
                            haveSeenExtensionMethod = True
 
                            If AddExtensionMethodLookupSymbolsInfoViabilityCheck(method, options, nameSet, originalBinder) Then
                                nameSet.AddSymbol(member, member.Name, member.GetArity())
 
                                ' Move to the next name.
                                Exit For
                            End If
                        End If
                    End If
                Next
            Next
 
            Return haveSeenExtensionMethod
        End Function
 
        ''' <summary>
        ''' Perform extension method viability check within AppendExtensionMethodNames method above.
        ''' This method is overridden by RetargetingNamedtypeSymbol and RetargetingNamespaceSymbol in order to 
        ''' perform the check on corresponding RetargetingMethodSymbol.
        ''' 
        ''' Returns true if the method is viable. 
        ''' </summary>
        Friend Overridable Function AddExtensionMethodLookupSymbolsInfoViabilityCheck(
            method As MethodSymbol,
            options As LookupOptions,
            nameSet As LookupSymbolsInfo,
            originalBinder As Binder
        ) As Boolean
            Return originalBinder.CanAddLookupSymbolInfo(method, options, nameSet, accessThroughType:=method.ContainingType)
        End Function
 
        ''' <summary> 
        ''' Finds types or namespaces described by a qualified name. 
        ''' </summary> 
        ''' <param name="qualifiedName">Sequence of simple plain names.</param>
        '''  <returns> A set of namespace or type symbols with given qualified name (might comprise of types with multiple generic arities),  
        ''' or an empty set if the member can't be found (the qualified name is ambiguous or the symbol doesn't exist). 
        ''' </returns> 
        ''' <remarks> 
        ''' "C.D" matches C.D, C(Of T).D, C(Of S,T).D(Of U), etc. 
        ''' </remarks>
        Friend Function GetNamespaceOrTypeByQualifiedName(qualifiedName As IEnumerable(Of String)) As IEnumerable(Of NamespaceOrTypeSymbol)
            Dim namespaceOrType As NamespaceOrTypeSymbol = Me
            Dim symbols As IEnumerable(Of NamespaceOrTypeSymbol) = Nothing
            For Each namePart In qualifiedName
                If symbols IsNot Nothing Then
                    namespaceOrType = symbols.OfMinimalArity()
                    If namespaceOrType Is Nothing Then
                        Return SpecializedCollections.EmptyEnumerable(Of NamespaceOrTypeSymbol)()
                    End If
                End If
 
                symbols = namespaceOrType.GetMembers(namePart).OfType(Of NamespaceOrTypeSymbol)()
            Next
 
            Return symbols
        End Function
 
#Region "INamespaceOrTypeSymbol"
 
        Private Function INamespaceOrTypeSymbol_GetMembers() As ImmutableArray(Of ISymbol) Implements INamespaceOrTypeSymbol.GetMembers
            Return StaticCast(Of ISymbol).From(Me.GetMembers())
        End Function
 
        Private Function INamespaceOrTypeSymbol_GetMembers(name As String) As ImmutableArray(Of ISymbol) Implements INamespaceOrTypeSymbol.GetMembers
            Return StaticCast(Of ISymbol).From(Me.GetMembers(name))
        End Function
 
        Private Function INamespaceOrTypeSymbol_GetTypeMembers() As ImmutableArray(Of INamedTypeSymbol) Implements INamespaceOrTypeSymbol.GetTypeMembers
            Return StaticCast(Of INamedTypeSymbol).From(Me.GetTypeMembers())
        End Function
 
        Private Function INamespaceOrTypeSymbol_GetTypeMembers(name As String) As ImmutableArray(Of INamedTypeSymbol) Implements INamespaceOrTypeSymbol.GetTypeMembers
            Return StaticCast(Of INamedTypeSymbol).From(Me.GetTypeMembers(name))
        End Function
 
        Public Function INamespaceOrTypeSymbol_GetTypeMembers(name As String, arity As Integer) As ImmutableArray(Of INamedTypeSymbol) Implements INamespaceOrTypeSymbol.GetTypeMembers
            Return StaticCast(Of INamedTypeSymbol).From(Me.GetTypeMembers(name, arity))
        End Function
 
#End Region
    End Class
End Namespace