File: Binding\Binder.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.Concurrent
Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports System.Reflection.Metadata
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.RuntimeMembers
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Utilities
Imports TypeKind = Microsoft.CodeAnalysis.TypeKind
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    ''' <summary>
    ''' A Binder object represents a general location from where binding is happening, and provides
    ''' virtual methods for looking up unqualified names, reporting errors, and also other
    ''' operations that need to know about where binding happened from (accessibility checking,
    ''' etc.) It also contains most of the methods related to general binding of constructs,
    ''' although some large sections are factored into their own classes.
    '''
    ''' Yes, Binder is a big grab bag of features. The reason for this is that binders are threaded
    ''' through essentially ALL binding functions. So, basically Binder has all the features that
    ''' need to be threaded through binding.
    '''
    ''' Binder objects form a linked list and each binder links to its containing binder. Each
    ''' binder only handles operations that it knows how to handles, and passes on other calls to
    ''' its containing binder. This maintains separation of concerns and allows binders to be strung
    ''' together in various configurations to enable different binding scenarios (e.g., debugger
    ''' expression evaluator).
    '''
    ''' In general, binder objects should be constructed via the BinderBuilder class.
    '''
    ''' Binder class has GetBinder methods that return binders for scopes nested into the current
    ''' binder scope. One should not expect to get a binder from the functions unless a syntax that
    ''' originates a scope is passed as the argument. Also, the functions do not cross lambda
    ''' boundaries, if binder's scope contains a lambda expression, binder will not return any
    ''' binders for nodes contained in the lambda body. In order to get them, the lambda must be
    ''' bound to BoundLambda node, which exposes LambdaBinder, which can be asked for binders in the
    ''' lambda body (but it will not descend into nested lambdas). Currently, only
    ''' <see cref="ExecutableCodeBinder"/>, <see cref="MethodBodySemanticModel.IncrementalBinder"/>
    ''' and <see cref="SpeculativeBinder"/> have special implementation of GetBinder functions,
    ''' the rest just delegate to containing binder.
    ''' </summary>
    Friend MustInherit Class Binder
 
        Private Shared ReadOnly s_noArguments As ImmutableArray(Of BoundExpression) = ImmutableArray(Of BoundExpression).Empty
 
        Protected ReadOnly m_containingBinder As Binder
 
        ' Caching these items in the nearest binder is a performance win.
        Private ReadOnly _syntaxTree As SyntaxTree
        Private ReadOnly _compilation As VisualBasicCompilation
        Private ReadOnly _sourceModule As SourceModuleSymbol
        Private ReadOnly _isEarlyAttributeBinder As Boolean
        Private ReadOnly _ignoreBaseClassesInLookup As Boolean
        Private ReadOnly _basesBeingResolved As BasesBeingResolved
 
        Protected Sub New(containingBinder As Binder)
            m_containingBinder = containingBinder
 
            If containingBinder IsNot Nothing Then
                _syntaxTree = containingBinder.SyntaxTree
                _compilation = containingBinder.Compilation
                _sourceModule = containingBinder.SourceModule
                _isEarlyAttributeBinder = containingBinder.IsEarlyAttributeBinder
                _ignoreBaseClassesInLookup = containingBinder.IgnoreBaseClassesInLookup
                _basesBeingResolved = containingBinder.BasesBeingResolved
            End If
        End Sub
 
        Protected Sub New(containingBinder As Binder, syntaxTree As SyntaxTree)
            Me.New(containingBinder)
            _syntaxTree = syntaxTree
        End Sub
 
        Protected Sub New(containingBinder As Binder, sourceModule As SourceModuleSymbol, compilation As VisualBasicCompilation)
            Me.New(containingBinder)
            _sourceModule = sourceModule
            _compilation = compilation
        End Sub
 
        Protected Sub New(containingBinder As Binder, Optional isEarlyAttributeBinder As Boolean? = Nothing, Optional ignoreBaseClassesInLookup As Boolean? = Nothing)
            Me.New(containingBinder)
 
            If isEarlyAttributeBinder.HasValue Then
                _isEarlyAttributeBinder = isEarlyAttributeBinder.Value
            End If
 
            If ignoreBaseClassesInLookup.HasValue Then
                _ignoreBaseClassesInLookup = ignoreBaseClassesInLookup.Value
            End If
        End Sub
 
        Protected Sub New(containingBinder As Binder, basesBeingResolved As BasesBeingResolved)
            Me.New(containingBinder)
            _basesBeingResolved = basesBeingResolved
        End Sub
 
        Public ReadOnly Property ContainingBinder As Binder
            Get
                Return m_containingBinder
            End Get
        End Property
 
        ''' <summary>
        ''' If the binding context requires specific binding options, then modify the given
        ''' lookup options accordingly.
        ''' </summary>
        Friend Overridable Function BinderSpecificLookupOptions(options As LookupOptions) As LookupOptions
            Return m_containingBinder.BinderSpecificLookupOptions(options)
        End Function
 
        Friend ReadOnly Property IgnoresAccessibility As Boolean
            Get
                Return (BinderSpecificLookupOptions(Nothing) And LookupOptions.IgnoreAccessibility) =
                    LookupOptions.IgnoreAccessibility
            End Get
        End Property
 
        ''' <summary>
        ''' Lookup the given name in the binder and containing binders.
        ''' Returns the result of the lookup. See the definition of LookupResult for details.
        ''' </summary>
        ''' <remarks>
        ''' This method is virtual, but usually there is no need to override it. It
        ''' calls the virtual LookupInSingleBinder, which should be overridden instead,
        ''' for each binder in turn, and merges the results.
        ''' Overriding this method is needed only in limited scenarios, for example for
        ''' a binder that binds query [Into] clause and has implicit qualifier.
        ''' </remarks>
        Public Overridable Sub Lookup(lookupResult As LookupResult,
                          name As String,
                          arity As Integer,
                          options As LookupOptions,
                          <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol))
            Debug.Assert(name IsNot Nothing)
 
            Dim originalBinder As Binder = Me
            Dim currentBinder As Binder = Me
 
            Debug.Assert(lookupResult.IsClear)
            options = BinderSpecificLookupOptions(options)
 
            Dim currentResult As LookupResult = LookupResult.GetInstance()
 
            Do
                currentResult.Clear()
                currentBinder.LookupInSingleBinder(currentResult, name, arity, options, originalBinder, useSiteInfo)
                lookupResult.MergePrioritized(currentResult)
 
                If lookupResult.StopFurtherLookup Then
                    currentResult.Free()
                    Return  ' don't need to look further, we have a viable result.
                ElseIf currentResult.IsWrongArity AndAlso TypeOf currentBinder Is ImportAliasesBinder Then
                    ' Since there was a name match among imported aliases, we should not look
                    ' in types and namespaces imported on the same level (file or project).
                    ' We should skip ImportedTypesAndNamespacesMembersBinder and TypesOfImportedNamespacesMembersBinder
                    ' above the currentBinder. Both binders are optional, however either both are present or
                    ' both are absent and the precedence order is the following:
                    '
                    '         <SourceFile or SourceModule binder>
                    '                          |
                    '                          V
                    '       [<TypesOfImportedNamespacesMembersBinder>]
                    '                          |
                    '                          V
                    '       [<ImportedTypesAndNamespacesMembersBinder>]
                    '                          |
                    '                          V
                    '                <ImportAliasesBinder>
 
                    If TypeOf currentBinder.m_containingBinder Is ImportedTypesAndNamespacesMembersBinder Then
                        currentBinder = currentBinder.m_containingBinder.m_containingBinder
                    End If
 
                    Debug.Assert(TypeOf currentBinder.m_containingBinder Is SourceFileBinder OrElse
                                 TypeOf currentBinder.m_containingBinder Is SourceModuleBinder)
 
                ElseIf (options And LookupOptions.IgnoreExtensionMethods) = 0 AndAlso
                   TypeOf currentBinder Is NamedTypeBinder Then
                    ' Only binder of the most nested type can bind to an extension method.
                    options = options Or LookupOptions.IgnoreExtensionMethods
                End If
 
                ' Continue to containing binders.
                currentBinder = currentBinder.m_containingBinder
            Loop While currentBinder IsNot Nothing
 
            currentResult.Free()
 
            ' No good symbols found in any binder. LookupResult has best we found.
            Return
        End Sub
 
        ''' <summary>
        ''' Lookup in just a single binder, without delegating to containing binder. The original
        ''' binder passed in is used for accessibility checking and so forth.
        ''' </summary>
        Friend Overridable 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))
            lookupResult.Clear()
        End Sub
 
        ''' <summary>
        ''' Collect extension methods with the given name that are in scope in this binder.
        ''' The passed in ArrayBuilder must be empty. Extension methods from the same containing type
        ''' must be grouped together.
        ''' </summary>
        Protected Overridable Sub CollectProbableExtensionMethodsInSingleBinder(name As String,
                                                                        methods As ArrayBuilder(Of MethodSymbol),
                                                                        originalBinder As Binder)
            Debug.Assert(methods.Count = 0)
        End Sub
 
        ''' <summary>
        ''' Lookup all names of extension methods that are available from a single binder, without delegating
        ''' to containing binder. The original binder passed in is used for accessibility checking
        ''' and so forth.
        ''' Names that are available are inserted into "nameSet". This is a hashSet that accumulates
        ''' names, and should be created with the VB identifierComparer.
        ''' </summary>
        Protected Overridable Sub AddExtensionMethodLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo,
                                                                                     options As LookupOptions,
                                                                                     originalBinder As Binder)
            ' overridden in derived binders that introduce names.
        End Sub
 
        ''' <summary>
        ''' Lookups labels by label names, returns a label or Nothing
        ''' </summary>
        Friend Overridable Function LookupLabelByNameToken(labelName As SyntaxToken) As LabelSymbol
            Return Me.ContainingBinder.LookupLabelByNameToken(labelName)
        End Function
 
        ' Lookup the names that are available in this binder, given the options.
        ' Names that are available are inserted into "nameSet". This is a hashSet that accumulates
        ' names, and should be created with the VB identifierComparer.
        Public Overridable Sub AddLookupSymbolsInfo(nameSet As LookupSymbolsInfo, options As LookupOptions)
            Debug.Assert(nameSet IsNot Nothing)
 
            Dim originalBinder As Binder = Me
            Dim currentBinder As Binder = Me
 
            Do
                currentBinder.AddLookupSymbolsInfoInSingleBinder(nameSet, options, originalBinder)
 
                ' Only binder of the most nested type can bind to an extension method.
                If (options And LookupOptions.IgnoreExtensionMethods) = 0 AndAlso
                   TypeOf currentBinder Is NamedTypeBinder Then
                    options = options Or LookupOptions.IgnoreExtensionMethods
                End If
 
                ' Continue to containing binders.
                currentBinder = currentBinder.m_containingBinder
            Loop While currentBinder IsNot Nothing
        End Sub
 
        ''' <summary>
        ''' Lookup all names that are available from a single binder, without delegating
        ''' to containing binder. The original binder passed in is used for accessibility checking
        ''' and so forth.
        ''' Names that are available are inserted into "nameSet". This is a hashSet that accumulates
        ''' names, and should be created with the VB identifierComparer.
        ''' </summary>
        Friend Overridable Sub AddLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo,
                                                                  options As LookupOptions,
                                                                  originalBinder As Binder)
            ' overridden in derived binders that introduce names.
        End Sub
 
        ''' <summary>
        ''' Determine if "sym" is accessible from the location represented by this binder. For protected
        ''' access, use the qualifier type "accessThroughType" if not Nothing (if Nothing just check protected
        ''' access with no qualifier).
        ''' </summary>
        ''' <remarks>
        ''' Overriding methods should consider <see cref="IgnoresAccessibility"/>.
        ''' </remarks>
        Public Overridable Function CheckAccessibility(sym As Symbol,
                                                       <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol),
                                                       Optional accessThroughType As TypeSymbol = Nothing,
                                                       Optional basesBeingResolved As BasesBeingResolved = Nothing) As AccessCheckResult
            Return m_containingBinder.CheckAccessibility(sym, useSiteInfo, accessThroughType, basesBeingResolved)
        End Function
 
        ''' <summary>
        ''' Determine if "sym" is accessible from the location represented by this binder. For protected
        ''' access, use the qualifier type "accessThroughType" if not Nothing (if Nothing just check protected
        ''' access with no qualifier).
        ''' </summary>
        Public Function IsAccessible(sym As Symbol,
                                     <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol),
                                     Optional accessThroughType As TypeSymbol = Nothing,
                                     Optional basesBeingResolved As BasesBeingResolved = Nothing) As Boolean
            Return CheckAccessibility(sym, useSiteInfo, accessThroughType, basesBeingResolved) = AccessCheckResult.Accessible
        End Function
 
        ''' <summary>
        ''' Some nodes have special binder's for their contents
        ''' </summary>
        Public Overridable Function GetBinder(node As SyntaxNode) As Binder
            Return m_containingBinder.GetBinder(node)
        End Function
 
        ''' <summary>
        ''' Some nodes have special binder's for their contents
        ''' </summary>
        Public Overridable Function GetBinder(stmtList As SyntaxList(Of StatementSyntax)) As Binder
            Return m_containingBinder.GetBinder(stmtList)
        End Function
 
        ''' <summary>
        ''' The member containing the binding context
        ''' </summary>
        Public Overridable ReadOnly Property ContainingMember As Symbol
            Get
                Return m_containingBinder.ContainingMember
            End Get
        End Property
 
        ''' <summary>
        ''' Additional members associated with the binding context
        ''' Currently, this field is only used for multiple field/property symbols initialized by an AsNew initializer, e.g. "Dim x, y As New Integer" or "WithEvents x, y as New Object"
        ''' </summary>
        Public Overridable ReadOnly Property AdditionalContainingMembers As ImmutableArray(Of Symbol)
            Get
                Return m_containingBinder.AdditionalContainingMembers
            End Get
        End Property
 
        Friend ReadOnly Property ContainingModule As ModuleSymbol
            Get
                ' If there's a containing member, it either is or has a containing module.
                ' Otherwise, we'll just use the compilation's source module.
                Dim containingMember = Me.ContainingMember
                Return If(TryCast(containingMember, ModuleSymbol), If(containingMember?.ContainingModule, Me.Compilation.SourceModule))
            End Get
        End Property
 
        ''' <summary>
        ''' Tells whether binding is happening in a query context.
        ''' </summary>
        Public Overridable ReadOnly Property IsInQuery As Boolean
            Get
                Return m_containingBinder.IsInQuery
            End Get
        End Property
 
        ''' <summary>
        ''' Tells whether binding is happening in a lambda context.
        ''' </summary>
        Friend ReadOnly Property IsInLambda As Boolean
            Get
                Debug.Assert(ContainingMember IsNot Nothing)
                Return ContainingMember.IsLambdaMethod
            End Get
        End Property
 
        Public Overridable ReadOnly Property ImplicitlyTypedLocalsBeingBound As ConsList(Of LocalSymbol)
            Get
                Return m_containingBinder.ImplicitlyTypedLocalsBeingBound
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if the node is in a position where an unbound type
        ''' such as (C(of)) is allowed.
        ''' </summary>
        Public Overridable Function IsUnboundTypeAllowed(syntax As GenericNameSyntax) As Boolean
            Return m_containingBinder.IsUnboundTypeAllowed(syntax)
        End Function
 
        ''' <summary>
        ''' The type containing the binding context
        ''' </summary>
        Public Overridable ReadOnly Property ContainingType As NamedTypeSymbol
            Get
                Return m_containingBinder.ContainingType
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if the binder is binding top-level script code.
        ''' </summary>
        Friend ReadOnly Property BindingTopLevelScriptCode As Boolean
            Get
                Dim containingMember = Me.ContainingMember
                Select Case containingMember.Kind
                    Case SymbolKind.Method
                        ' global statements
                        Return (DirectCast(containingMember, MethodSymbol)).IsScriptConstructor
                    Case SymbolKind.NamedType
                        ' script variable initializers
                        Return (DirectCast(containingMember, NamedTypeSymbol)).IsScriptClass
                    Case Else
                        Return False
                End Select
            End Get
        End Property
 
        ''' <summary>
        ''' The namespace or type containing the binding context
        ''' </summary>
        Public Overridable ReadOnly Property ContainingNamespaceOrType As NamespaceOrTypeSymbol
            Get
                Return m_containingBinder.ContainingNamespaceOrType
            End Get
        End Property
 
        ''' <summary>
        ''' Get the built-in MSCORLIB type identified. If it's not available (an error type), then report the
        ''' error with the given syntax and diagnostic bag. If the node and diagBag are Nothing, then don't report the error (not recommended).
        ''' </summary>
        ''' <param name="typeId">Type to get</param>
        ''' <param name="node">Where to report the error, if any.</param>
        Public Function GetSpecialType(typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As BindingDiagnosticBag) As NamedTypeSymbol
            Dim reportedAnError As Boolean = False
            Return GetSpecialType(Compilation, typeId, node, diagBag, reportedAnError, suppressUseSiteError:=False)
        End Function
 
        Public Shared Function GetSpecialType(compilation As VisualBasicCompilation, typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As BindingDiagnosticBag) As NamedTypeSymbol
            Dim reportedAnError As Boolean = False
            Return GetSpecialType(compilation, typeId, node, diagBag, reportedAnError, suppressUseSiteError:=False)
        End Function
 
        Public Function GetSpecialType(typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As BindingDiagnosticBag, ByRef reportedAnError As Boolean, suppressUseSiteError As Boolean) As NamedTypeSymbol
            Return GetSpecialType(Compilation, typeId, node, diagBag, reportedAnError, suppressUseSiteError)
        End Function
 
        Public Shared Function GetSpecialType(compilation As VisualBasicCompilation, typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As BindingDiagnosticBag, ByRef reportedAnError As Boolean, suppressUseSiteError As Boolean) As NamedTypeSymbol
            Dim symbol As NamedTypeSymbol = compilation.GetSpecialType(typeId)
 
            If diagBag IsNot Nothing Then
                Dim info = GetUseSiteInfoForSpecialType(symbol, suppressUseSiteError)
                If ReportUseSite(diagBag, node, info) Then
                    reportedAnError = True
                End If
            End If
 
            Return symbol
        End Function
 
        Friend Shared Function GetUseSiteInfoForSpecialType(type As TypeSymbol, Optional suppressUseSiteInfo As Boolean = False) As UseSiteInfo(Of AssemblySymbol)
            Dim info As UseSiteInfo(Of AssemblySymbol) = Nothing
            If type.TypeKind = TypeKind.Error AndAlso TypeOf type Is MissingMetadataTypeSymbol.TopLevel Then
                Dim missing = DirectCast(type, MissingMetadataTypeSymbol.TopLevel)
                info = New UseSiteInfo(Of AssemblySymbol)(ErrorFactory.ErrorInfo(ERRID.ERR_UndefinedType1, MetadataHelpers.BuildQualifiedName(missing.NamespaceName, missing.Name)))
            ElseIf Not suppressUseSiteInfo Then
                info = type.GetUseSiteInfo()
            End If
            Return info
        End Function
 
        ''' <summary>
        ''' This is a layer on top of the Compilation version that generates a diagnostic if the well-known
        ''' type isn't found.
        ''' </summary>
        Friend Function GetWellKnownType(type As WellKnownType, syntax As SyntaxNode, diagBag As BindingDiagnosticBag) As NamedTypeSymbol
            Return GetWellKnownType(Me.Compilation, type, syntax, diagBag)
        End Function
 
        Friend Shared Function GetWellKnownType(compilation As VisualBasicCompilation, type As WellKnownType, syntax As SyntaxNode, diagBag As BindingDiagnosticBag) As NamedTypeSymbol
            Dim typeSymbol As NamedTypeSymbol = compilation.GetWellKnownType(type)
            Debug.Assert(typeSymbol IsNot Nothing)
 
            Dim useSiteInfo = GetUseSiteInfoForWellKnownType(typeSymbol)
            ReportUseSite(diagBag, syntax, useSiteInfo)
 
            Return typeSymbol
        End Function
 
        Friend Shared Function GetUseSiteInfoForWellKnownType(type As TypeSymbol) As UseSiteInfo(Of AssemblySymbol)
            Return type.GetUseSiteInfo()
        End Function
 
        Private Function GetInternalXmlHelperType(syntax As VisualBasicSyntaxNode, diagBag As BindingDiagnosticBag) As NamedTypeSymbol
            Dim typeSymbol = GetInternalXmlHelperType()
 
            Dim useSiteInfo = GetUseSiteInfoForWellKnownType(typeSymbol)
            ReportUseSite(diagBag, syntax, useSiteInfo)
 
            Return typeSymbol
        End Function
 
        Private Function GetInternalXmlHelperType() As NamedTypeSymbol
            Const globalMetadataName = "My.InternalXmlHelper"
            Dim metadataName = globalMetadataName
 
            Dim rootNamespace = Me.Compilation.Options.RootNamespace
            If Not String.IsNullOrEmpty(rootNamespace) Then
                metadataName = $"{rootNamespace}.{metadataName}"
            End If
 
            Dim emittedName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding:=True)
            Dim result As NamedTypeSymbol = Me.ContainingModule.LookupTopLevelMetadataType(emittedName)
            Debug.Assert(If(Not result?.IsErrorType(), True))
 
            Return If(result, New MissingMetadataTypeSymbol.TopLevel(Me.ContainingModule, emittedName))
        End Function
 
        ''' <summary>
        ''' WARN: Retrieves the symbol but does not check its viability (accessibility, etc).
        ''' </summary>
        Private Function GetInternalXmlHelperValueExtensionProperty() As PropertySymbol
            For Each candidate As Symbol In GetInternalXmlHelperType().GetMembers("Value")
                If Not candidate.IsShared OrElse candidate.Kind <> SymbolKind.Property Then
                    Continue For
                End If
 
                Dim candidateProperty = DirectCast(candidate, PropertySymbol)
                If candidateProperty.Type.SpecialType <> SpecialType.System_String OrElse
                    candidateProperty.RefCustomModifiers.Length > 0 OrElse
                    candidateProperty.TypeCustomModifiers.Length > 0 OrElse
                    candidateProperty.ParameterCount <> 1 Then
 
                    Continue For
                End If
 
                Dim parameter = candidateProperty.Parameters(0)
                If parameter.CustomModifiers.Length > 0 OrElse parameter.RefCustomModifiers.Length > 0 Then
                    Continue For
                End If
 
                Dim parameterType = parameter.Type
                If parameterType.OriginalDefinition.SpecialType <> SpecialType.System_Collections_Generic_IEnumerable_T OrElse
                        Not TypeSymbol.Equals(DirectCast(parameterType, NamedTypeSymbol).TypeArgumentsNoUseSiteDiagnostics(0), Me.Compilation.GetWellKnownType(WellKnownType.System_Xml_Linq_XElement), TypeCompareKind.ConsiderEverything) Then
                    Continue For
                End If
 
                ' Only one symbol can match the criteria above, so we don't have to worry about ambiguity.
                Return candidateProperty
            Next
 
            Return Nothing
        End Function
 
        ''' <summary>
        ''' This is a layer on top of the assembly version that generates a diagnostic if the well-known
        ''' member isn't found.
        ''' </summary>
        Friend Function GetSpecialTypeMember(member As SpecialMember, syntax As SyntaxNode, diagnostics As BindingDiagnosticBag) As Symbol
            Return GetSpecialTypeMember(Me.ContainingMember.ContainingAssembly, member, syntax, diagnostics)
        End Function
 
        Friend Shared Function GetSpecialTypeMember(assembly As AssemblySymbol, member As SpecialMember, syntax As SyntaxNode, diagnostics As BindingDiagnosticBag) As Symbol
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
            Dim specialMemberSymbol As Symbol = GetSpecialTypeMember(assembly, member, useSiteInfo)
            ReportUseSite(diagnostics, syntax, useSiteInfo)
 
            Return specialMemberSymbol
        End Function
 
        Friend Shared Function GetSpecialTypeMember(assembly As AssemblySymbol, member As SpecialMember, <Out> ByRef useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As Symbol
            Dim specialMemberSymbol As Symbol = assembly.GetSpecialTypeMember(member)
 
            If specialMemberSymbol Is Nothing Then
                Dim memberDescriptor As MemberDescriptor = SpecialMembers.GetDescriptor(member)
                useSiteInfo = New UseSiteInfo(Of AssemblySymbol)(ErrorFactory.ErrorInfo(ERRID.ERR_MissingRuntimeHelper, memberDescriptor.DeclaringTypeMetadataName & "." & memberDescriptor.Name))
            Else
                useSiteInfo = GetUseSiteInfoForMemberAndContainingType(specialMemberSymbol)
            End If
 
            Return specialMemberSymbol
        End Function
 
        Friend Shared Function GetUseSiteInfoForMemberAndContainingType(member As Symbol) As UseSiteInfo(Of AssemblySymbol)
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = member.GetUseSiteInfo()
 
            If useSiteInfo.DiagnosticInfo Is Nothing Then
                member.MergeUseSiteInfo(useSiteInfo, member.ContainingType.GetUseSiteInfo())
            End If
 
            Return useSiteInfo
        End Function
 
        ''' <summary>
        ''' This is a layer on top of the Compilation version that generates a diagnostic if the well-known
        ''' member isn't found.
        ''' </summary>
        Friend Function GetWellKnownTypeMember(member As WellKnownMember, syntax As SyntaxNode, diagBag As BindingDiagnosticBag) As Symbol
            Return GetWellKnownTypeMember(Me.Compilation, member, syntax, diagBag)
        End Function
 
        Friend Shared Function GetWellKnownTypeMember(compilation As VisualBasicCompilation, member As WellKnownMember, syntax As SyntaxNode, diagBag As BindingDiagnosticBag) As Symbol
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
            Dim memberSymbol As Symbol = GetWellKnownTypeMember(compilation, member, useSiteInfo)
            ReportUseSite(diagBag, syntax, useSiteInfo)
 
            Return memberSymbol
        End Function
 
        Friend Shared Function GetWellKnownTypeMember(compilation As VisualBasicCompilation, member As WellKnownMember, <Out> ByRef useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As Symbol
            Dim memberSymbol As Symbol = compilation.GetWellKnownTypeMember(member)
 
            useSiteInfo = GetUseSiteInfoForWellKnownTypeMember(memberSymbol, member, compilation.Options.EmbedVbCoreRuntime)
 
            Return memberSymbol
        End Function
 
        Friend Shared Function GetUseSiteInfoForWellKnownTypeMember(memberSymbol As Symbol, member As WellKnownMember, embedVBRuntimeUsed As Boolean) As UseSiteInfo(Of AssemblySymbol)
            If memberSymbol Is Nothing Then
                Dim memberDescriptor As MemberDescriptor = WellKnownMembers.GetDescriptor(member)
 
                Return New UseSiteInfo(Of AssemblySymbol)(GetDiagnosticForMissingRuntimeHelper(memberDescriptor.DeclaringTypeMetadataName, memberDescriptor.Name, embedVBRuntimeUsed))
            Else
                Return GetUseSiteInfoForMemberAndContainingType(memberSymbol)
            End If
        End Function
 
        ''' <summary>
        ''' Get the source module.
        ''' </summary>
        Public ReadOnly Property SourceModule As SourceModuleSymbol
            Get
                Return _sourceModule
            End Get
        End Property
 
        ''' <summary>
        ''' Get the compilation.
        ''' </summary>
        Public ReadOnly Property Compilation As VisualBasicCompilation
            Get
                Return _compilation
            End Get
        End Property
 
        ''' <summary>
        ''' Get an error symbol.
        ''' </summary>
        Public Shared Function GetErrorSymbol(
            name As String,
            errorInfo As DiagnosticInfo,
            candidateSymbols As ImmutableArray(Of Symbol),
            resultKind As LookupResultKind,
            Optional reportErrorWhenReferenced As Boolean = False
        ) As ErrorTypeSymbol
            Return New ExtendedErrorTypeSymbol(errorInfo, name, 0, candidateSymbols, resultKind, reportErrorWhenReferenced)
        End Function
 
        Public Shared Function GetErrorSymbol(name As String, errorInfo As DiagnosticInfo, Optional reportErrorWhenReferenced As Boolean = False) As ErrorTypeSymbol
            Return GetErrorSymbol(name, errorInfo, ImmutableArray(Of Symbol).Empty, LookupResultKind.Empty, reportErrorWhenReferenced)
        End Function
 
        ''' <summary>
        ''' Get the Location associated with a given TextSpan.
        ''' </summary>
        Public Function GetLocation(span As TextSpan) As Location
            Return Me.SyntaxTree.GetLocation(span)
        End Function
 
        ''' <summary>
        ''' Get a SyntaxReference associated with a given syntax node.
        ''' </summary>
        Public Overridable Function GetSyntaxReference(node As VisualBasicSyntaxNode) As SyntaxReference
            Return m_containingBinder.GetSyntaxReference(node)
        End Function
 
        ''' <summary>
        ''' Returns the syntax tree.
        ''' </summary>
        Public ReadOnly Property SyntaxTree As SyntaxTree
            Get
                Return _syntaxTree
            End Get
        End Property
 
        ''' <summary>
        ''' Called in member lookup right before going into the base class of a type. Results a set of named types whose
        ''' bases classes are currently in the process of being resolved, so we shouldn't look into their bases
        ''' again to prevent/detect circular references.
        ''' </summary>
        ''' <returns>Nothing if no bases being resolved, otherwise the set of bases being resolved.</returns>
        Public Function BasesBeingResolved() As BasesBeingResolved
            Return _basesBeingResolved
        End Function
 
        Friend Overridable ReadOnly Property ConstantFieldsInProgress As ConstantFieldsInProgress
            Get
                Return m_containingBinder.ConstantFieldsInProgress
            End Get
        End Property
 
        Friend Overridable ReadOnly Property DefaultParametersInProgress As SymbolsInProgress(Of ParameterSymbol)
            Get
                Return m_containingBinder.DefaultParametersInProgress
            End Get
        End Property
 
        ''' <summary>
        ''' Called during member lookup before going into the base class of a type. If returns
        ''' true, the base class is ignored. Primarily used for binding Imports.
        ''' </summary>
        Public ReadOnly Property IgnoreBaseClassesInLookup As Boolean
            Get
                Return _ignoreBaseClassesInLookup
            End Get
        End Property
 
        ''' <summary>
        ''' Current Option Strict mode.
        ''' </summary>
        Public Overridable ReadOnly Property OptionStrict As OptionStrict
            Get
                Return m_containingBinder.OptionStrict
            End Get
        End Property
 
        ''' <summary>
        ''' True if Option Infer On is in effect. False if Option Infer Off is in effect.
        ''' </summary>
        Public Overridable ReadOnly Property OptionInfer As Boolean
            Get
                Return m_containingBinder.OptionInfer
            End Get
        End Property
 
        ''' <summary>
        ''' True if Option Explicit On is in effect. False if Option Explicit Off is in effect.
        ''' Note that even if Option Explicit Off is in effect, there are places (field initializers)
        ''' where implicit variable declaration is not permitted. See the ImplicitVariablesDeclarationAllowedHere
        ''' property also.
        ''' </summary>
        Public Overridable ReadOnly Property OptionExplicit As Boolean
            Get
                Return m_containingBinder.OptionExplicit
            End Get
        End Property
 
        ''' <summary>
        ''' True if Option Compare Text is in effect. False if Option Compare Binary is in effect.
        ''' </summary>
        Public Overridable ReadOnly Property OptionCompareText As Boolean
            Get
                Return m_containingBinder.OptionCompareText
            End Get
        End Property
 
        ''' <summary>
        ''' True if integer overflow checking is On.
        ''' </summary>
        Public Overridable ReadOnly Property CheckOverflow As Boolean
            Get
                Return m_containingBinder.CheckOverflow
            End Get
        End Property
 
        ''' <summary>
        ''' True if implicit variable declaration is available within this binder, and the binder
        ''' has already finished binding all possible implicit declarations inside (and is not accepting)
        ''' any more.
        ''' </summary>
        Public Overridable ReadOnly Property AllImplicitVariableDeclarationsAreHandled As Boolean
            Get
                Return m_containingBinder.AllImplicitVariableDeclarationsAreHandled
            End Get
        End Property
 
        ''' <summary>
        ''' True if implicit variable declaration is allow by the language here. Differs from OptionExplicit
        ''' in that it is only try if this binder is associated with a region that allows implicit variable
        ''' declaration (field initializers and attributes don't, for example).
        ''' </summary>
        Public Overridable ReadOnly Property ImplicitVariableDeclarationAllowed As Boolean
            Get
                Return m_containingBinder.ImplicitVariableDeclarationAllowed
            End Get
        End Property
 
        ''' <summary>
        ''' Declare an implicit local variable. The type of the local is determined
        ''' by the type character (if any) on the variable.
        ''' </summary>
        Public Overridable Function DeclareImplicitLocalVariable(nameSyntax As IdentifierNameSyntax, diagnostics As BindingDiagnosticBag) As LocalSymbol
            Debug.Assert(Not Me.AllImplicitVariableDeclarationsAreHandled)
            Return m_containingBinder.DeclareImplicitLocalVariable(nameSyntax, diagnostics)
        End Function
 
        ''' <summary>
        ''' Get all implicitly declared variables that were declared in this method body.
        ''' </summary>
        Public Overridable ReadOnly Property ImplicitlyDeclaredVariables As ImmutableArray(Of LocalSymbol)
            Get
                Return m_containingBinder.ImplicitlyDeclaredVariables
            End Get
        End Property
 
        ''' <summary>
        ''' Disallow additional local variable declaration and report delayed shadowing diagnostics.
        ''' </summary>
        ''' <remarks></remarks>
        Public Overridable Sub DisallowFurtherImplicitVariableDeclaration(diagnostics As BindingDiagnosticBag)
            m_containingBinder.DisallowFurtherImplicitVariableDeclaration(diagnostics)
        End Sub
 
#If DEBUG Then
        ' In DEBUG, this method (overridden in ExecutableCodeBinder) checks that identifiers are bound in order,
        ' which ensures that implicit variable declaration will work correctly.
        Public Overridable Sub CheckSimpleNameBindingOrder(node As SimpleNameSyntax)
            m_containingBinder.CheckSimpleNameBindingOrder(node)
        End Sub
 
        Public Overridable Sub EnableSimpleNameBindingOrderChecks(enable As Boolean)
            m_containingBinder.EnableSimpleNameBindingOrderChecks(enable)
        End Sub
 
        ' Helper to allow displaying the binder hierarchy in the debugger.
        Friend Function GetAllBinders() As Binder()
            Dim binders = ArrayBuilder(Of Binder).GetInstance()
            Dim binder = Me
            While binder IsNot Nothing
                binders.Add(binder)
                binder = binder.ContainingBinder
            End While
            Return binders.ToArrayAndFree()
        End Function
#End If
 
        ''' <summary>
        ''' Get the label that a Exit XXX statement should branch to, or Nothing if we are
        ''' not inside a context that would be exited by that kind of statement. The passed in kind
        ''' is the SyntaxKind for the exit statement that would target the label (e.g. SyntaxKind.ExitDoStatement).
        ''' </summary>
        Public Overridable Function GetExitLabel(exitSyntaxKind As SyntaxKind) As LabelSymbol
            Return m_containingBinder.GetExitLabel(exitSyntaxKind)
        End Function
 
        ''' <summary>
        ''' Get the label that a Continue XXX statement should branch to, or Nothing if we are
        ''' not inside a context that would be exited by that kind of statement. The passed in kind
        ''' is the SyntaxKind for the exit statement that would target the label (e.g. SyntaxKind.ContinueDoStatement).
        ''' </summary>
        Public Overridable Function GetContinueLabel(continueSyntaxKind As SyntaxKind) As LabelSymbol
            Return m_containingBinder.GetContinueLabel(continueSyntaxKind)
        End Function
 
        ''' <summary>
        ''' Get the label that a Return statement should branch to, or Nothing if we are
        ''' not inside a context that would be exited by that kind of statement. This method
        ''' is equivalent to calling <see cref="GetExitLabel"/> with the appropriate exit
        ''' <see cref="SyntaxKind"/>.
        ''' </summary>
        Public Overridable Function GetReturnLabel() As LabelSymbol
            Return m_containingBinder.GetReturnLabel()
        End Function
 
        ''' <summary>
        ''' Get the special local symbol with the same name as the enclosing function.
        ''' </summary>
        Public Overridable Function GetLocalForFunctionValue() As LocalSymbol
            Return m_containingBinder.GetLocalForFunctionValue()
        End Function
 
        ''' <summary>
        ''' Create a diagnostic at a particular syntax node and place it in a diagnostic bag.
        ''' </summary>
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, syntax As SyntaxNodeOrToken, id As ERRID)
            ReportDiagnostic(diagBag, syntax, ErrorFactory.ErrorInfo(id))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, syntax As SyntaxNodeOrToken, id As ERRID, ParamArray args As Object())
            ReportDiagnostic(diagBag, syntax, ErrorFactory.ErrorInfo(id, args))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, syntax As SyntaxNodeOrToken, info As DiagnosticInfo)
            Dim diag As New VBDiagnostic(info, syntax.GetLocation())
            ReportDiagnostic(diagBag, diag)
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, location As Location, id As ERRID)
            ReportDiagnostic(diagBag, location, ErrorFactory.ErrorInfo(id))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, location As Location, id As ERRID, ParamArray args As Object())
            ReportDiagnostic(diagBag, location, ErrorFactory.ErrorInfo(id, args))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, location As Location, info As DiagnosticInfo)
            Dim diag As New VBDiagnostic(info, location)
            ReportDiagnostic(diagBag, diag)
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As DiagnosticBag, diag As Diagnostic)
            diagBag.Add(diag)
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, syntax As SyntaxNodeOrToken, id As ERRID)
            ReportDiagnostic(diagBag, syntax, ErrorFactory.ErrorInfo(id))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, syntax As SyntaxNodeOrToken, id As ERRID, ParamArray args As Object())
            ReportDiagnostic(diagBag, syntax, ErrorFactory.ErrorInfo(id, args))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, syntax As SyntaxNodeOrToken, info As DiagnosticInfo)
            Dim diag As New VBDiagnostic(info, syntax.GetLocation())
            ReportDiagnostic(diagBag, diag)
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, location As Location, id As ERRID)
            ReportDiagnostic(diagBag, location, ErrorFactory.ErrorInfo(id))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, location As Location, id As ERRID, ParamArray args As Object())
            ReportDiagnostic(diagBag, location, ErrorFactory.ErrorInfo(id, args))
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, location As Location, info As DiagnosticInfo)
            Dim diag As New VBDiagnostic(info, location)
            ReportDiagnostic(diagBag, diag)
        End Sub
 
        Public Shared Sub ReportDiagnostic(diagBag As BindingDiagnosticBag, diag As Diagnostic)
            diagBag.Add(diag)
        End Sub
 
        Public Shared Function ReportUseSite(diagBag As BindingDiagnosticBag, syntax As SyntaxNodeOrToken, useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As Boolean
            Return diagBag.Add(useSiteInfo, syntax.GetLocation())
        End Function
 
        Public Shared Function ReportUseSite(diagBag As BindingDiagnosticBag, location As Location, useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As Boolean
            Return diagBag.Add(useSiteInfo, location)
        End Function
 
        Public Sub AddTypesAssemblyAsDependency(namespaceOrType As NamespaceOrTypeSymbol, diagBag As BindingDiagnosticBag)
            Dim container As AssemblySymbol = TryCast(namespaceOrType, NamedTypeSymbol)?.ContainingAssembly
            If container IsNot Nothing AndAlso container <> Compilation.Assembly AndAlso container <> Compilation.Assembly.CorLibrary Then
                diagBag.AddDependency(container)
            End If
        End Sub
 
        ''' <summary>
        ''' Issue an error or warning for a symbol if it is Obsolete. If there is not enough
        ''' information to report diagnostics, then store the symbols so that diagnostics
        ''' can be reported at a later stage.
        ''' Also, check runtime/language support for the symbol.
        ''' </summary>
        Friend Sub ReportDiagnosticsIfObsoleteOrNotSupported(diagnostics As BindingDiagnosticBag, symbol As Symbol, node As SyntaxNode)
            If Not Me.SuppressObsoleteDiagnostics Then
                ReportDiagnosticsIfObsolete(diagnostics, Me.ContainingMember, symbol, node)
            End If
 
            If Not IsNameOfArgument(node) AndAlso
               symbol.Kind <> SymbolKind.Property AndAlso
               Compilation.SourceModule IsNot symbol.ContainingModule AndAlso
               If(symbol.ContainingType?.IsInterface, False) Then
 
                If symbol.IsShared AndAlso
                   symbol.RequiresImplementation() Then
                    ReportDiagnostic(diagnostics, node, ERRID.ERR_BadAbstractStaticMemberAccess)
 
                ElseIf Not Compilation.Assembly.RuntimeSupportsDefaultInterfaceImplementation Then
                    If Not symbol.IsShared AndAlso
                       Not TypeOf symbol Is TypeSymbol AndAlso
                       Not symbol.RequiresImplementation() Then
                        ReportDiagnostic(diagnostics, node, ERRID.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation)
                    Else
                        Select Case symbol.DeclaredAccessibility
                            Case Accessibility.Protected,
                             Accessibility.ProtectedOrInternal,
                             Accessibility.ProtectedAndInternal
 
                                ReportDiagnostic(diagnostics, node, ERRID.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember)
                        End Select
                    End If
                End If
            End If
        End Sub
 
        Friend Shared Sub ReportDiagnosticsIfObsolete(diagnostics As BindingDiagnosticBag, context As Symbol, symbol As Symbol, node As SyntaxNode)
            Dim kind = ObsoleteAttributeHelpers.GetObsoleteDiagnosticKind(context, symbol)
 
            Dim info As DiagnosticInfo = Nothing
            Select Case kind
                Case ObsoleteDiagnosticKind.Diagnostic
                    info = ObsoleteAttributeHelpers.CreateObsoleteDiagnostic(symbol)
                Case ObsoleteDiagnosticKind.Lazy, ObsoleteDiagnosticKind.LazyPotentiallySuppressed
                    info = New LazyObsoleteDiagnosticInfo(symbol, context)
            End Select
 
            If info IsNot Nothing Then
                diagnostics.Add(info, node.GetLocation())
            End If
        End Sub
 
        Friend Overridable ReadOnly Property SuppressObsoleteDiagnostics As Boolean
            Get
                Return m_containingBinder.SuppressObsoleteDiagnostics
            End Get
        End Property
 
        ''' <summary>
        ''' Returns the type of construct being bound (BaseTypes, MethodSignature,
        ''' etc.) to allow the Binder to provide different behavior in certain cases.
        ''' Currently, this property is only used by ShouldCheckConstraints.
        ''' </summary>
        Public Overridable ReadOnly Property BindingLocation As BindingLocation
            Get
                Return m_containingBinder.BindingLocation
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if the binder is performing early decoding of a
        ''' (well-known) attribute.
        ''' </summary>
        Public ReadOnly Property IsEarlyAttributeBinder As Boolean
            Get
                Return _isEarlyAttributeBinder
            End Get
        End Property
 
        ''' <summary>
        ''' Return True if type constraints should be checked when binding.
        ''' </summary>
        Friend ReadOnly Property ShouldCheckConstraints As Boolean
            Get
                Select Case Me.BindingLocation
                    Case BindingLocation.BaseTypes,
                         BindingLocation.MethodSignature,
                         BindingLocation.FieldType,
                         BindingLocation.PropertyType,
                         BindingLocation.EventType,
                         BindingLocation.GenericConstraintsClause,
                         BindingLocation.ProjectImportsDeclaration,
                         BindingLocation.SourceFileImportsDeclaration
                        Return False
 
                    Case Else
                        Return True
 
                End Select
            End Get
        End Property
 
        ''' <summary>
        ''' Returns True if the binder, or any containing binder, has xmlns Imports.
        ''' </summary>
        Friend Overridable ReadOnly Property HasImportedXmlNamespaces As Boolean
            Get
                Return m_containingBinder.HasImportedXmlNamespaces
            End Get
        End Property
 
        ''' <summary>
        ''' Add { prefix, namespace } pairs from the explicitly declared namespaces in the
        ''' XmlElement hierarchy. The order of the pairs is the order the xmlns attributes
        ''' are declared on each element, and from innermost to outermost element.
        ''' </summary>
        Friend Overridable Sub GetInScopeXmlNamespaces(builder As ArrayBuilder(Of KeyValuePair(Of String, String)))
            m_containingBinder.GetInScopeXmlNamespaces(builder)
        End Sub
 
        Friend Overridable Function LookupXmlNamespace(prefix As String, ignoreXmlNodes As Boolean, <Out()> ByRef [namespace] As String, <Out()> ByRef fromImports As Boolean) As Boolean
            Return m_containingBinder.LookupXmlNamespace(prefix, ignoreXmlNodes, [namespace], fromImports)
        End Function
 
        ''' <summary>
        ''' This method reports use site errors if a required attribute constructor is missing.
        ''' Some attributes are considered to be optional (e.g. the CompilerGeneratedAttribute). In this case the use site
        ''' errors will be ignored.
        ''' </summary>
        Friend Function ReportUseSiteInfoForSynthesizedAttribute(
            attributeCtor As WellKnownMember,
            syntax As VisualBasicSyntaxNode,
            diagnostics As BindingDiagnosticBag
        ) As Boolean
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
 
            Dim ctor As Symbol = GetWellKnownTypeMember(Me.Compilation, attributeCtor, useSiteInfo)
 
            If Not WellKnownMembers.IsSynthesizedAttributeOptional(attributeCtor) Then
                Debug.Assert(diagnostics IsNot Nothing)
 
                If ReportUseSite(diagnostics, syntax, useSiteInfo) Then
                    Return True
                End If
            Else
                diagnostics.AddDependencies(useSiteInfo)
            End If
 
            Return False
        End Function
 
        ''' <summary>
        ''' This method reports use site errors if a required attribute constructor is missing.
        ''' Some attributes are considered to be optional (e.g. the CompilerGeneratedAttribute). In this case the use site
        ''' errors will be ignored.
        ''' </summary>
        Friend Shared Function ReportUseSiteInfoForSynthesizedAttribute(
            attributeCtor As WellKnownMember,
            compilation As VisualBasicCompilation,
            location As Location,
            diagnostics As BindingDiagnosticBag
        ) As Boolean
            Dim memberSymbol = compilation.GetWellKnownTypeMember(attributeCtor)
            Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = GetUseSiteInfoForWellKnownTypeMember(memberSymbol, attributeCtor, compilation.Options.EmbedVbCoreRuntime)
 
            If Not WellKnownMembers.IsSynthesizedAttributeOptional(attributeCtor) Then
                Debug.Assert(diagnostics IsNot Nothing)
 
                If diagnostics.Add(useSiteInfo, location) Then
                    Return True
                End If
            Else
                diagnostics.AddDependencies(useSiteInfo)
            End If
 
            Return False
        End Function
 
        ''' <summary>
        ''' Returns a placeholder substitute for a With statement placeholder specified or Nothing if not found
        '''
        ''' Note: 'placeholder' is needed to make sure the binder can check that the placeholder is
        ''' associated with the statement.
        ''' </summary>
        Friend Overridable Function GetWithStatementPlaceholderSubstitute(placeholder As BoundValuePlaceholderBase) As BoundExpression
            Return m_containingBinder.GetWithStatementPlaceholderSubstitute(placeholder)
        End Function
 
        ''' <summary>
        ''' Indicates that this binder is being used to answer SemanticModel questions (i.e. not
        ''' for batch compilation).
        ''' </summary>
        ''' <remarks>
        ''' Imports touched by a binder with this flag set are not consider "used".
        ''' </remarks>
        Public Overridable ReadOnly Property IsSemanticModelBinder As Boolean
            Get
                Return m_containingBinder.IsSemanticModelBinder
            End Get
        End Property
 
        Public Overridable ReadOnly Property QuickAttributeChecker As QuickAttributeChecker
            Get
                Return m_containingBinder.QuickAttributeChecker
            End Get
        End Property
    End Class
 
End Namespace