/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/Binder_Lookup.vb
2 167 строк
113 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.Runtime.InteropServices Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports TypeKind = Microsoft.CodeAnalysis.TypeKind Namespace Microsoft.CodeAnalysis.VisualBasic ' Handler the parts of binding for member lookup. Partial Friend Class Binder Friend Sub LookupMember(lookupResult As LookupResult, container As NamespaceOrTypeSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) MemberLookup.Lookup(lookupResult, container, name, arity, options, Me, useSiteInfo) End Sub Friend Sub LookupMember(lookupResult As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) Dim tempResult = lookupResult.GetInstance() MemberLookup.Lookup(lookupResult, container, name, arity, options, Me, tempResult, useSiteInfo) tempResult.Free() End Sub Friend Sub LookupMember(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) MemberLookup.Lookup(lookupResult, container, name, arity, options, Me, useSiteInfo) End Sub Friend Sub LookupMemberImmediate(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) MemberLookup.LookupImmediate(lookupResult, container, name, arity, options, Me, useSiteInfo) End Sub Friend Sub LookupExtensionMethods( lookupResult As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(options.IsValid()) Debug.Assert(lookupResult.IsClear) options = BinderSpecificLookupOptions(options) MemberLookup.LookupForExtensionMethods(lookupResult, container, name, arity, options, Me, useSiteInfo) End Sub Friend Sub LookupMemberInModules(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) MemberLookup.LookupInModules(lookupResult, container, name, arity, options, Me, useSiteInfo) End Sub Friend Sub AddMemberLookupSymbolsInfo(nameSet As LookupSymbolsInfo, container As NamespaceOrTypeSymbol, options As LookupOptions) Debug.Assert(options.IsValid()) options = BinderSpecificLookupOptions(options) MemberLookup.AddLookupSymbolsInfo(nameSet, container, options, Me) End Sub ' Validates a symbol to check if it ' a) has the right arity ' b) is accessible. (accessThroughType is passed in for protected access checks) ' c) matches the lookup options. ' A non-empty SingleLookupResult with the result is returned. ' ' For symbols from outside of this compilation the method also checks ' if the symbol is marked with 'Microsoft.VisualBasic.Embedded' or 'Microsoft.CodeAnalysis.Embedded' attributes. ' ' If arity passed in is -1, no arity checks are done. Friend Function CheckViability(sym As Symbol, arity As Integer, options As LookupOptions, accessThroughType As TypeSymbol, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As SingleLookupResult Debug.Assert(sym IsNot Nothing) If Not sym.CanBeReferencedByNameIgnoringIllegalCharacters Then Return SingleLookupResult.Empty End If If (options And LookupOptions.LabelsOnly) <> 0 Then ' If LabelsOnly is set then the symbol must be a label otherwise return empty If options = LookupOptions.LabelsOnly AndAlso sym.Kind = SymbolKind.Label Then Return SingleLookupResult.Good(sym) End If ' Mixing LabelsOnly with any other flag returns an empty result Return SingleLookupResult.Empty End If If (options And LookupOptions.MustNotBeReturnValueVariable) <> 0 Then '§11.4.4 Simple Name Expressions ' If the identifier matches a local variable, the local variable matched is ' the implicit function or Get accessor return local variable, and the expression ' is part of an invocation expression, invocation statement, or an AddressOf ' expression, then no match occurs and resolution continues. ' ' LookupOptions.MustNotBeReturnValueVariable is set if "the expression ' is part of an invocation expression, invocation statement, or an AddressOf ' expression", and we then skip return value variables. ' We'll always bind to the containing method or property instead further on in the lookup process. If sym.Kind = SymbolKind.Local AndAlso DirectCast(sym, LocalSymbol).IsFunctionValue Then Return SingleLookupResult.Empty End If End If Dim unwrappedSym = sym Dim asAlias = TryCast(sym, AliasSymbol) If asAlias IsNot Nothing Then unwrappedSym = asAlias.Target End If ' Check for external symbols marked with 'Microsoft.VisualBasic.Embedded' or 'Microsoft.CodeAnalysis.Embedded' attributes If unwrappedSym.ContainingModule IsNot Me.ContainingModule Then If unwrappedSym.IsHiddenByVisualBasicEmbeddedAttribute() OrElse unwrappedSym.IsHiddenByCodeAnalysisEmbeddedAttribute() Then Return SingleLookupResult.Empty End If End If If unwrappedSym.Kind = SymbolKind.NamedType AndAlso unwrappedSym.EmbeddedSymbolKind = EmbeddedSymbolKind.EmbeddedAttribute AndAlso Me.SyntaxTree IsNot Nothing AndAlso Me.SyntaxTree.GetEmbeddedKind = EmbeddedSymbolKind.None Then ' Only allow direct access to Microsoft.VisualBasic.Embedded attribute ' from user code if current compilation embeds Vb Core If Not Me.Compilation.Options.EmbedVbCoreRuntime Then Return SingleLookupResult.Empty End If End If ' Do arity checking, unless specifically asked not to. ' Only types and namespaces in VB shadow by arity. All other members shadow ' regardless of arity. So, we only check arity on types. If arity <> -1 Then Select Case sym.Kind Case SymbolKind.NamedType, SymbolKind.ErrorType Dim actualArity As Integer = DirectCast(sym, NamedTypeSymbol).Arity If actualArity <> arity Then Return SingleLookupResult.WrongArity(sym, WrongArityErrid(actualArity, arity)) End If Case SymbolKind.TypeParameter, SymbolKind.Namespace If arity <> 0 Then ' type parameters and namespaces are always arity 0 Return SingleLookupResult.WrongArity(unwrappedSym, WrongArityErrid(0, arity)) End If Case SymbolKind.Alias ' Since raw generics cannot be imported, the import aliases would always refer to ' constructed types when referring to generics. So any other generic arity besides ' -1 or 0 are invalid. If arity <> 0 Then ' aliases are always arity 0, but error refers to the target ' Note, Dev11 doesn't stop lookup in case of arity mismatch for an alias. Return SingleLookupResult.WrongArity(unwrappedSym, WrongArityErrid(0, arity)) End If Case SymbolKind.Method ' Unlike types and namespaces, we always stop looking if we find a method with the right name but wrong arity. ' The arity matching rules for methods are customizable for the LookupOptions; when binding expressions ' we always pass AllMethodsOfAnyArity and allow overload resolution to filter methods. The other flags ' are for binding API scenarios. Dim actualArity As Integer = DirectCast(sym, MethodSymbol).Arity If actualArity <> arity AndAlso Not ((options And LookupOptions.AllMethodsOfAnyArity) <> 0) Then Return SingleLookupResult.WrongArityAndStopLookup(sym, WrongArityErrid(actualArity, arity)) End If Case Else ' Unlike types and namespace, we stop looking if we find other symbols with wrong arity. ' All these symbols have arity 0. If arity <> 0 Then Return SingleLookupResult.WrongArityAndStopLookup(sym, WrongArityErrid(0, arity)) End If End Select End If If (options And LookupOptions.IgnoreAccessibility) = 0 Then Dim accessCheckResult = CheckAccessibility(unwrappedSym, useSiteInfo, If((options And LookupOptions.UseBaseReferenceAccessibility) <> 0, Nothing, accessThroughType)) ' Check if we are in 'MyBase' resolving mode and we need to ignore 'accessThroughType' to make protected members accessed If accessCheckResult <> VisualBasic.AccessCheckResult.Accessible Then Return SingleLookupResult.Inaccessible(sym, GetInaccessibleErrorInfo(sym)) End If End If If (options And Global.Microsoft.CodeAnalysis.VisualBasic.LookupOptions.MustNotBeInstance) <> 0 AndAlso sym.IsInstanceMember Then Return Global.Microsoft.CodeAnalysis.VisualBasic.SingleLookupResult.MustNotBeInstance(sym, Global.Microsoft.CodeAnalysis.VisualBasic.ERRID.ERR_ObjectReferenceNotSupplied) ElseIf (options And Global.Microsoft.CodeAnalysis.VisualBasic.LookupOptions.MustBeInstance) <> 0 AndAlso Not sym.IsInstanceMember Then Return Global.Microsoft.CodeAnalysis.VisualBasic.SingleLookupResult.MustBeInstance(sym) ' there is no error message for this End If Return SingleLookupResult.Good(sym) End Function Friend Function GetInaccessibleErrorInfo(sym As Symbol) As DiagnosticInfo Dim unwrappedSym = sym Dim asAlias = TryCast(sym, AliasSymbol) If asAlias IsNot Nothing Then unwrappedSym = asAlias.Target ElseIf sym.Kind = SymbolKind.Method Then sym = DirectCast(sym, MethodSymbol).ConstructedFrom End If Dim diagInfo As DiagnosticInfo ' for inaccessible members (in e.g. AddressOf expressions, DEV10 shows a ERR_InaccessibleMember3 diagnostic) ' TODO maybe this condition needs to be adjusted to be shown in cases of e.g. inaccessible properties If unwrappedSym.Kind = SymbolKind.Method AndAlso unwrappedSym.ContainingSymbol IsNot Nothing Then diagInfo = New BadSymbolDiagnostic(sym, ERRID.ERR_InaccessibleMember3, sym.ContainingSymbol.Name, sym, AccessCheck.GetAccessibilityForErrorMessage(sym, Me.Compilation.Assembly)) Else diagInfo = New BadSymbolDiagnostic(sym, ERRID.ERR_InaccessibleSymbol2, CustomSymbolDisplayFormatter.QualifiedName(sym), AccessCheck.GetAccessibilityForErrorMessage(sym, sym.ContainingAssembly)) End If Debug.Assert(diagInfo.Severity = DiagnosticSeverity.Error) Return diagInfo End Function ''' <summary> ''' Used by Add*LookupSymbolsInfo* to determine whether the symbol is of interest. ''' Distinguish from <see cref="CheckViability"/>, which performs an analogous task for LookupSymbols*. ''' </summary> ''' <remarks> ''' Does not consider <see cref="Symbol.CanBeReferencedByName"/> - that is left to the caller. ''' </remarks> Friend Function CanAddLookupSymbolInfo(sym As Symbol, options As LookupOptions, nameSet As LookupSymbolsInfo, accessThroughType As TypeSymbol) As Boolean Debug.Assert(sym IsNot Nothing) If Not nameSet.CanBeAdded(sym.Name) Then Return False End If Dim singleResult = CheckViability(sym, -1, options, accessThroughType, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) If (options And LookupOptions.MethodsOnly) <> 0 AndAlso sym.Kind <> SymbolKind.Method Then Return False End If If singleResult.IsGoodOrAmbiguous Then ' Its possible there is an error (ambiguity, wrong arity) associated with result. ' We still return true here, because binding finds that symbol and doesn't continue. ' NOTE: We're going to let the SemanticModel check for symbols that can't be ' referenced by name. That way, it can either filter them or not, depending ' on whether a name was passed to LookupSymbols. Return True End If Return False End Function ' return the error id for mismatched arity. Private Shared Function WrongArityErrid(actualArity As Integer, arity As Integer) As ERRID If actualArity < arity Then If actualArity = 0 Then Return ERRID.ERR_TypeOrMemberNotGeneric1 Else Return ERRID.ERR_TooManyGenericArguments1 End If Else Debug.Assert(actualArity > arity, "arities shouldn't match") Return ERRID.ERR_TooFewGenericArguments1 End If End Function ''' <summary> ''' This class handles binding of members of namespaces and types. ''' The key member is Lookup, which handles looking up a name ''' in a namespace or type, by name and arity, and produces a ''' lookup result. ''' </summary> Private Class MemberLookup ''' <summary> ''' Lookup a member name in a namespace or type, returning a LookupResult that ''' summarizes the results of the lookup. See LookupResult structure for a detailed ''' discussing of the meaning of the results. The supplied binder is used for accessibility ''' checked and base class suppression. ''' </summary> Public Shared Sub Lookup(lookupResult As LookupResult, container As NamespaceOrTypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) If container.IsNamespace Then Lookup(lookupResult, DirectCast(container, NamespaceSymbol), name, arity, options, binder, useSiteInfo) Else Dim tempResult = lookupResult.GetInstance() Lookup(lookupResult, DirectCast(container, TypeSymbol), name, arity, options, binder, tempResult, useSiteInfo) tempResult.Free() End If End Sub ' Lookup all the names available on the given container, that match the given lookup options. ' The supplied binder is used for accessibility checking. Public Shared Sub AddLookupSymbolsInfo(nameSet As LookupSymbolsInfo, container As NamespaceOrTypeSymbol, options As LookupOptions, binder As Binder) If container.IsNamespace Then AddLookupSymbolsInfo(nameSet, DirectCast(container, NamespaceSymbol), options, binder) Else AddLookupSymbolsInfo(nameSet, DirectCast(container, TypeSymbol), options, binder) End If End Sub ''' <summary> ''' Lookup a member name in a namespace, returning a LookupResult that ''' summarizes the results of the lookup. See LookupResult structure for a detailed ''' discussing of the meaning of the results. The supplied binder is used for accessibility ''' checked and base class suppression. ''' </summary> Public Shared Sub Lookup(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(lookupResult.IsClear) LookupImmediate(lookupResult, container, name, arity, options, binder, useSiteInfo) ' Result in the namespace takes precedence over results in containing modules. If lookupResult.StopFurtherLookup Then Return End If Dim currentResult = lookupResult.GetInstance() LookupInModules(currentResult, container, name, arity, options, binder, useSiteInfo) lookupResult.MergeAmbiguous(currentResult, s_ambiguousInModuleError) currentResult.Free() End Sub ''' <summary> ''' Lookup an immediate (without descending into modules) member name in a namespace, ''' returning a LookupResult that summarizes the results of the lookup. ''' See LookupResult structure for a detailed discussion of the meaning of the results. ''' The supplied binder is used for accessibility checks and base class suppression. ''' </summary> Public Shared Sub LookupImmediate(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(lookupResult.IsClear) Dim sourceModule = binder.Compilation.SourceModule ' Handle a case of being able to refer to System.Int32 through System.Integer. ' Same for other intrinsic types with intrinsic name different from emitted name. If (options And LookupOptions.AllowIntrinsicAliases) <> 0 AndAlso arity = 0 Then Dim containingNs = container.ContainingNamespace If containingNs IsNot Nothing AndAlso containingNs.IsGlobalNamespace AndAlso CaseInsensitiveComparison.Equals(container.Name, MetadataHelpers.SystemString) Then Dim specialType = GetTypeForIntrinsicAlias(name) If specialType <> specialType.None Then Dim candidate = binder.Compilation.GetSpecialType(specialType) ' Intrinsic alias works only if type is available If Not candidate.IsErrorType() Then lookupResult.MergeMembersOfTheSameNamespace(binder.CheckViability(candidate, arity, options, Nothing, useSiteInfo), sourceModule, options) End If End If End If End If #If DEBUG Then Dim haveSeenNamespace As Boolean = False #End If For Each sym In container.GetMembers(name) #If DEBUG Then If sym.Kind = SymbolKind.Namespace Then Debug.Assert(Not haveSeenNamespace, "Expected namespaces to be merged into a single symbol.") haveSeenNamespace = True End If #End If Dim currentResult As SingleLookupResult = binder.CheckViability(sym, arity, options, Nothing, useSiteInfo) lookupResult.MergeMembersOfTheSameNamespace(currentResult, sourceModule, options) Next End Sub Public Shared Function GetTypeForIntrinsicAlias(possibleAlias As String) As SpecialType Dim aliasAsKeyword As SyntaxKind = SyntaxFacts.GetKeywordKind(possibleAlias) Select Case aliasAsKeyword Case SyntaxKind.DateKeyword Return SpecialType.System_DateTime Case SyntaxKind.UShortKeyword Return SpecialType.System_UInt16 Case SyntaxKind.ShortKeyword Return SpecialType.System_Int16 Case SyntaxKind.UIntegerKeyword Return SpecialType.System_UInt32 Case SyntaxKind.IntegerKeyword Return SpecialType.System_Int32 Case SyntaxKind.ULongKeyword Return SpecialType.System_UInt64 Case SyntaxKind.LongKeyword Return SpecialType.System_Int64 Case Else Return SpecialType.None End Select End Function ''' <summary> ''' Lookup a member name in modules of a namespace, ''' returning a LookupResult that summarizes the results of the lookup. ''' See LookupResult structure for a detailed discussion of the meaning of the results. ''' The supplied binder is used for accessibility checks and base class suppression. ''' </summary> Public Shared Sub LookupInModules(lookupResult As LookupResult, container As NamespaceSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(lookupResult.IsClear) Dim firstModule As Boolean = True Dim sourceModule = binder.Compilation.SourceModule ' NOTE: while looking up the symbol in modules we should ignore base class options = options Or LookupOptions.IgnoreExtensionMethods Or LookupOptions.NoBaseClassLookup Dim currentResult As LookupResult = Nothing Dim tempResult = lookupResult.GetInstance() ' Next, do a lookup in each contained module and merge the results. For Each containedModule As NamedTypeSymbol In container.GetModuleMembers() If firstModule Then Lookup(lookupResult, containedModule, name, arity, options, binder, tempResult, useSiteInfo) firstModule = False Else If currentResult Is Nothing Then currentResult = lookupResult.GetInstance() Else currentResult.Clear() End If Lookup(currentResult, containedModule, name, arity, options, binder, tempResult, useSiteInfo) ' Symbols in source take priority over symbols in a referenced assembly. If currentResult.StopFurtherLookup AndAlso currentResult.Symbols.Count > 0 AndAlso lookupResult.StopFurtherLookup AndAlso lookupResult.Symbols.Count > 0 Then Dim currentFromSource = currentResult.Symbols(0).ContainingModule Is sourceModule Dim contenderFromSource = lookupResult.Symbols(0).ContainingModule Is sourceModule If currentFromSource Then If Not contenderFromSource Then ' current is better lookupResult.SetFrom(currentResult) Continue For End If ElseIf contenderFromSource Then ' contender is better Continue For End If End If lookupResult.MergeAmbiguous(currentResult, s_ambiguousInModuleError) End If Next tempResult.Free() currentResult?.Free() End Sub Private Shared Sub AddLookupSymbolsInfo(nameSet As LookupSymbolsInfo, container As NamespaceSymbol, options As LookupOptions, binder As Binder) ' Add names from the namespace For Each sym In container.GetMembersUnordered() ' UNDONE: filter by options If binder.CanAddLookupSymbolInfo(sym, options, nameSet, Nothing) Then nameSet.AddSymbol(sym, sym.Name, sym.GetArity()) End If Next ' Next, add names from each contained module. For Each containedModule As NamedTypeSymbol In container.GetModuleMembers() AddLookupSymbolsInfo(nameSet, containedModule, options, binder) Next End Sub ' Create a diagnostic for ambiguous names in multiple modules. Private Shared ReadOnly s_ambiguousInModuleError As Func(Of ImmutableArray(Of Symbol), AmbiguousSymbolDiagnostic) = Function(syms As ImmutableArray(Of Symbol)) As AmbiguousSymbolDiagnostic Dim name As String = syms(0).Name Dim deferredFormattedList As New FormattedSymbolList(syms.Select(Function(sym) sym.ContainingType)) Return New AmbiguousSymbolDiagnostic(ERRID.ERR_AmbiguousInModules2, syms, name, deferredFormattedList) End Function ''' <summary> ''' Lookup a member name in a type, returning a LookupResult that ''' summarizes the results of the lookup. See LookupResult structure for a detailed ''' discussing of the meaning of the results. The supplied binder is used for accessibility ''' checked and base class suppression. ''' </summary> Friend Shared Sub Lookup(lookupResult As LookupResult, type As TypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(lookupResult.IsClear) Select Case type.TypeKind Case TypeKind.Class, TypeKind.Module, TypeKind.Structure, TypeKind.Delegate, TypeKind.Array, TypeKind.Enum LookupInClass(lookupResult, type, name, arity, options, type, binder, tempResult, useSiteInfo) Case TypeKind.Submission LookupInSubmissions(lookupResult, type, name, arity, options, binder, useSiteInfo) Case TypeKind.Interface LookupInInterface(lookupResult, DirectCast(type, NamedTypeSymbol), name, arity, options, binder, tempResult, useSiteInfo) Case TypeKind.TypeParameter LookupInTypeParameter(lookupResult, DirectCast(type, TypeParameterSymbol), name, arity, options, binder, tempResult, useSiteInfo) Case TypeKind.Error ' Error types have no members. Return Case Else Throw ExceptionUtilities.UnexpectedValue(type.TypeKind) End Select End Sub Private Shared Sub AddLookupSymbolsInfo(nameSet As LookupSymbolsInfo, container As TypeSymbol, options As LookupOptions, binder As Binder) Select Case container.TypeKind Case TypeKind.Class, TypeKind.Structure, TypeKind.Delegate, TypeKind.Array, TypeKind.Enum AddLookupSymbolsInfoInClass(nameSet, container, options, binder) Case TypeKind.Module AddLookupSymbolsInfoInClass(nameSet, container, options Or LookupOptions.NoBaseClassLookup, binder) Case TypeKind.Submission AddLookupSymbolsInfoInSubmissions(nameSet, container, options, binder) Case TypeKind.Interface AddLookupSymbolsInfoInInterface(nameSet, DirectCast(container, NamedTypeSymbol), options, binder) Case TypeKind.TypeParameter AddLookupSymbolsInfoInTypeParameter(nameSet, DirectCast(container, TypeParameterSymbol), options, binder) Case TypeKind.Error ' Error types have no members. Return Case Else Throw ExceptionUtilities.UnexpectedValue(container.TypeKind) End Select End Sub ''' <summary> ''' Lookup a member name in a module, class, struct, enum, or delegate, returning a LookupResult that ''' summarizes the results of the lookup. See LookupResult structure for a detailed ''' discussing of the meaning of the results. The supplied binder is used for accessibility ''' checks and base class suppression. ''' </summary> Private Shared Sub LookupInClass(result As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, accessThroughType As TypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(result.IsClear) Dim methodsOnly As Boolean = CheckAndClearMethodsOnlyOption(options) ' Lookup proceeds up the base class chain. Dim currentType = container Do tempResult.Clear() Dim hitNonoverloadingSymbol As Boolean = False LookupWithoutInheritance(tempResult, currentType, name, arity, options, accessThroughType, binder, useSiteInfo) If result.IsGoodOrAmbiguous AndAlso tempResult.IsGoodOrAmbiguous AndAlso Not LookupResult.CanOverload(result.Symbols(0), tempResult.Symbols(0)) Then ' We hit another good symbol that can't overload this one. That doesn't affect the lookup result, but means we have to stop ' looking for more members. See bug #14078 for example. hitNonoverloadingSymbol = True End If result.MergeOverloadedOrPrioritized(tempResult, True) ' If the type is from a winmd file and implements any of the special WinRT collection ' projections, then we may need to add projected interface members Dim namedType = TryCast(currentType, NamedTypeSymbol) If namedType IsNot Nothing AndAlso namedType.ShouldAddWinRTMembers Then FindWinRTMembers(result, namedType, binder, tempResult, useSiteInfo, lookupMembersNotDefaultProperties:=True, name:=name, arity:=arity, options:=options) End If If hitNonoverloadingSymbol Then Exit Do ' still do extension methods. End If If result.StopFurtherLookup Then ' If we found a non-overloadable symbol, we can stop now. Note that even if we find a method without the Overloads ' modifier, we cannot stop because we need to check for extension methods. If result.HasSymbol Then If Not result.Symbols.First.IsOverloadable Then If methodsOnly Then Exit Do ' Need to look for extension methods. End If Return End If End If End If ' Go to base type, unless that would case infinite recursion or the options or the binder ' disallows it. If (options And LookupOptions.NoBaseClassLookup) <> 0 OrElse binder.IgnoreBaseClassesInLookup Then currentType = Nothing Else currentType = currentType.GetDirectBaseTypeWithDefinitionUseSiteDiagnostics(binder.BasesBeingResolved, useSiteInfo) End If If currentType Is Nothing Then Exit Do End If Loop ClearLookupResultIfNotMethods(methodsOnly, result) LookupForExtensionMethodsIfNeedTo(result, container, name, arity, options, binder, tempResult, useSiteInfo) End Sub Public Delegate Sub WinRTLookupDelegate(iface As NamedTypeSymbol, binder As Binder, result As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) ''' <summary> ''' This function generalizes the idea of producing a set of non-conflicting ''' WinRT members of a given type based on the results of some arbitrary lookup ''' closure (which produces a LookupResult signifying success as IsGood). ''' ''' A non-conflicting WinRT member lookup looks for all members of projected ''' WinRT interfaces which are implemented by a given type, discarding any ''' which have equal signatures. ''' ''' If <paramref name="lookupMembersNotDefaultProperties" /> is true then ''' this function lookups up members with the given <paramref name="name" />, ''' <paramref name="arity" />, and <paramref name="options" />. Otherwise, it looks for default properties. ''' </summary> Private Shared Sub FindWinRTMembers(result As LookupResult, type As NamedTypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), lookupMembersNotDefaultProperties As Boolean, Optional name As String = Nothing, Optional arity As Integer = -1, Optional options As LookupOptions = Nothing) ' If we have no conflict with existing members, we also have to check ' if we have a conflict with other interface members. An example would be ' a type which implements both IIterable (IEnumerable) and IMap ' (IDictionary).There are two different GetEnumerator methods from each ' interface. Thus, we don't know which method to choose. The solution? ' Don't add any GetEnumerator method. Dim comparer = MemberSignatureComparer.WinRTComparer Dim allMembers = New HashSet(Of Symbol)(comparer) Dim conflictingMembers = New HashSet(Of Symbol)(comparer) ' Add all viable members from type lookup If result.IsGood Then For Each sym In result.Symbols ' Fields can't be present in the HashSet because they can't be compared ' with a MemberSignatureComparer ' TODO: Add field support in the C# and VB member comparers and then ' delete this check If sym.Kind <> SymbolKind.Field Then allMembers.Add(sym) End If Next End If Dim tmp = LookupResult.GetInstance() ' Dev11 searches all declared and undeclared base interfaces For Each iface In type.AllInterfacesWithDefinitionUseSiteDiagnostics(useSiteInfo) If IsWinRTProjectedInterface(iface, binder.Compilation) Then If lookupMembersNotDefaultProperties Then Debug.Assert(name IsNot Nothing) LookupWithoutInheritance(tmp, iface, name, arity, options, iface, binder, useSiteInfo) Else LookupDefaultPropertyInSingleType(tmp, iface, iface, binder, tempResult, useSiteInfo) End If ' only add viable members If tmp.IsGood Then For Each sym In tmp.Symbols If Not allMembers.Add(sym) Then conflictingMembers.Add(sym) End If Next End If tmp.Clear() End If Next tmp.Free() If result.IsGood Then For Each sym In result.Symbols If sym.Kind <> SymbolKind.Field Then allMembers.Remove(sym) conflictingMembers.Remove(sym) End If Next End If For Each sym In allMembers If Not conflictingMembers.Contains(sym) Then ' since we only added viable members, every lookupresult should be viable result.MergeOverloadedOrPrioritized( New SingleLookupResult(LookupResultKind.Good, sym, Nothing), checkIfCurrentHasOverloads:=False) End If Next End Sub Private Shared Function IsWinRTProjectedInterface(iFace As NamedTypeSymbol, compilation As VisualBasicCompilation) As Boolean Dim idictSymbol = compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IDictionary_KV) Dim iroDictSymbol = compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IReadOnlyDictionary_KV) Dim iListSymbol = compilation.GetWellKnownType(WellKnownType.System_Collections_IList) Dim iCollectionSymbol = compilation.GetWellKnownType(WellKnownType.System_Collections_ICollection) Dim inccSymbol = compilation.GetWellKnownType(WellKnownType.System_Collections_Specialized_INotifyCollectionChanged) Dim inpcSymbol = compilation.GetWellKnownType(WellKnownType.System_ComponentModel_INotifyPropertyChanged) Dim iFaceOriginal = iFace.OriginalDefinition Dim iFaceSpecial = iFaceOriginal.SpecialType ' Types match the list given in dev11 IMPORTER::GetWindowsRuntimeInterfacesToFake Return iFaceSpecial = SpecialType.System_Collections_Generic_IEnumerable_T OrElse iFaceSpecial = SpecialType.System_Collections_Generic_IList_T OrElse iFaceSpecial = SpecialType.System_Collections_Generic_ICollection_T OrElse TypeSymbol.Equals(iFaceOriginal, idictSymbol, TypeCompareKind.ConsiderEverything) OrElse iFaceSpecial = SpecialType.System_Collections_Generic_IReadOnlyList_T OrElse iFaceSpecial = SpecialType.System_Collections_Generic_IReadOnlyCollection_T OrElse TypeSymbol.Equals(iFaceOriginal, iroDictSymbol, TypeCompareKind.ConsiderEverything) OrElse iFaceSpecial = SpecialType.System_Collections_IEnumerable OrElse TypeSymbol.Equals(iFaceOriginal, iListSymbol, TypeCompareKind.ConsiderEverything) OrElse TypeSymbol.Equals(iFaceOriginal, iCollectionSymbol, TypeCompareKind.ConsiderEverything) OrElse TypeSymbol.Equals(iFaceOriginal, inccSymbol, TypeCompareKind.ConsiderEverything) OrElse TypeSymbol.Equals(iFaceOriginal, inpcSymbol, TypeCompareKind.ConsiderEverything) End Function ''' <summary> ''' Lookup a member name in a submission chain. ''' </summary> ''' <remarks> ''' We start with the current submission class and walk the submission chain back to the first submission. ''' The search has two phases ''' 1) We are looking for any symbol matching the given name, arity, and options. If we don't find any the search is over. ''' If we find an overloadable symbol(s) (a method or a property) we start looking for overloads of this kind ''' (lookingForOverloadsOfKind) of symbol in phase 2. ''' 2) If a visited submission contains a matching member of a kind different from lookingForOverloadsOfKind we stop ''' looking further. Otherwise, if we find viable overload(s) we add them into the result. Overloads modifier is ignored. ''' </remarks> Private Shared Sub LookupInSubmissions(result As LookupResult, submissionClass As TypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(result.IsClear) Dim submissionSymbols = LookupResult.GetInstance() Dim nonViable = LookupResult.GetInstance() Dim lookingForOverloadsOfKind As SymbolKind? = Nothing Dim submission = binder.Compilation Do submissionSymbols.Clear() If submission.ScriptClass IsNot Nothing Then LookupWithoutInheritance(submissionSymbols, submission.ScriptClass, name, arity, options, submissionClass, binder, useSiteInfo) End If ' TODO (tomat): import aliases If lookingForOverloadsOfKind Is Nothing Then If Not submissionSymbols.IsGoodOrAmbiguous Then ' skip non-viable members, but remember them in case no viable members are found in previous submissions: nonViable.MergePrioritized(submissionSymbols) submission = submission.PreviousSubmission Continue Do End If ' always overload (ignore Overloads modifier): result.MergeOverloadedOrPrioritized(submissionSymbols, checkIfCurrentHasOverloads:=False) Dim first = submissionSymbols.Symbols.First If Not first.IsOverloadable Then Exit Do End If ' we are now looking for any kind of member regardless of the original binding restrictions: options = options And Not LookupOptions.NamespacesOrTypesOnly lookingForOverloadsOfKind = first.Kind Else ' found a member we are not looking for - the overload set is final now If submissionSymbols.HasSymbol AndAlso submissionSymbols.Symbols.First.Kind <> lookingForOverloadsOfKind.Value Then Exit Do End If ' found a viable overload If submissionSymbols.IsGoodOrAmbiguous Then ' merge overloads Debug.Assert(result.Symbols.All(Function(s) s.IsOverloadable)) ' always overload (ignore Overloads modifier): result.MergeOverloadedOrPrioritized(submissionSymbols, checkIfCurrentHasOverloads:=False) End If End If submission = submission.PreviousSubmission Loop Until submission Is Nothing If Not result.HasSymbol Then result.SetFrom(nonViable) End If ' TODO (tomat): extension methods submissionSymbols.Free() nonViable.Free() End Sub Public Shared Sub LookupDefaultProperty(result As LookupResult, container As TypeSymbol, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Select Case container.TypeKind Case TypeKind.Class, TypeKind.Module, TypeKind.Structure Dim tempResult = LookupResult.GetInstance() LookupDefaultPropertyInClass(result, DirectCast(container, NamedTypeSymbol), binder, tempResult, useSiteInfo) tempResult.Free() Case TypeKind.Interface Dim tempResult = LookupResult.GetInstance() LookupDefaultPropertyInInterface(result, DirectCast(container, NamedTypeSymbol), binder, tempResult, useSiteInfo) tempResult.Free() Case TypeKind.TypeParameter Dim tempResult = LookupResult.GetInstance() LookupDefaultPropertyInTypeParameter(result, DirectCast(container, TypeParameterSymbol), binder, tempResult, useSiteInfo) tempResult.Free() End Select End Sub Private Shared Sub LookupDefaultPropertyInClass( result As LookupResult, type As NamedTypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(type.IsClassType OrElse type.IsModuleType OrElse type.IsStructureType OrElse type.IsDelegateType) Dim accessThroughType As NamedTypeSymbol = type While type IsNot Nothing If LookupDefaultPropertyInSingleType(result, type, accessThroughType, binder, tempResult, useSiteInfo) Then Return End If ' If this is a WinRT type, we should also look for default properties in the ' implemented projected interfaces If type.ShouldAddWinRTMembers Then FindWinRTMembers(result, type, binder, tempResult, useSiteInfo, lookupMembersNotDefaultProperties:=False) If result.IsGood Then Return End If End If type = type.BaseTypeWithDefinitionUseSiteDiagnostics(useSiteInfo) End While End Sub ' See Semantics::LookupDefaultPropertyInInterface. Private Shared Sub LookupDefaultPropertyInInterface( result As LookupResult, [interface] As NamedTypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert([interface].IsInterfaceType) If LookupDefaultPropertyInSingleType(result, [interface], [interface], binder, tempResult, useSiteInfo) Then Return End If For Each baseInterface In [interface].InterfacesNoUseSiteDiagnostics baseInterface.OriginalDefinition.AddUseSiteInfo(useSiteInfo) LookupDefaultPropertyInBaseInterface(result, baseInterface, binder, tempResult, useSiteInfo) If result.HasDiagnostic Then Return End If Next End Sub Private Shared Sub LookupDefaultPropertyInTypeParameter( result As LookupResult, typeParameter As TypeParameterSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) ' Look up in class constraint. Dim constraintClass = typeParameter.GetClassConstraint(useSiteInfo) If constraintClass IsNot Nothing Then LookupDefaultPropertyInClass(result, constraintClass, binder, tempResult, useSiteInfo) If Not result.IsClear Then Return End If End If ' Look up in interface constraints. Dim lookIn As Queue(Of InterfaceInfo) = Nothing Dim processed As HashSet(Of InterfaceInfo) = Nothing AddInterfaceConstraints(typeParameter, lookIn, processed, useSiteInfo) If lookIn IsNot Nothing Then For Each baseInterface In lookIn LookupDefaultPropertyInBaseInterface(result, baseInterface.InterfaceType, binder, tempResult, useSiteInfo) If result.HasDiagnostic Then Return End If Next End If End Sub ' See Semantics::LookupDefaultPropertyInBaseInterface. Private Shared Sub LookupDefaultPropertyInBaseInterface( result As LookupResult, type As NamedTypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) If type.IsErrorType() Then Return End If Debug.Assert(type.IsInterfaceType) Debug.Assert(Not result.HasDiagnostic) Dim tmpResult = LookupResult.GetInstance() Try LookupDefaultPropertyInInterface(tmpResult, type, binder, tempResult, useSiteInfo) If Not tmpResult.HasSymbol Then Return End If If tmpResult.HasDiagnostic OrElse Not result.HasSymbol Then result.SetFrom(tmpResult) Return End If ' At least one member was found on another interface. ' Report an ambiguity error if the two interfaces are distinct. Dim symbolA = result.Symbols(0) Dim symbolB = tmpResult.Symbols(0) If symbolA.ContainingSymbol <> symbolB.ContainingSymbol Then result.MergeAmbiguous(tmpResult, AddressOf GenerateAmbiguousDefaultPropertyDiagnostic) End If Finally tmpResult.Free() End Try End Sub ' Return True if a default property is defined on the type. Private Shared Function LookupDefaultPropertyInSingleType( result As LookupResult, type As NamedTypeSymbol, accessThroughType As TypeSymbol, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) As Boolean Dim defaultPropertyName = type.DefaultPropertyName If String.IsNullOrEmpty(defaultPropertyName) Then Return False End If Select Case type.TypeKind Case TypeKind.Class, TypeKind.Module, TypeKind.Structure LookupInClass( result, type, defaultPropertyName, arity:=0, options:=LookupOptions.Default, accessThroughType:=accessThroughType, binder:=binder, tempResult:=tempResult, useSiteInfo:=useSiteInfo) Case TypeKind.Interface Debug.Assert(accessThroughType Is type) LookupInInterface( result, type, defaultPropertyName, arity:=0, options:=LookupOptions.Default, binder:=binder, tempResult:=tempResult, useSiteInfo:=useSiteInfo) Case TypeKind.TypeParameter Throw ExceptionUtilities.UnexpectedValue(type.TypeKind) End Select Return result.HasSymbol End Function Private Shared Function GenerateAmbiguousDefaultPropertyDiagnostic(symbols As ImmutableArray(Of Symbol)) As AmbiguousSymbolDiagnostic Debug.Assert(symbols.Length > 1) Dim symbolA = symbols(0) Dim containingSymbolA = symbolA.ContainingSymbol For i = 1 To symbols.Length - 1 Dim symbolB = symbols(i) Dim containingSymbolB = symbolB.ContainingSymbol If containingSymbolA <> containingSymbolB Then ' "Default property access is ambiguous between the inherited interface members '{0}' of interface '{1}' and '{2}' of interface '{3}'." Return New AmbiguousSymbolDiagnostic(ERRID.ERR_DefaultPropertyAmbiguousAcrossInterfaces4, symbols, symbolA, containingSymbolA, symbolB, containingSymbolB) End If Next ' Expected ambiguous symbols Throw ExceptionUtilities.Unreachable End Function Private Shared Sub LookupForExtensionMethodsIfNeedTo( result As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) If result.IsGood AndAlso ((options And LookupOptions.EagerlyLookupExtensionMethods) = 0 OrElse result.Symbols(0).Kind <> SymbolKind.Method) Then Return End If tempResult.Clear() LookupForExtensionMethods(tempResult, container, name, arity, options, binder, useSiteInfo) MergeInternalXmlHelperValueIfNecessary(tempResult, container, name, arity, options, binder, useSiteInfo) result.MergeOverloadedOrPrioritized(tempResult, checkIfCurrentHasOverloads:=False) End Sub Private Shared Function ShouldLookupExtensionMethods(options As LookupOptions, container As TypeSymbol) As Boolean Return options.ShouldLookupExtensionMethods AndAlso Not container.IsObjectType() AndAlso Not container.IsShared AndAlso Not container.IsModuleType() End Function Public Shared Sub LookupForExtensionMethods( lookupResult As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(lookupResult.IsClear) If Not ShouldLookupExtensionMethods(options, container) Then lookupResult.SetFrom(SingleLookupResult.Empty) Return End If ' Proceed up the chain of binders, collecting extension methods Dim originalBinder = binder Dim currentBinder = binder Dim methods = ArrayBuilder(Of MethodSymbol).GetInstance() Dim proximity As Integer = 0 ' We don't want to process the same methods more than once, but the same extension method ' might be in scope in several different binders. For example, within a type, within ' imported the same type, within imported namespace containing the type. ' So, taking into consideration the fact that CollectProbableExtensionMethodsInSingleBinder ' groups methods from the same containing type together, we will keep track of the types and ' will process all the methods from the same containing type at once. Dim seenContainingTypes As New HashSet(Of NamedTypeSymbol)() Do methods.Clear() currentBinder.CollectProbableExtensionMethodsInSingleBinder(name, methods, originalBinder) Dim i As Integer = 0 Dim count As Integer = methods.Count While i < count Dim containingType As NamedTypeSymbol = methods(i).ContainingType If seenContainingTypes.Add(containingType) AndAlso ((options And LookupOptions.IgnoreAccessibility) <> 0 OrElse AccessCheck.IsSymbolAccessible(containingType, binder.Compilation.Assembly, useSiteInfo)) Then ' Process all methods from the same type together. Do ' Try to reduce this method and merge with the current result Dim reduced As MethodSymbol = methods(i).ReduceExtensionMethod(container, proximity, useSiteInfo, binder.Compilation.LanguageVersion) If reduced IsNot Nothing Then lookupResult.MergeOverloadedOrPrioritizedExtensionMethods(binder.CheckViability(reduced, arity, options, reduced.ContainingType, useSiteInfo)) End If i += 1 Loop While i < count AndAlso containingType Is methods(i).ContainingSymbol Else ' We already processed extension methods from this container before or the whole container is not accessible, ' skip the whole group of methods from this containing type. Do i += 1 Loop While i < count AndAlso containingType Is methods(i).ContainingSymbol End If End While ' Continue to containing binders. proximity += 1 currentBinder = currentBinder.m_containingBinder Loop While currentBinder IsNot Nothing methods.Free() End Sub ''' <summary> ''' Include the InternalXmlHelper.Value extension property in the LookupResult ''' if the container implements IEnumerable(Of XElement), the name is "Value", ''' and the arity is 0. ''' </summary> Private Shared Sub MergeInternalXmlHelperValueIfNecessary( lookupResult As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) If (arity <> 0) OrElse Not IdentifierComparison.Equals(name, StringConstants.ValueProperty) Then Return End If Dim compilation = binder.Compilation If (options And LookupOptions.NamespacesOrTypesOnly) <> 0 OrElse Not container.IsOrImplementsIEnumerableOfXElement(compilation, useSiteInfo) Then Return End If Dim symbol = binder.GetInternalXmlHelperValueExtensionProperty() Dim singleResult As SingleLookupResult If symbol Is Nothing Then ' Match the native compiler which reports ERR_XmlFeaturesNotAvailable in this case. Dim useSiteError = ErrorFactory.ErrorInfo(ERRID.ERR_XmlFeaturesNotAvailable) singleResult = New SingleLookupResult(LookupResultKind.NotReferencable, binder.GetErrorSymbol(name, useSiteError), useSiteError) Else Dim reduced = New ReducedExtensionPropertySymbol(DirectCast(symbol, PropertySymbol)) singleResult = binder.CheckViability(reduced, arity, options, reduced.ContainingType, useSiteInfo) End If lookupResult.MergePrioritized(singleResult) End Sub Private Shared Sub AddLookupSymbolsInfoOfExtensionMethods(nameSet As LookupSymbolsInfo, container As TypeSymbol, newInfo As LookupSymbolsInfo, binder As Binder) Dim lookup = LookupResult.GetInstance() For Each name In newInfo.Names lookup.Clear() LookupForExtensionMethods(lookup, container, name, 0, LookupOptions.AllMethodsOfAnyArity Or LookupOptions.IgnoreAccessibility, binder, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) If lookup.IsGood Then For Each method As MethodSymbol In lookup.Symbols nameSet.AddSymbol(method, method.Name, method.Arity) Next End If Next lookup.Free() End Sub Public Shared Sub AddExtensionMethodLookupSymbolsInfo(nameSet As LookupSymbolsInfo, container As TypeSymbol, options As LookupOptions, binder As Binder) If Not ShouldLookupExtensionMethods(options, container) Then Return End If ' We will not reduce extension methods for the purpose of this operation, ' they will still be shared methods. options = options And (Not Global.Microsoft.CodeAnalysis.VisualBasic.LookupOptions.MustBeInstance) ' Proceed up the chain of binders, collecting names of extension methods Dim currentBinder As Binder = binder Dim newInfo = LookupSymbolsInfo.GetInstance() Do currentBinder.AddExtensionMethodLookupSymbolsInfoInSingleBinder(newInfo, options, binder) ' Continue to containing binders. currentBinder = currentBinder.m_containingBinder Loop While currentBinder IsNot Nothing AddLookupSymbolsInfoOfExtensionMethods(nameSet, container, newInfo, binder) newInfo.Free() ' Include "Value" for InternalXmlHelper.Value if necessary. Dim compilation = binder.Compilation Dim useSiteInfo = CompoundUseSiteInfo(Of AssemblySymbol).DiscardedDependencies If container.IsOrImplementsIEnumerableOfXElement(compilation, useSiteInfo) AndAlso useSiteInfo.Diagnostics.IsNullOrEmpty Then nameSet.AddSymbol(Nothing, StringConstants.ValueProperty, 0) End If End Sub ''' <summary> ''' Checks if two interfaces have a base-derived relationship ''' </summary> Private Shared Function IsDerivedInterface( base As NamedTypeSymbol, derived As NamedTypeSymbol, basesBeingResolved As BasesBeingResolved, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) As Boolean Debug.Assert(base.IsInterface) Debug.Assert(derived.IsInterface) If TypeSymbol.Equals(derived.OriginalDefinition, base.OriginalDefinition, TypeCompareKind.ConsiderEverything) Then Return False End If ' if we are not resolving bases we can just go through AllInterfaces list If basesBeingResolved.InheritsBeingResolvedOpt Is Nothing Then For Each i In derived.AllInterfacesWithDefinitionUseSiteDiagnostics(useSiteInfo) If TypeSymbol.Equals(i, base, TypeCompareKind.ConsiderEverything) Then Return True End If Next Return False End If ' we are resolving bases so should use a private helper that relies only on Declared interfaces Return IsDerivedInterface(base, derived, basesBeingResolved, New HashSet(Of Symbol), useSiteInfo) End Function Private Shared Function IsDerivedInterface( base As NamedTypeSymbol, derived As NamedTypeSymbol, basesBeingResolved As BasesBeingResolved, verified As HashSet(Of Symbol), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) As Boolean Debug.Assert(Not TypeSymbol.Equals(base, derived, TypeCompareKind.ConsiderEverything), "should already be verified for equality") Debug.Assert(base.IsInterface) Debug.Assert(derived.IsInterface) verified.Add(derived) ' not afraid of cycles here as we will not verify same symbol twice Dim interfaces = derived.GetDeclaredInterfacesWithDefinitionUseSiteDiagnostics(basesBeingResolved, useSiteInfo) If Not interfaces.IsDefaultOrEmpty Then For Each i In interfaces If TypeSymbol.Equals(i, base, TypeCompareKind.ConsiderEverything) Then Return True End If If verified.Contains(i) Then ' seen this already Continue For End If If IsDerivedInterface( base, i, basesBeingResolved, verified, useSiteInfo) Then Return True End If Next End If Return False End Function Private Structure InterfaceInfo Implements IEquatable(Of InterfaceInfo) Public ReadOnly InterfaceType As NamedTypeSymbol Public ReadOnly InComInterfaceContext As Boolean Public ReadOnly DescendantDefinitions As ImmutableHashSet(Of NamedTypeSymbol) Public Sub New(interfaceType As NamedTypeSymbol, inComInterfaceContext As Boolean, Optional descendantDefinitions As ImmutableHashSet(Of NamedTypeSymbol) = Nothing) Me.InterfaceType = interfaceType Me.InComInterfaceContext = inComInterfaceContext Me.DescendantDefinitions = descendantDefinitions End Sub Public Overrides Function GetHashCode() As Integer Return Hash.Combine(Me.InterfaceType.GetHashCode(), Me.InComInterfaceContext.GetHashCode()) End Function Public Overloads Overrides Function Equals(obj As Object) As Boolean Return TypeOf obj Is InterfaceInfo AndAlso Equals(DirectCast(obj, InterfaceInfo)) End Function Public Overloads Function Equals(other As InterfaceInfo) As Boolean Implements IEquatable(Of InterfaceInfo).Equals Return Me.InterfaceType.Equals(other.InterfaceType) AndAlso Me.InComInterfaceContext = other.InComInterfaceContext End Function End Structure Private Shared Sub LookupInInterface(lookupResult As LookupResult, container As NamedTypeSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(lookupResult.IsClear) Dim methodsOnly As Boolean = CheckAndClearMethodsOnlyOption(options) ' look in these types. Start with container, add more accordingly. Dim info As New InterfaceInfo(container, False) Dim lookIn As New Queue(Of InterfaceInfo) lookIn.Enqueue(info) Dim processed As New HashSet(Of InterfaceInfo) processed.Add(info) LookupInInterfaces(lookupResult, container, lookIn, processed, name, arity, options, binder, methodsOnly, useSiteInfo) ' If no viable or ambiguous results, look in Object. If Not lookupResult.IsGoodOrAmbiguous AndAlso (options And LookupOptions.NoSystemObjectLookupForInterfaces) = 0 Then Dim currentResult = lookupResult.GetInstance() Dim obj As NamedTypeSymbol = binder.SourceModule.ContainingAssembly.GetSpecialType(SpecialType.System_Object) LookupInClass(currentResult, obj, name, arity, options Or LookupOptions.IgnoreExtensionMethods, obj, binder, tempResult, useSiteInfo) If currentResult.IsGood Then lookupResult.SetFrom(currentResult) End If currentResult.Free() End If ClearLookupResultIfNotMethods(methodsOnly, lookupResult) LookupForExtensionMethodsIfNeedTo(lookupResult, container, name, arity, options, binder, tempResult, useSiteInfo) Return End Sub Private Shared Sub LookupInInterfaces(lookupResult As LookupResult, container As TypeSymbol, lookIn As Queue(Of InterfaceInfo), processed As HashSet(Of InterfaceInfo), name As String, arity As Integer, options As LookupOptions, binder As Binder, methodsOnly As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(lookupResult.IsClear) Dim basesBeingResolved As BasesBeingResolved = binder.BasesBeingResolved() Dim isEventsOnlySpecified As Boolean = (options And LookupOptions.EventsOnly) <> 0 Dim currentResult = lookupResult.GetInstance() Do Dim info As InterfaceInfo = lookIn.Dequeue() Debug.Assert(processed.Contains(info)) Debug.Assert(currentResult.IsClear) LookupWithoutInheritance(currentResult, info.InterfaceType, name, arity, options, container, binder, useSiteInfo) ' if result does not shadow we will have bases to visit If Not (currentResult.StopFurtherLookup AndAlso AnyShadows(currentResult)) Then If (options And LookupOptions.NoBaseClassLookup) = 0 AndAlso Not binder.IgnoreBaseClassesInLookup Then AddBaseInterfacesToTheSearch(binder, info, lookIn, processed, useSiteInfo) End If End If Dim leaveEventsOnly As Boolean? = Nothing If info.InComInterfaceContext Then leaveEventsOnly = isEventsOnlySpecified End If If lookupResult.IsGood AndAlso currentResult.IsGood Then ' We have _another_ viable result while lookupResult is already viable. Use special interface merging rules. MergeInterfaceLookupResults(lookupResult, currentResult, basesBeingResolved, leaveEventsOnly, useSiteInfo) Else If currentResult.IsGood AndAlso leaveEventsOnly.HasValue Then FilterSymbolsInLookupResult(currentResult, SymbolKind.Event, leaveInsteadOfRemoving:=leaveEventsOnly.Value) End If lookupResult.MergePrioritized(currentResult) End If currentResult.Clear() Loop While lookIn.Count <> 0 currentResult.Free() If methodsOnly AndAlso lookupResult.IsGood Then ' We need to filter out non-method symbols from 'currentResult' ' before merging with 'lookupResult' FilterSymbolsInLookupResult(lookupResult, SymbolKind.Method, leaveInsteadOfRemoving:=True) End If ' it may look like a Good result, but it may have ambiguities inside ' so we need to check that to be sure. If lookupResult.IsGood Then Dim ambiguityDiagnostics As AmbiguousSymbolDiagnostic = Nothing Dim symbols As ArrayBuilder(Of Symbol) = lookupResult.Symbols For i As Integer = 0 To symbols.Count - 2 Dim interface1 = DirectCast(symbols(i).ContainingType, NamedTypeSymbol) For j As Integer = i + 1 To symbols.Count - 1 If Not lookupResult.CanOverload(symbols(i), symbols(j)) Then ' Symbols cannot overload each other. ' If they were from the same interface, LookupWithoutInheritance would make the result ambiguous. ' If they were from interfaces related through inheritance, one of them would shadow another, ' MergeInterfaceLookupResults handles that. ' Therefore, this symbols are from unrelated interfaces. ambiguityDiagnostics = New AmbiguousSymbolDiagnostic( ERRID.ERR_AmbiguousAcrossInterfaces3, symbols.ToImmutable, name, CustomSymbolDisplayFormatter.DefaultErrorFormat(symbols(i).ContainingType), CustomSymbolDisplayFormatter.DefaultErrorFormat(symbols(j).ContainingType)) GoTo ExitForFor End If Next Next ExitForFor: If ambiguityDiagnostics IsNot Nothing Then lookupResult.SetFrom(New SingleLookupResult(LookupResultKind.Ambiguous, symbols.First, ambiguityDiagnostics)) End If End If End Sub Private Shared Sub FilterSymbolsInLookupResult(result As LookupResult, kind As SymbolKind, leaveInsteadOfRemoving As Boolean) Debug.Assert(result.IsGood) Dim resultSymbols As ArrayBuilder(Of Symbol) = result.Symbols Debug.Assert(resultSymbols.Count > 0) Dim i As Integer = 0 Dim j As Integer = 0 While j < resultSymbols.Count Dim symbol As Symbol = resultSymbols(j) If (symbol.Kind = kind) = leaveInsteadOfRemoving Then resultSymbols(i) = resultSymbols(j) i += 1 End If j += 1 End While resultSymbols.Clip(i) If i = 0 Then result.Clear() End If End Sub Private Shared Sub LookupInTypeParameter(lookupResult As LookupResult, typeParameter As TypeParameterSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Dim methodsOnly = CheckAndClearMethodsOnlyOption(options) LookupInTypeParameterNoExtensionMethods(lookupResult, typeParameter, name, arity, options, binder, tempResult, useSiteInfo) ClearLookupResultIfNotMethods(methodsOnly, lookupResult) LookupForExtensionMethodsIfNeedTo(lookupResult, typeParameter, name, arity, options, binder, tempResult, useSiteInfo) End Sub Private Shared Sub LookupInTypeParameterNoExtensionMethods(result As LookupResult, typeParameter As TypeParameterSymbol, name As String, arity As Integer, options As LookupOptions, binder As Binder, tempResult As LookupResult, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert((options And LookupOptions.MethodsOnly) = 0) options = options Or LookupOptions.IgnoreExtensionMethods ' §4.9.2: "the class constraint hides members in interface constraints, which ' hide members in System.ValueType (if Structure constraint is specified), ' which hides members in Object." ' Look up in class constraint. Dim constraintClass = typeParameter.GetClassConstraint(useSiteInfo) If constraintClass IsNot Nothing Then LookupInClass(result, constraintClass, name, arity, options, constraintClass, binder, tempResult, useSiteInfo) If result.StopFurtherLookup Then Return End If End If ' Look up in interface constraints. Dim lookIn As Queue(Of InterfaceInfo) = Nothing Dim processed As HashSet(Of InterfaceInfo) = Nothing AddInterfaceConstraints(typeParameter, lookIn, processed, useSiteInfo) If lookIn IsNot Nothing Then ' §4.9.2: "If a member with the same name appears in more than one interface ' constraint the member is unavailable (as in multiple interface inheritance)" Dim interfaceResult = LookupResult.GetInstance() Debug.Assert((options And LookupOptions.MethodsOnly) = 0) LookupInInterfaces(interfaceResult, typeParameter, lookIn, processed, name, arity, options, binder, False, useSiteInfo) result.MergePrioritized(interfaceResult) interfaceResult.Free() If Not result.IsClear Then Return End If End If ' Look up in System.ValueType or System.Object. If constraintClass Is Nothing Then Debug.Assert(result.IsClear) Dim baseType = GetTypeParameterBaseType(typeParameter) LookupInClass(result, baseType, name, arity, options, baseType, binder, tempResult, useSiteInfo) End If End Sub Private Shared Function CheckAndClearMethodsOnlyOption(ByRef options As LookupOptions) As Boolean If (options And LookupOptions.MethodsOnly) <> 0 Then options = CType(options And (Not LookupOptions.MethodsOnly), LookupOptions) Return True End If Return False End Function Private Shared Sub ClearLookupResultIfNotMethods(methodsOnly As Boolean, lookupResult As LookupResult) If methodsOnly AndAlso lookupResult.HasSymbol AndAlso lookupResult.Symbols(0).Kind <> SymbolKind.Method Then lookupResult.Clear() End If End Sub Private Shared Sub AddInterfaceConstraints(typeParameter As TypeParameterSymbol, ByRef allInterfaces As Queue(Of InterfaceInfo), ByRef processedInterfaces As HashSet(Of InterfaceInfo), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) For Each constraintType In typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(useSiteInfo) Select Case constraintType.TypeKind Case TypeKind.Interface Dim newInfo As New InterfaceInfo(DirectCast(constraintType, NamedTypeSymbol), False) If processedInterfaces Is Nothing OrElse Not processedInterfaces.Contains(newInfo) Then If processedInterfaces Is Nothing Then allInterfaces = New Queue(Of InterfaceInfo) processedInterfaces = New HashSet(Of InterfaceInfo) End If allInterfaces.Enqueue(newInfo) processedInterfaces.Add(newInfo) End If Case TypeKind.TypeParameter AddInterfaceConstraints(DirectCast(constraintType, TypeParameterSymbol), allInterfaces, processedInterfaces, useSiteInfo) End Select Next End Sub ''' <summary> ''' Merges two lookup results while eliminating symbols that are shadowed. ''' Note that the final result may contain unrelated and possibly conflicting symbols as ''' this helper is not intended to catch ambiguities. ''' </summary> ''' <param name="leaveEventsOnly"> ''' If is not Nothing and False filters out all Event symbols, and if is not Nothing ''' and True filters out all non-Event symbols, nos not have any effect otherwise. ''' Is used for special handling of Events inside COM interfaces. ''' </param> Private Shared Sub MergeInterfaceLookupResults( knownResult As LookupResult, newResult As LookupResult, BasesBeingResolved As BasesBeingResolved, leaveEventsOnly As Boolean?, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Debug.Assert(knownResult.Kind = newResult.Kind) Dim knownSymbols As ArrayBuilder(Of Symbol) = knownResult.Symbols Dim newSymbols As ArrayBuilder(Of Symbol) = newResult.Symbols Dim newSymbolContainer = newSymbols.First().ContainingType For i As Integer = 0 To knownSymbols.Count - 1 Dim knownSymbol = knownSymbols(i) ' Nothing means that the symbol has been eliminated via shadowing If knownSymbol Is Nothing Then Continue For End If Dim knownSymbolContainer = knownSymbol.ContainingType For j As Integer = 0 To newSymbols.Count - 1 Dim newSymbol As Symbol = newSymbols(j) ' Nothing means that the symbol has been eliminated via shadowing If newSymbol Is Nothing Then Continue For End If ' Special-case events in case we are inside COM interface If leaveEventsOnly.HasValue AndAlso (newSymbol.Kind = SymbolKind.Event) <> leaveEventsOnly.Value Then newSymbols(j) = Nothing Continue For End If If knownSymbol = newSymbol Then ' this is the same result as we already have, remove from the new set newSymbols(j) = Nothing Continue For End If ' container of the first new symbol should be container of all others Debug.Assert(TypeSymbol.Equals(newSymbolContainer, newSymbol.ContainingType, TypeCompareKind.ConsiderEverything)) ' Are the known and new symbols of the right kinds to overload? Dim cantOverloadEachOther = Not LookupResult.CanOverload(knownSymbol, newSymbol) If IsDerivedInterface(base:=newSymbolContainer, derived:=knownSymbolContainer, basesBeingResolved:=BasesBeingResolved, useSiteInfo:=useSiteInfo) Then ' if currently known is more derived and shadows the new one ' it shadows all the new ones and we are done If IsShadows(knownSymbol) OrElse cantOverloadEachOther Then ' no need to continue with merge. new symbols are all shadowed ' and they cannot shadow anything in the old set Debug.Assert(Not knownSymbols.Any(Function(s) s Is Nothing)) newResult.Clear() Return End If ElseIf IsDerivedInterface(base:=knownSymbolContainer, derived:=newSymbolContainer, basesBeingResolved:=BasesBeingResolved, useSiteInfo:=useSiteInfo) Then ' if new is more derived and shadows ' the current one should be dropped ' NOTE that we continue iterating as more known symbols may be "shadowed out" by the current. If IsShadows(newSymbol) OrElse cantOverloadEachOther Then knownSymbols(i) = Nothing ' all following known symbols in the same container are shadowed by the new one ' we can do a quick check and remove them here For k = i + 1 To knownSymbols.Count - 1 Dim otherKnown As Symbol = knownSymbols(k) If otherKnown IsNot Nothing AndAlso TypeSymbol.Equals(otherKnown.ContainingType, knownSymbolContainer, TypeCompareKind.ConsiderEverything) Then knownSymbols(k) = Nothing End If Next End If End If ' we can get here if results are completely unrelated. ' However we do not know if they are conflicting as either one could be "shadowed out" in later iterations. ' for now we let both known and new stay Next Next CompactAndAppend(knownSymbols, newSymbols) newResult.Clear() End Sub ''' <summary> ''' first.Where(t IsNot Nothing).Concat(second.Where(t IsNot Nothing)) ''' </summary> Private Shared Sub CompactAndAppend(first As ArrayBuilder(Of Symbol), second As ArrayBuilder(Of Symbol)) Dim i As Integer = 0 ' skip non nulls While i < first.Count If first(i) Is Nothing Then Exit While End If i += 1 End While ' compact the rest Dim j As Integer = i + 1 While j < first.Count Dim item As Symbol = first(j) If item IsNot Nothing Then first(i) = item i += 1 End If j += 1 End While ' clip to compacted size first.Clip(i) ' append non nulls from second i = 0 While i < second.Count Dim items As Symbol = second(i) If items IsNot Nothing Then first.Add(items) End If i += 1 End While End Sub ''' <summary> ''' ''' </summary> Private Shared Sub AddBaseInterfacesToTheSearch(binder As Binder, currentInfo As InterfaceInfo, lookIn As Queue(Of InterfaceInfo), processed As HashSet(Of InterfaceInfo), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Dim interfaces As ImmutableArray(Of NamedTypeSymbol) = currentInfo.InterfaceType.GetDirectBaseInterfacesNoUseSiteDiagnostics(binder.BasesBeingResolved) If Not interfaces.IsDefaultOrEmpty Then Dim inComInterfaceContext As Boolean = currentInfo.InComInterfaceContext OrElse currentInfo.InterfaceType.CoClassType IsNot Nothing Dim descendants As ImmutableHashSet(Of NamedTypeSymbol) If binder.BasesBeingResolved.InheritsBeingResolvedOpt Is Nothing Then descendants = Nothing Else ' We need to watch out for cycles in inheritance chain since they are not broken while bases are being resolved. If currentInfo.DescendantDefinitions Is Nothing Then descendants = ImmutableHashSet.Create(currentInfo.InterfaceType.OriginalDefinition) Else descendants = currentInfo.DescendantDefinitions.Add(currentInfo.InterfaceType.OriginalDefinition) End If End If For Each i In interfaces If descendants IsNot Nothing AndAlso descendants.Contains(i.OriginalDefinition) Then ' About to get in an inheritance cycle Continue For End If i.OriginalDefinition.AddUseSiteInfo(useSiteInfo) Dim newInfo As New InterfaceInfo(i, inComInterfaceContext, descendants) If processed.Add(newInfo) Then lookIn.Enqueue(newInfo) End If Next End If End Sub ''' <summary> ''' if any symbol in the list Shadows. This implies that name is not visible through the base. ''' </summary> Private Shared Function AnyShadows(result As LookupResult) As Boolean For Each sym As Symbol In result.Symbols If sym.IsShadows Then Return True End If Next Return False End Function ' Find all names in a non-interface type, consider inheritance. Private Shared Sub AddLookupSymbolsInfoInClass(nameSet As LookupSymbolsInfo, container As TypeSymbol, options As LookupOptions, binder As Binder) ' We need a check for SpecialType.System_Void as its base type is ' ValueType but we don't wish to return any members for void type If container IsNot Nothing And container.SpecialType = SpecialType.System_Void Then Return End If ' Lookup proceeds up the base class chain. Dim currentType = container Do AddLookupSymbolsInfoWithoutInheritance(nameSet, currentType, options, container, binder) ' If the type is from a winmd file and implements any of the special WinRT collection ' projections, then we may need to add projected interface members Dim namedType = TryCast(currentType, NamedTypeSymbol) If namedType IsNot Nothing AndAlso namedType.ShouldAddWinRTMembers Then AddWinRTMembersLookupSymbolsInfo(nameSet, namedType, options, container, binder) End If ' Go to base type, unless that would case infinite recursion or the options or the binder ' disallows it. If (options And LookupOptions.NoBaseClassLookup) <> 0 OrElse binder.IgnoreBaseClassesInLookup Then currentType = Nothing Else currentType = currentType.GetDirectBaseTypeNoUseSiteDiagnostics(binder.BasesBeingResolved) End If Loop While currentType IsNot Nothing ' Search for extension methods. AddExtensionMethodLookupSymbolsInfo(nameSet, container, options, binder) ' Special case: if we're in a constructor of a class or structure, then we can call constructors on ourself or our immediate base ' (via Me.New or MyClass.New or MyBase.New). We don't have enough info to check the constraints that the constructor must be ' the specific tokens Me, MyClass, or MyBase, or that its the first statement in the constructor, so services must do ' that check if it wants to show that. ' Roslyn Bug 9701. Dim containingMethod = TryCast(binder.ContainingMember, MethodSymbol) If containingMethod IsNot Nothing AndAlso containingMethod.MethodKind = MethodKind.Constructor AndAlso (container.TypeKind = TypeKind.Class OrElse container.TypeKind = TypeKind.Structure) AndAlso (TypeSymbol.Equals(containingMethod.ContainingType, container, TypeCompareKind.ConsiderEverything) OrElse TypeSymbol.Equals(containingMethod.ContainingType.BaseTypeNoUseSiteDiagnostics, container, TypeCompareKind.ConsiderEverything)) Then nameSet.AddSymbol(Nothing, WellKnownMemberNames.InstanceConstructorName, 0) End If End Sub Private Shared Sub AddLookupSymbolsInfoInSubmissions(nameSet As LookupSymbolsInfo, submissionClass As TypeSymbol, options As LookupOptions, binder As Binder) Dim submission = binder.Compilation Do ' TODO (tomat): import aliases If submission.ScriptClass IsNot Nothing Then AddLookupSymbolsInfoWithoutInheritance(nameSet, submission.ScriptClass, options, submissionClass, binder) End If submission = submission.PreviousSubmission Loop Until submission Is Nothing ' TODO (tomat): extension methods End Sub ' Find all names in an interface type, consider inheritance. Private Shared Sub AddLookupSymbolsInfoInInterface(nameSet As LookupSymbolsInfo, container As NamedTypeSymbol, options As LookupOptions, binder As Binder) Dim info As New InterfaceInfo(container, False) Dim lookIn As New Queue(Of InterfaceInfo) lookIn.Enqueue(info) Dim processed As New HashSet(Of InterfaceInfo) processed.Add(info) AddLookupSymbolsInfoInInterfaces(nameSet, container, lookIn, processed, options, binder) ' Look in Object. AddLookupSymbolsInfoInClass(nameSet, binder.SourceModule.ContainingAssembly.GetSpecialType(SpecialType.System_Object), options Or LookupOptions.IgnoreExtensionMethods, binder) ' Search for extension methods. AddExtensionMethodLookupSymbolsInfo(nameSet, container, options, binder) End Sub Private Shared Sub AddLookupSymbolsInfoInInterfaces(nameSet As LookupSymbolsInfo, container As TypeSymbol, lookIn As Queue(Of InterfaceInfo), processed As HashSet(Of InterfaceInfo), options As LookupOptions, binder As Binder) Dim useSiteInfo = CompoundUseSiteInfo(Of AssemblySymbol).Discarded Do Dim currentType As InterfaceInfo = lookIn.Dequeue AddLookupSymbolsInfoWithoutInheritance(nameSet, currentType.InterfaceType, options, container, binder) ' Go to base type, unless that would case infinite recursion or the options or the binder ' disallows it. If (options And LookupOptions.NoBaseClassLookup) = 0 AndAlso Not binder.IgnoreBaseClassesInLookup Then AddBaseInterfacesToTheSearch(binder, currentType, lookIn, processed, useSiteInfo) End If Loop While lookIn.Count <> 0 End Sub Private Shared Sub AddLookupSymbolsInfoInTypeParameter(nameSet As LookupSymbolsInfo, typeParameter As TypeParameterSymbol, options As LookupOptions, binder As Binder) If typeParameter.TypeParameterKind = TypeParameterKind.Cref Then Return End If AddLookupSymbolsInfoInTypeParameterNoExtensionMethods(nameSet, typeParameter, options, binder) ' Search for extension methods. AddExtensionMethodLookupSymbolsInfo(nameSet, typeParameter, options, binder) End Sub Private Shared Sub AddLookupSymbolsInfoInTypeParameterNoExtensionMethods(nameSet As LookupSymbolsInfo, typeParameter As TypeParameterSymbol, options As LookupOptions, binder As Binder) options = options Or LookupOptions.IgnoreExtensionMethods ' Look up in class constraint. Dim constraintClass = typeParameter.GetClassConstraint(CompoundUseSiteInfo(Of AssemblySymbol).Discarded) If constraintClass IsNot Nothing Then AddLookupSymbolsInfoInClass(nameSet, constraintClass, options, binder) End If ' Look up in interface constraints. Dim lookIn As Queue(Of InterfaceInfo) = Nothing Dim processed As HashSet(Of InterfaceInfo) = Nothing AddInterfaceConstraints(typeParameter, lookIn, processed, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) If lookIn IsNot Nothing Then AddLookupSymbolsInfoInInterfaces(nameSet, typeParameter, lookIn, processed, options, binder) End If ' Look up in System.ValueType or System.Object. If constraintClass Is Nothing Then Dim baseType = GetTypeParameterBaseType(typeParameter) AddLookupSymbolsInfoInClass(nameSet, baseType, options, binder) End If End Sub ''' <summary> ''' Lookup a member name in a type without considering inheritance, returning a LookupResult that ''' summarizes the results of the lookup. See LookupResult structure for a detailed ''' discussing of the meaning of the results. ''' </summary> Private Shared Sub LookupWithoutInheritance(lookupResult As LookupResult, container As TypeSymbol, name As String, arity As Integer, options As LookupOptions, accessThroughType As TypeSymbol, binder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol) ) Dim members As ImmutableArray(Of Symbol) = ImmutableArray(Of Symbol).Empty If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly)) = LookupOptions.NamespacesOrTypesOnly Then ' Only named types have members that are types. Go through all the types in this type and ' validate them. If there's multiple, give an error. If TypeOf container Is NamedTypeSymbol Then members = ImmutableArray(Of Symbol).CastUp(container.GetTypeMembers(name)) End If ElseIf (options And LookupOptions.LabelsOnly) = 0 Then members = container.GetMembers(name) End If Debug.Assert(lookupResult.IsClear) ' Go through each member of the type, and combine them into a single result. Overloadable members ' are combined together, while other duplicates cause an ambiguity error. If Not members.IsDefaultOrEmpty Then Dim imported As Boolean = container.ContainingModule IsNot binder.SourceModule For Each sym In members lookupResult.MergeMembersOfTheSameType(binder.CheckViability(sym, arity, options, accessThroughType, useSiteInfo), imported) Next End If End Sub ' Find all names in a type, without considering inheritance. Private Shared Sub AddLookupSymbolsInfoWithoutInheritance(nameSet As LookupSymbolsInfo, container As TypeSymbol, options As LookupOptions, accessThroughType As TypeSymbol, binder As Binder) ' UNDONE: validate symbols with something that looks like ValidateSymbol. If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly)) = LookupOptions.NamespacesOrTypesOnly Then ' Only named types have members that are types. Go through all the types in this type and ' validate them. If TypeOf container Is NamedTypeSymbol Then For Each sym In container.GetTypeMembersUnordered() If binder.CanAddLookupSymbolInfo(sym, options, nameSet, accessThroughType) Then nameSet.AddSymbol(sym, sym.Name, sym.Arity) End If Next End If ElseIf (options And LookupOptions.LabelsOnly) = 0 Then ' Go through each member of the type. For Each sym In container.GetMembersUnordered() If binder.CanAddLookupSymbolInfo(sym, options, nameSet, accessThroughType) Then nameSet.AddSymbol(sym, sym.Name, sym.GetArity()) End If Next End If End Sub Private Shared Sub AddWinRTMembersLookupSymbolsInfo( nameSet As LookupSymbolsInfo, type As NamedTypeSymbol, options As LookupOptions, accessThroughType As TypeSymbol, binder As Binder ) ' Dev11 searches all declared and undeclared base interfaces For Each iface In type.AllInterfacesNoUseSiteDiagnostics If IsWinRTProjectedInterface(iface, binder.Compilation) Then AddLookupSymbolsInfoWithoutInheritance(nameSet, iface, options, accessThroughType, binder) End If Next End Sub Private Shared Function GetTypeParameterBaseType(typeParameter As TypeParameterSymbol) As NamedTypeSymbol ' The default base type should only be used if there is no explicit class constraint. Debug.Assert(typeParameter.GetClassConstraint(CompoundUseSiteInfo(Of AssemblySymbol).Discarded) Is Nothing) Return typeParameter.ContainingAssembly.GetSpecialType(If(typeParameter.HasValueTypeConstraint, SpecialType.System_ValueType, SpecialType.System_Object)) End Function End Class End Class End Namespace