File: Binders\ParametersAndLocalsBinder.vb
Web Access
Project: src\src\ExpressionEvaluator\VisualBasic\Source\ExpressionCompiler\Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler.vbproj (Microsoft.CodeAnalysis.VisualBasic.ExpressionCompiler)
' 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.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Roslyn.Utilities
 
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
    Friend NotInheritable Class ParametersAndLocalsBinder
        Inherits Binder
 
        Private ReadOnly _substitutedSourceMethod As MethodSymbol
        Private ReadOnly _nameToSymbolMap As Dictionary(Of String, Symbol)
 
        Public Sub New(containingBinder As Binder, targetMethod As EEMethodSymbol, substitutedSourceMethod As MethodSymbol)
            MyBase.New(containingBinder)
 
            _substitutedSourceMethod = substitutedSourceMethod
            _nameToSymbolMap = BuildNameToSymbolMap(targetMethod.Parameters, targetMethod.LocalsForBinding)
        End Sub
 
        ''' <remarks>
        ''' Currently, if there are duplicate names, the last one will win.
        ''' CONSIDER: We could create a multi-dictionary to let lookup fail "naturally".
        ''' CONSIDER: It would be nice to capture this behavior with a test.
        ''' </remarks>
        Private Shared Function BuildNameToSymbolMap(parameters As ImmutableArray(Of ParameterSymbol), locals As ImmutableArray(Of LocalSymbol)) As Dictionary(Of String, Symbol)
            Dim nameToSymbolMap As New Dictionary(Of String, Symbol)(CaseInsensitiveComparison.Comparer)
 
            For Each parameter In parameters
                Dim name As String = parameter.Name
                Dim kind As GeneratedNameKind = GeneratedNameParser.GetKind(name)
                If kind = GeneratedNameKind.None OrElse kind = GeneratedNameKind.HoistedMeField Then
                    nameToSymbolMap(name) = parameter
                Else
                    Debug.Assert(kind = GeneratedNameKind.TransparentIdentifier OrElse
                                 kind = GeneratedNameKind.AnonymousTransparentIdentifier)
                End If
            Next
 
            For Each local In locals
                nameToSymbolMap(local.Name) = local
            Next
 
            Return nameToSymbolMap
        End Function
 
        Public Overrides ReadOnly Property ContainingMember As Symbol
            Get
                Return _substitutedSourceMethod
            End Get
        End Property
 
        Public Overrides ReadOnly Property AdditionalContainingMembers As ImmutableArray(Of Symbol)
            Get
                Return ImmutableArray(Of Symbol).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingNamespaceOrType As NamespaceOrTypeSymbol
            Get
                Return _substitutedSourceMethod.ContainingNamespaceOrType
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingType As NamedTypeSymbol
            Get
                Return _substitutedSourceMethod.ContainingType
            End Get
        End Property
 
        Public Overrides Function GetLocalForFunctionValue() As LocalSymbol
            ' If this is ever hit, we'll have to dig the function local out of the locals list.
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Sub LookupInSingleBinder(lookupResult As LookupResult,
                                              name As String,
                                              arity As Integer,
                                              options As LookupOptions,
                                              originalBinder As Binder,
                                              <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol))
            Debug.Assert(lookupResult.IsClear)
 
            ' Parameters and locals always have arity 0 and are not namespaces or types.
            If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly Or LookupOptions.MustNotBeLocalOrParameter)) = 0 Then
                Dim symbol As Symbol = Nothing
                If _nameToSymbolMap.TryGetValue(name, symbol) Then
                    lookupResult.SetFrom(CheckViability(symbol, arity, options, Nothing, useSiteInfo))
                End If
            End If
        End Sub
 
        Friend Overrides Sub AddLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo,
                                                                    options As LookupOptions,
                                                                    originalBinder As Binder)
            ' UNDONE: additional filtering based on options?
            If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly Or LookupOptions.MustNotBeLocalOrParameter)) = 0 Then
                For Each symbol In _nameToSymbolMap.Values
                    If originalBinder.CanAddLookupSymbolInfo(symbol, options, nameSet, Nothing) Then
                        nameSet.AddSymbol(symbol, symbol.Name, 0)
                    End If
                Next
            End If
        End Sub
 
    End Class
End Namespace