File: Binding\DescendantBinderFactory.vb
Web Access
Project: src\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 System.Threading
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic

    ''' <summary>
    ''' Provides a way to obtain binders for descendant scopes in method or lambda body.
    ''' Factory for a method body does not create binders for scopes inside a lambda, 
    ''' contained by the method. A dedicated factory must be created for each lambda body.
    ''' </summary>
    Friend Class DescendantBinderFactory

        Private ReadOnly _rootBinder As ExecutableCodeBinder
        Private ReadOnly _root As SyntaxNode

        Public Sub New(binder As ExecutableCodeBinder, root As SyntaxNode)
            _rootBinder = binder
            _root = root
        End Sub

        Friend ReadOnly Property Root As SyntaxNode
            Get
                Return _root
            End Get
        End Property

        Friend ReadOnly Property RootBinder As ExecutableCodeBinder
            Get
                Return _rootBinder
            End Get
        End Property

        Friend Function GetBinder(node As SyntaxNode) As Binder
            Dim binder As BlockBaseBinder = Nothing
            If NodeToBinderMap.TryGetValue(node, binder) Then
                Return binder
            Else
                Return Nothing
            End If
        End Function

        Friend Function GetBinder(statementList As SyntaxList(Of StatementSyntax)) As Binder
            Dim binder As BlockBaseBinder = Nothing
            If StmtListToBinderMap.TryGetValue(statementList, binder) Then
                Return binder
            Else
                Return Nothing
            End If
        End Function

        Private _lazyNodeToBinderMap As ImmutableDictionary(Of SyntaxNode, BlockBaseBinder)

        ' Get the map that maps from syntax nodes to binders.
        Friend ReadOnly Property NodeToBinderMap As ImmutableDictionary(Of SyntaxNode, BlockBaseBinder)
            Get
                If _lazyNodeToBinderMap Is Nothing Then
                    BuildBinderMaps()
                End If
                Return _lazyNodeToBinderMap
            End Get
        End Property

        Private _lazyStmtListToBinderMap As ImmutableDictionary(Of SyntaxList(Of StatementSyntax), BlockBaseBinder)

        ' Get the map that maps from statement lists to binders.
        Friend ReadOnly Property StmtListToBinderMap As ImmutableDictionary(Of SyntaxList(Of StatementSyntax), BlockBaseBinder)
            Get
                If _lazyStmtListToBinderMap Is Nothing Then
                    BuildBinderMaps()
                End If
                Return _lazyStmtListToBinderMap
            End Get
        End Property

        ' Build the two maps that map to nodes and statement lists to binders.
        Private Sub BuildBinderMaps()
            Dim builder As New LocalBinderBuilder(DirectCast(_rootBinder.ContainingMember, MethodSymbol))
            builder.MakeBinder(Root, RootBinder)
            Interlocked.CompareExchange(_lazyNodeToBinderMap, builder.NodeToBinderMap, Nothing)
            Interlocked.CompareExchange(_lazyStmtListToBinderMap, builder.StmtListToBinderMap, Nothing)
        End Sub

    End Class

End Namespace