/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/Binder.vb
1 153 строки
55 KB
AlekseyTs
VB: Recognize and check an `unmanaged` constraint (#75665)
06 ноя 2024, 01:45
Не верифицирован
06 ноя 2024, 01:45
f97c50e
Код
Авторство
О чём код?
' 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