| File: Binding\ImportedTypesAndNamespacesMembersBinder.vb | Web Access |
| Project: src\roslyn\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic) |
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Concurrent Imports System.Collections.Generic Imports System.Collections.Immutable 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> ''' Provides lookup in imported namespaces and types (not the alias kind), ''' either at file level or project level. ''' </summary> Friend Class ImportedTypesAndNamespacesMembersBinder Inherits Binder Private ReadOnly _importedSymbols As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition) Public Sub New(containingBinder As Binder, importedSymbols As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition)) MyBase.New(containingBinder) _importedSymbols = importedSymbols End Sub Friend Overrides Sub LookupInSingleBinder(lookupResult As LookupResult, name As String, arity As Integer, options As LookupOptions, originalBinder As Binder, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(lookupResult.IsClear) ' Look up the name in all imported symbols, merging and generating ambiguity errors if needed. Dim currentResult As LookupResult options = options Or LookupOptions.IgnoreExtensionMethods ' First, lookup immediate members of imported types and namespaces For Each importedSym In _importedSymbols currentResult = LookupResult.GetInstance() If importedSym.NamespaceOrType.IsNamespace Then originalBinder.LookupMemberImmediate(currentResult, DirectCast(importedSym.NamespaceOrType, NamespaceSymbol), name, arity, options, useSiteInfo) Else originalBinder.LookupMember(currentResult, importedSym.NamespaceOrType, name, arity, options, useSiteInfo) End If If currentResult.IsGoodOrAmbiguous AndAlso Not originalBinder.IsSemanticModelBinder Then Me.Compilation.MarkImportDirectiveAsUsed(Me.SyntaxTree, importedSym.ImportsClausePosition) End If ' If lookup in an import produces an ambiguous result, return that ambiguity. Dim cancelLookup As Boolean = currentResult.IsAmbiguous If cancelLookup Then lookupResult.SetFrom(currentResult) Else ' If currentResult is a namespace that doesn't contain accessible types ' (including types in child namespaces), ignore the namespace. If Not (currentResult.IsGood AndAlso currentResult.HasSingleSymbol AndAlso currentResult.SingleSymbol.Kind = SymbolKind.Namespace AndAlso Not DirectCast(currentResult.SingleSymbol, NamespaceSymbol).ContainsTypesAccessibleFrom(Compilation.Assembly)) Then If lookupResult.StopFurtherLookup AndAlso currentResult.StopFurtherLookup Then Debug.Assert(lookupResult.Symbols.Count > 0) ' How can it stop lookup otherwise? Debug.Assert(currentResult.Symbols.Count > 0) ' How can it stop lookup otherwise? Dim lookupResultIsNamespace As Boolean = (lookupResult.Symbols(0).Kind = SymbolKind.Namespace) Dim currentResultIsNamespace As Boolean = (currentResult.Symbols(0).Kind = SymbolKind.Namespace) ' Non-namespace wins over a namespace If lookupResultIsNamespace AndAlso (Not currentResultIsNamespace) Then lookupResult.SetFrom(currentResult) ElseIf (Not currentResultIsNamespace) OrElse lookupResultIsNamespace Then Debug.Assert(currentResultIsNamespace = lookupResultIsNamespace) ' Ignore the same result. Assuming that in case of overloaded members both equal results ' should list members in the same order, it is sufficient to compare first ' symbols from each result. If Not (lookupResult.Symbols.Count = currentResult.Symbols.Count AndAlso lookupResult.Symbols(0).Equals(currentResult.Symbols(0))) Then If lookupResultIsNamespace AndAlso currentResult.IsGood AndAlso lookupResult.IsGood Then ' Collect all ambiguous namespaces so that we can create a namespace group at the end. lookupResult.Symbols.AddRange(currentResult.Symbols) Else lookupResult.MergeAmbiguous(currentResult, GenerateAmbiguityError) End If End If Else Debug.Assert(currentResultIsNamespace AndAlso (Not lookupResultIsNamespace)) ' ignore the current result End If Else lookupResult.MergeAmbiguous(currentResult, GenerateAmbiguityError) End If End If End If currentResult.Free() If cancelLookup Then Debug.Assert(lookupResult.StopFurtherLookup) Exit For End If Next If lookupResult.IsGood AndAlso lookupResult.Symbols.Count > 1 AndAlso lookupResult.Symbols(0).Kind = SymbolKind.Namespace Then ' Create and return namespace group symbol lookupResult.SetFrom(MergedNamespaceSymbol.CreateNamespaceGroup(lookupResult.Symbols.Cast(Of NamespaceSymbol))) End If 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 Overrides Sub CollectProbableExtensionMethodsInSingleBinder(name As String, methods As ArrayBuilder(Of MethodSymbol), originalBinder As Binder) Debug.Assert(methods.Count = 0) For Each importedSym In _importedSymbols If importedSym.NamespaceOrType.Kind = SymbolKind.NamedType Then DirectCast(importedSym.NamespaceOrType, NamedTypeSymbol).AppendProbableExtensionMethods(name, methods) If methods.Count <> 0 AndAlso Not originalBinder.IsSemanticModelBinder Then Me.Compilation.MarkImportDirectiveAsUsed(Me.SyntaxTree, importedSym.ImportsClausePosition) End If End If Next End Sub Protected Overrides Sub AddExtensionMethodLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo, options As LookupOptions, originalBinder As Binder) For Each importedSym In _importedSymbols If importedSym.NamespaceOrType.Kind = SymbolKind.NamedType Then DirectCast(importedSym.NamespaceOrType, NamedTypeSymbol).AddExtensionMethodLookupSymbolsInfo( nameSet, options, originalBinder) End If Next End Sub Friend Overrides Sub AddLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo, options As LookupOptions, originalBinder As Binder) For Each importedSym In _importedSymbols originalBinder.AddMemberLookupSymbolsInfo(nameSet, importedSym.NamespaceOrType, options Or LookupOptions.IgnoreExtensionMethods) Next End Sub Friend Shared GenerateAmbiguityError As Func(Of ImmutableArray(Of Symbol), AmbiguousSymbolDiagnostic) = Function(ambiguousSymbols As ImmutableArray(Of Symbol)) As AmbiguousSymbolDiagnostic Return New AmbiguousSymbolDiagnostic(ERRID.ERR_AmbiguousInImports2, ambiguousSymbols, ambiguousSymbols(0).Name, New FormattedSymbolList(ambiguousSymbols.Select(Function(sym) sym.ContainingSymbol))) End Function End Class End Namespace