File: Declarations\MergedNamespaceDeclaration.vb
Web Access
Project: src\roslyn\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.Immutable
Imports Microsoft.CodeAnalysis.PooledObjects

Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    ' An invariant of a merged declaration is that all of its children
    ' are also merged declarations.
    Friend NotInheritable Class MergedNamespaceDeclaration
        Inherits MergedNamespaceOrTypeDeclaration

        Private ReadOnly _declarations As ImmutableArray(Of SingleNamespaceDeclaration)
        Private ReadOnly _multipleSpellings As Boolean  ' true if the namespace is spelling with multiple different case-insensitive spellings ("Namespace GOO" and "Namespace goo")
        Private _children As ImmutableArray(Of MergedNamespaceOrTypeDeclaration)

        Private Sub New(declarations As ImmutableArray(Of SingleNamespaceDeclaration))
            MyBase.New(String.Empty)
            If declarations.Any() Then
                Me.Name = SingleNamespaceDeclaration.BestName(Of SingleNamespaceDeclaration)(declarations, _multipleSpellings)
            End If

            Me._declarations = declarations
        End Sub

        Public Shared Function Create(declarations As IEnumerable(Of SingleNamespaceDeclaration)) As MergedNamespaceDeclaration
            Return New MergedNamespaceDeclaration(ImmutableArray.CreateRange(Of SingleNamespaceDeclaration)(declarations))
        End Function

        Public Shared Function Create(ParamArray declarations As SingleNamespaceDeclaration()) As MergedNamespaceDeclaration
            Return New MergedNamespaceDeclaration(declarations.AsImmutableOrNull)
        End Function

        Public Overrides ReadOnly Property Kind As DeclarationKind
            Get
                Return DeclarationKind.Namespace
            End Get
        End Property

        Public ReadOnly Property Declarations As ImmutableArray(Of SingleNamespaceDeclaration)
            Get
                Return _declarations
            End Get
        End Property

        Public Function GetLexicalSortKey(compilation As VisualBasicCompilation) As LexicalSortKey
            ' Return first sort key from all declarations.
            Dim sortKey As LexicalSortKey = New LexicalSortKey(_declarations(0).NameLocation, compilation)
            For i = 1 To _declarations.Length - 1
                sortKey = LexicalSortKey.First(sortKey, New LexicalSortKey(_declarations(i).NameLocation, compilation))
            Next
            Return sortKey
        End Function

        Public ReadOnly Property NameLocations As ImmutableArray(Of Location)
            Get
                If _declarations.Length = 1 Then
                    Dim loc = _declarations(0).NameLocation
                    If loc Is Nothing Then
                        Return ImmutableArray(Of Location).Empty
                    End If
                    Return ImmutableArray.Create(loc)
                End If

                Dim builder = ArrayBuilder(Of Location).GetInstance()

                For Each decl In _declarations
                    Dim loc = decl.NameLocation
                    If loc IsNot Nothing Then
                        builder.Add(loc)
                    End If
                Next

                Return builder.ToImmutableAndFree()
            End Get
        End Property

        Public ReadOnly Property SyntaxReferences As ImmutableArray(Of SyntaxReference)
            Get
                Dim references = ArrayBuilder(Of SyntaxReference).GetInstance()

                For Each decl In _declarations
                    If decl.SyntaxReference IsNot Nothing Then
                        references.Add(decl.SyntaxReference)
                    End If
                Next

                Return references.ToImmutableAndFree()
            End Get
        End Property

        Protected Overrides Function GetDeclarationChildren() As ImmutableArray(Of Declaration)
            Return StaticCast(Of Declaration).From(Me.Children)
        End Function

        Private Function MakeChildren() As ImmutableArray(Of MergedNamespaceOrTypeDeclaration)

            Dim childNamespaces = ArrayBuilder(Of SingleNamespaceDeclaration).GetInstance()
            Dim singleTypeDeclarations = ArrayBuilder(Of SingleTypeDeclaration).GetInstance()

            ' Distribute declarations into the two lists
            For Each d As SingleNamespaceDeclaration In _declarations
                For Each child As SingleNamespaceOrTypeDeclaration In d.Children
                    Dim singleNamespaceDeclaration As SingleNamespaceDeclaration = TryCast(child, SingleNamespaceDeclaration)
                    If singleNamespaceDeclaration IsNot Nothing Then
                        childNamespaces.Add(singleNamespaceDeclaration)
                    Else
                        singleTypeDeclarations.Add(DirectCast(child, SingleTypeDeclaration))
                    End If
                Next
            Next

            Dim result As ArrayBuilder(Of MergedNamespaceOrTypeDeclaration) = ArrayBuilder(Of MergedNamespaceOrTypeDeclaration).GetInstance()

            ' Merge and add the namespaces
            Select Case childNamespaces.Count
                Case 0
                    ' Do nothing
                Case 1
                    ' Add a single element
                    result.Add(MergedNamespaceDeclaration.Create(childNamespaces))
                Case 2
                    ' Could be one group or two
                    If SingleNamespaceDeclaration.EqualityComparer.Equals(childNamespaces(0), childNamespaces(1)) Then
                        result.Add(MergedNamespaceDeclaration.Create(childNamespaces))
                    Else
                        result.Add(MergedNamespaceDeclaration.Create(childNamespaces(0)))
                        result.Add(MergedNamespaceDeclaration.Create(childNamespaces(1)))
                    End If
                Case Else
                    ' Three or more. Use GroupBy to add by groups.
                    For Each group In childNamespaces.GroupBy(Function(n) n, SingleNamespaceDeclaration.EqualityComparer)
                        result.Add(MergedNamespaceDeclaration.Create(group))
                    Next
            End Select

            childNamespaces.Free()

            ' Merge and add the types
            If singleTypeDeclarations.Count <> 0 Then
                result.AddRange(MergedTypeDeclaration.MakeMergedTypes(singleTypeDeclarations))
            End If

            singleTypeDeclarations.Free()

            Return result.ToImmutableAndFree()

        End Function

        Public Overloads ReadOnly Property Children As ImmutableArray(Of MergedNamespaceOrTypeDeclaration)
            Get
                If Me._children.IsDefault Then
                    ImmutableInterlocked.InterlockedInitialize(Me._children, MakeChildren())
                End If

                Return Me._children
            End Get
        End Property

        ' Is this declaration merged from declarations with different case-sensitive spellings
        ' (i.e., "Namespace GOO" and "Namespace goo".
        Public ReadOnly Property HasMultipleSpellings As Boolean
            Get
                Return _multipleSpellings
            End Get
        End Property
    End Class
End Namespace