/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Binding/DocumentationCommentCrefBinder.vb
1 121 строка
56 KB
AlekseyTs
Merge remote-tracking branch 'dotnet/master' into UsedAssemblies_13
24 янв 2020, 03:48
24 янв 2020, 03:48
5f06615
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports System.Runtime.InteropServices Imports System.Threading Namespace Microsoft.CodeAnalysis.VisualBasic ''' <summary> ''' Binder used for interiors of documentation comment for binding 'cref' attribute value ''' </summary> Partial Friend NotInheritable Class DocumentationCommentCrefBinder Inherits DocumentationCommentBinder Public Sub New(containingBinder As Binder, commentedSymbol As Symbol) MyBase.New(containingBinder, commentedSymbol) End Sub Private _typeParameterBinder As TypeParametersBinder Private Function GetOrCreateTypeParametersAwareBinder(typeParameters As Dictionary(Of String, CrefTypeParameterSymbol)) As Binder If Me._typeParameterBinder Is Nothing Then Interlocked.CompareExchange(Me._typeParameterBinder, New TypeParametersBinder(Me, typeParameters), Nothing) End If #If DEBUG Then ' Make sure the type parameter symbols are the same Debug.Assert(typeParameters.Count = Me._typeParameterBinder._typeParameters.Count) For Each kvp In typeParameters Debug.Assert(kvp.Value.Equals(Me._typeParameterBinder._typeParameters(kvp.Key))) Next #End If Return Me._typeParameterBinder End Function Private Shared Function HasTrailingSkippedTokensAndShouldReportError(reference As CrefReferenceSyntax) As Boolean Dim triviaList As SyntaxTriviaList = reference.GetTrailingTrivia() For Each trivia In triviaList If trivia.Kind = SyntaxKind.SkippedTokensTrivia Then ' ignore those, representing VB intrinsic types Dim name As TypeSyntax = reference.Name If name.Kind = SyntaxKind.IdentifierName Then Dim identifier As SyntaxToken = DirectCast(name, IdentifierNameSyntax).Identifier If Not identifier.IsBracketed AndAlso IsIntrinsicTypeForDocumentationComment(SyntaxFacts.GetKeywordKind(identifier.ValueText)) Then ' special case to be ignored, also see description ' in ParseXml.vb::TryParseXmlCrefAttributeValue(...) Continue For End If ElseIf name.Kind = SyntaxKind.PredefinedType Then Continue For End If ' Otherwise report an error Return True End If Next Return False End Function Friend Overrides Function BindInsideCrefAttributeValue(reference As CrefReferenceSyntax, preserveAliases As Boolean, diagnosticBag As BindingDiagnosticBag, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ImmutableArray(Of Symbol) ' If the node has trailing syntax nodes, it should report error, unless the name ' is a VB intrinsic type (which ensures compatibility with Dev11) If HasTrailingSkippedTokensAndShouldReportError(reference) Then Return ImmutableArray(Of Symbol).Empty End If If reference.Signature Is Nothing Then Return BindNameInsideCrefReferenceInLegacyMode(reference.Name, preserveAliases, useSiteInfo) End If ' Extended 'cref' attribute syntax should not contain complex generic arguments ' such as in [cref="List(Of Action(Of A))"], because these generic arguments actually ' define type parameters to be used in signature part and return value If NameSyntaxHasComplexGenericArguments(reference.Name) Then Return ImmutableArray(Of Symbol).Empty End If Dim symbols = ArrayBuilder(Of Symbol).GetInstance ' Bind the name part and collect type parameters Dim typeParameters As New Dictionary(Of String, CrefTypeParameterSymbol)(CaseInsensitiveComparison.Comparer) CollectCrefNameSymbolsStrict(reference.Name, reference.Signature.ArgumentTypes.Count, typeParameters, symbols, preserveAliases, useSiteInfo) If symbols.Count = 0 Then symbols.Free() Return ImmutableArray(Of Symbol).Empty End If RemoveOverriddenMethodsAndProperties(symbols) ' Bind signature and return type if present Dim signatureTypes As ArrayBuilder(Of SignatureElement) = Nothing Dim returnType As TypeSymbol = Nothing BindSignatureAndReturnValue(reference, typeParameters, signatureTypes, returnType, diagnosticBag) ' Create only if needed Debug.Assert(signatureTypes Is Nothing OrElse signatureTypes.Count > 0) Dim signatureParameterCount As Integer = If(signatureTypes Is Nothing, 0, signatureTypes.Count) ' Choose between symbols those with matching signatures Dim candidatePointer As Integer = 0 Dim goodPointer As Integer = 0 While candidatePointer < symbols.Count Dim candidateSymbol As Symbol = symbols(candidatePointer) ' NOTE: we do a very simple signature check and ' avoid using signature comparer Select Case candidateSymbol.Kind Case SymbolKind.Method Dim candidateMethod = DirectCast(candidateSymbol, MethodSymbol) If candidateMethod.ParameterCount <> signatureParameterCount Then ' Signature does not match Exit Select End If Dim parameters As ImmutableArray(Of ParameterSymbol) = candidateMethod.Parameters For i = 0 To signatureParameterCount - 1 Dim parameter As ParameterSymbol = parameters(i) If parameter.IsByRef <> signatureTypes(i).IsByRef OrElse Not parameter.Type.IsSameTypeIgnoringAll(signatureTypes(i).Type) Then ' Signature does not match Exit Select End If Next If returnType IsNot Nothing Then If candidateMethod.IsSub OrElse Not candidateMethod.ReturnType.IsSameTypeIgnoringAll(returnType) Then ' Return type does not match Exit Select End If End If ' Good candidate symbols(goodPointer) = candidateSymbol goodPointer += 1 candidatePointer += 1 Continue While Case SymbolKind.Property Dim candidateProperty = DirectCast(candidateSymbol, PropertySymbol) Dim parameters As ImmutableArray(Of ParameterSymbol) = candidateProperty.Parameters If parameters.Length <> signatureParameterCount Then ' Signature does not match Exit Select End If For i = 0 To signatureParameterCount - 1 Dim parameter As ParameterSymbol = parameters(i) If parameter.IsByRef <> signatureTypes(i).IsByRef OrElse Not parameter.Type.IsSameTypeIgnoringAll(signatureTypes(i).Type) Then ' Signature does not match Exit Select End If Next Debug.Assert(returnType Is Nothing, "Return type is only allowed for Operator CType, why we found a property here?") ' Good candidate symbols(goodPointer) = candidateSymbol goodPointer += 1 candidatePointer += 1 Continue While Case Else ' All other symbols are ignored End Select ' Ignore symbol candidatePointer += 1 End While If signatureTypes IsNot Nothing Then signatureTypes.Free() End If If goodPointer < candidatePointer Then symbols.Clip(goodPointer) End If Return symbols.ToImmutableAndFree() End Function Friend Overrides Function BindInsideCrefAttributeValue(name As TypeSyntax, preserveAliases As Boolean, diagnosticBag As BindingDiagnosticBag, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ImmutableArray(Of Symbol) Dim isPartOfSignatureOrReturnType As Boolean = False Dim crefReference As CrefReferenceSyntax = GetEnclosingCrefReference(name, isPartOfSignatureOrReturnType) If crefReference Is Nothing Then Debug.Assert(False, "Speculative binding??") Return ImmutableArray(Of Symbol).Empty End If If crefReference.Signature Is Nothing Then Debug.Assert(Not isPartOfSignatureOrReturnType) Return BindNameInsideCrefReferenceInLegacyMode(name, preserveAliases, useSiteInfo) End If If isPartOfSignatureOrReturnType Then Return BindInsideCrefSignatureOrReturnType(crefReference, name, preserveAliases, diagnosticBag) Else Return BindInsideCrefReferenceName(name, crefReference.Signature.ArgumentTypes.Count, preserveAliases, useSiteInfo) End If End Function Private Function BindInsideCrefSignatureOrReturnType(crefReference As CrefReferenceSyntax, name As TypeSyntax, preserveAliases As Boolean, diagnosticBag As BindingDiagnosticBag) As ImmutableArray(Of Symbol) Dim typeParameterAwareBinder As Binder = Me.GetOrCreateTypeParametersAwareBinder(crefReference) Dim result As Symbol = typeParameterAwareBinder.BindNamespaceOrTypeOrAliasSyntax(name, If(diagnosticBag, BindingDiagnosticBag.Discarded)) result = typeParameterAwareBinder.BindNamespaceOrTypeOrAliasSyntax(name, If(diagnosticBag, BindingDiagnosticBag.Discarded)) If result IsNot Nothing AndAlso result.Kind = SymbolKind.Alias AndAlso Not preserveAliases Then result = DirectCast(result, AliasSymbol).Target End If Return If(result Is Nothing, ImmutableArray(Of Symbol).Empty, ImmutableArray.Create(Of Symbol)(result)) End Function Private Function GetOrCreateTypeParametersAwareBinder(crefReference As CrefReferenceSyntax) As Binder ' To create type-param-aware binder we need to have type parameters, ' but we don't want to do so if the binder is already created If Me._typeParameterBinder IsNot Nothing Then Return Me._typeParameterBinder End If Dim typeParameters As New Dictionary(Of String, CrefTypeParameterSymbol)(IdentifierComparison.Comparer) Dim crefName As TypeSyntax = crefReference.Name Dim genericName As GenericNameSyntax = Nothing While crefName IsNot Nothing Select Case crefName.Kind Case SyntaxKind.GenericName genericName = DirectCast(crefName, GenericNameSyntax) crefName = Nothing Case SyntaxKind.QualifiedName Dim qName = DirectCast(crefName, QualifiedNameSyntax) crefName = qName.Left If qName.Right.Kind = SyntaxKind.GenericName Then genericName = DirectCast(qName.Right, GenericNameSyntax) End If Case SyntaxKind.IdentifierName, SyntaxKind.CrefOperatorReference, SyntaxKind.GlobalName, SyntaxKind.PredefinedType Exit While Case SyntaxKind.QualifiedCrefOperatorReference crefName = DirectCast(crefName, QualifiedCrefOperatorReferenceSyntax).Left Case Else Throw ExceptionUtilities.UnexpectedValue(crefName.Kind) End Select ' Fall back to the next name part, if we need to collect type ' parameters genericName is supposed to be not Nothing If genericName IsNot Nothing Then Dim arguments As SeparatedSyntaxList(Of TypeSyntax) = genericName.TypeArgumentList.Arguments For i = 0 To arguments.Count - 1 Dim typeSyntax As TypeSyntax = arguments(i) Select Case typeSyntax.Kind Case SyntaxKind.IdentifierName Dim identifier = DirectCast(typeSyntax, IdentifierNameSyntax) Dim typeParameterName As String = identifier.Identifier.ValueText ' As we go 'left-to-right' don't override right-most parameters with the same name If Not typeParameters.ContainsKey(typeParameterName) Then typeParameters(typeParameterName) = New CrefTypeParameterSymbol(i, typeParameterName, identifier) End If Case Else ' An error case End Select Next End If End While Return GetOrCreateTypeParametersAwareBinder(typeParameters) End Function Private Function BindInsideCrefReferenceName(name As TypeSyntax, argCount As Integer, preserveAliases As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) As ImmutableArray(Of Symbol) ' NOTE: in code here and below 'parent' may be Nothing in ' case of speculative binding (which is NYI) Dim parent As VisualBasicSyntaxNode = name.Parent ' Type parameter If parent IsNot Nothing AndAlso parent.Kind = SyntaxKind.TypeArgumentList Then Dim ordinal As Integer = DirectCast(parent, TypeArgumentListSyntax).Arguments.IndexOf(name) If name.Kind = SyntaxKind.IdentifierName Then Dim identifier = DirectCast(name, IdentifierNameSyntax) Return ImmutableArray.Create(Of Symbol)(New CrefTypeParameterSymbol(ordinal, identifier.Identifier.ValueText, identifier)) End If ' An error case Return ImmutableArray.Create(Of Symbol)(New CrefTypeParameterSymbol(ordinal, StringConstants.NamedSymbolErrorName, name)) End If ' Names considered to be checked for color-color case are Identifier or Generic names which ' are the left part of the qualified name parent Dim checkForColorColor As Boolean = False Dim nameText As String = Nothing Dim arity As Integer = -1 lAgain: Select Case name.Kind Case SyntaxKind.IdentifierName, SyntaxKind.GenericName If parent IsNot Nothing AndAlso parent.Kind = SyntaxKind.QualifiedName Then Dim qualified = DirectCast(parent, QualifiedNameSyntax) If qualified.Right Is name Then name = qualified parent = name.Parent GoTo lAgain End If End If ' color-color info checkForColorColor = True If name.Kind = SyntaxKind.IdentifierName Then nameText = DirectCast(name, IdentifierNameSyntax).Identifier.ValueText arity = 0 Else Dim generic = DirectCast(name, GenericNameSyntax) nameText = generic.Identifier.ValueText arity = generic.TypeArgumentList.Arguments.Count End If ' Fall through Case SyntaxKind.CrefOperatorReference If parent IsNot Nothing AndAlso parent.Kind = SyntaxKind.QualifiedCrefOperatorReference Then name = DirectCast(parent, QualifiedCrefOperatorReferenceSyntax) parent = name.Parent GoTo lAgain End If ' Fall through Case SyntaxKind.QualifiedName, SyntaxKind.QualifiedCrefOperatorReference ' Fall through Case SyntaxKind.GlobalName Return ImmutableArray.Create(Of Symbol)(Me.Compilation.GlobalNamespace) Case Else Throw ExceptionUtilities.UnexpectedValue(name.Kind) End Select Dim symbols = ArrayBuilder(Of Symbol).GetInstance CollectCrefNameSymbolsStrict(name, argCount, New Dictionary(Of String, CrefTypeParameterSymbol)(IdentifierComparison.Comparer), symbols, preserveAliases, useSiteInfo) RemoveOverriddenMethodsAndProperties(symbols) If symbols.Count = 1 AndAlso checkForColorColor Then Dim symbol As Symbol = symbols(0) Dim type As TypeSymbol = Nothing Select Case symbol.Kind Case SymbolKind.Field type = DirectCast(symbol, FieldSymbol).Type Case SymbolKind.Method type = DirectCast(symbol, MethodSymbol).ReturnType Case SymbolKind.Property type = DirectCast(symbol, PropertySymbol).Type End Select Dim replaceWithType As Boolean = False If type IsNot Nothing Then If IdentifierComparison.Equals(type.Name, nameText) Then Dim namedType = TryCast(type, NamedTypeSymbol) If namedType IsNot Nothing Then replaceWithType = namedType.Arity = arity Else replaceWithType = arity = 0 End If End If End If If replaceWithType Then symbols(0) = type End If End If Return symbols.ToImmutableAndFree() End Function Private Shared Function GetEnclosingCrefReference(nameFromCref As TypeSyntax, <Out> ByRef partOfSignatureOrReturnType As Boolean) As CrefReferenceSyntax partOfSignatureOrReturnType = False Dim node As VisualBasicSyntaxNode = nameFromCref While node IsNot Nothing Select Case node.Kind Case SyntaxKind.CrefReference Exit While Case SyntaxKind.SimpleAsClause partOfSignatureOrReturnType = True Case SyntaxKind.CrefSignature partOfSignatureOrReturnType = True End Select node = node.Parent End While Return DirectCast(node, CrefReferenceSyntax) End Function Private Structure SignatureElement Public ReadOnly Type As TypeSymbol Public ReadOnly IsByRef As Boolean Public Sub New(type As TypeSymbol, isByRef As Boolean) Me.Type = type Me.IsByRef = isByRef End Sub End Structure Private Sub BindSignatureAndReturnValue(reference As CrefReferenceSyntax, typeParameters As Dictionary(Of String, CrefTypeParameterSymbol), <Out> ByRef signatureTypes As ArrayBuilder(Of SignatureElement), <Out> ByRef returnType As TypeSymbol, diagnosticBag As BindingDiagnosticBag) signatureTypes = Nothing returnType = Nothing Dim typeParameterAwareBinder As Binder = Me.GetOrCreateTypeParametersAwareBinder(typeParameters) Dim diagnostic = If(diagnosticBag, BindingDiagnosticBag.Discarded) Dim signature As CrefSignatureSyntax = reference.Signature Debug.Assert(signature IsNot Nothing) If signature.ArgumentTypes.Count > 0 Then signatureTypes = ArrayBuilder(Of SignatureElement).GetInstance For Each part In signature.ArgumentTypes signatureTypes.Add( New SignatureElement( typeParameterAwareBinder.BindTypeSyntax(part.Type, diagnostic), part.Modifier.Kind = SyntaxKind.ByRefKeyword)) Next End If If reference.AsClause IsNot Nothing Then returnType = typeParameterAwareBinder.BindTypeSyntax(reference.AsClause.Type, diagnostic) End If End Sub Private Sub CollectCrefNameSymbolsStrict(nameFromCref As TypeSyntax, argsCount As Integer, typeParameters As Dictionary(Of String, CrefTypeParameterSymbol), symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) ' This binding mode is used for extended cref-reference syntax with mandatory ' signature specified, we enforce more strict rules in this case Select Case nameFromCref.Kind Case SyntaxKind.QualifiedCrefOperatorReference ' 'A.B.Operator+' or 'C(Of T).Operator CType' CollectQualifiedOperatorReferenceSymbolsStrict( DirectCast(nameFromCref, QualifiedCrefOperatorReferenceSyntax), argsCount, typeParameters, symbols, useSiteInfo) Case SyntaxKind.CrefOperatorReference ' 'Operator+' or 'Operator CType' CollectTopLevelOperatorReferenceStrict( DirectCast(nameFromCref, CrefOperatorReferenceSyntax), argsCount, symbols, useSiteInfo) Case SyntaxKind.IdentifierName, SyntaxKind.GenericName ' 'New', 'A', or 'B(Of T)' CollectSimpleNameSymbolsStrict( DirectCast(nameFromCref, SimpleNameSyntax), typeParameters, symbols, preserveAlias, useSiteInfo, False) Case SyntaxKind.QualifiedName ' 'A(Of T).B.M(Of E)' CollectQualifiedNameSymbolsStrict( DirectCast(nameFromCref, QualifiedNameSyntax), typeParameters, symbols, preserveAlias, useSiteInfo) Case Else Throw ExceptionUtilities.UnexpectedValue(nameFromCref.Kind) End Select End Sub Private Sub CollectTopLevelOperatorReferenceStrict(reference As CrefOperatorReferenceSyntax, argCount As Integer, symbols As ArrayBuilder(Of Symbol), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) CollectOperatorsAndConversionsInType(reference, argCount, Me.ContainingType, symbols, useSiteInfo) End Sub Private Sub CollectSimpleNameSymbolsStrict(node As SimpleNameSyntax, typeParameters As Dictionary(Of String, CrefTypeParameterSymbol), symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), typeOrNamespaceOnly As Boolean) ' Name syntax of Cref should not have diagnostics If node.ContainsDiagnostics Then Return End If If node.Kind = SyntaxKind.GenericName Then ' Generic name Dim genericName = DirectCast(node, GenericNameSyntax) ' Search exact arity only CollectSimpleNameSymbolsStrict(genericName.Identifier.ValueText, genericName.TypeArgumentList.Arguments.Count, symbols, preserveAlias, useSiteInfo, typeOrNamespaceOnly) CreateTypeParameterSymbolsAndConstructSymbols(genericName, symbols, typeParameters) Else ' Simple identifier name Debug.Assert(node.Kind = SyntaxKind.IdentifierName) Dim identifier = DirectCast(node, IdentifierNameSyntax) Dim token As SyntaxToken = identifier.Identifier If IdentifierComparison.Equals(identifier.Identifier.ValueText, SyntaxFacts.GetText(SyntaxKind.NewKeyword)) AndAlso Not token.IsBracketed Then CollectConstructorsSymbolsStrict(symbols) Else ' Search 0-arity only CollectSimpleNameSymbolsStrict(identifier.Identifier.ValueText, 0, symbols, preserveAlias, useSiteInfo, typeOrNamespaceOnly) End If End If End Sub Private Sub CollectQualifiedNameSymbolsStrict(node As QualifiedNameSyntax, typeParameters As Dictionary(Of String, CrefTypeParameterSymbol), symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) ' Name syntax of Cref should not have diagnostics If node.ContainsDiagnostics Then Return End If Dim allowColorColor As Boolean = True Dim left As NameSyntax = node.Left Select Case left.Kind Case SyntaxKind.IdentifierName CollectSimpleNameSymbolsStrict(DirectCast(left, SimpleNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo, typeOrNamespaceOnly:=True) Case SyntaxKind.GenericName CollectSimpleNameSymbolsStrict(DirectCast(left, SimpleNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo, typeOrNamespaceOnly:=True) Case SyntaxKind.QualifiedName CollectQualifiedNameSymbolsStrict(DirectCast(left, QualifiedNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo) allowColorColor = False Case SyntaxKind.GlobalName symbols.Add(Me.Compilation.GlobalNamespace) Case Else Throw ExceptionUtilities.UnexpectedValue(left.Kind) End Select If symbols.Count <> 1 Then ' Stop resolving typeParameters.Clear() symbols.Clear() Return End If Dim singleSymbol As Symbol = symbols(0) symbols.Clear() ' We found one single symbol, we need to search for the 'right' ' name in the context of this symbol Dim right As SimpleNameSyntax = node.Right If right.Kind = SyntaxKind.GenericName Then ' Generic name Dim genericName = DirectCast(right, GenericNameSyntax) ' Search exact arity only CollectSimpleNameSymbolsStrict(singleSymbol, allowColorColor, genericName.Identifier.ValueText, genericName.TypeArgumentList.Arguments.Count, symbols, preserveAlias, useSiteInfo) CreateTypeParameterSymbolsAndConstructSymbols(genericName, symbols, typeParameters) Else ' Simple identifier name Debug.Assert(right.Kind = SyntaxKind.IdentifierName) Dim identifier = DirectCast(right, IdentifierNameSyntax) Dim token As SyntaxToken = identifier.Identifier If IdentifierComparison.Equals(identifier.Identifier.ValueText, SyntaxFacts.GetText(SyntaxKind.NewKeyword)) AndAlso Not token.IsBracketed Then CollectConstructorsSymbolsStrict(singleSymbol, symbols) Else ' Search 0-arity only CollectSimpleNameSymbolsStrict(singleSymbol, allowColorColor, identifier.Identifier.ValueText, 0, symbols, preserveAlias, useSiteInfo) End If End If End Sub Private Sub CollectQualifiedOperatorReferenceSymbolsStrict(node As QualifiedCrefOperatorReferenceSyntax, argCount As Integer, typeParameters As Dictionary(Of String, CrefTypeParameterSymbol), symbols As ArrayBuilder(Of Symbol), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) ' Name syntax of Cref should not have diagnostics If node.ContainsDiagnostics Then Return End If Dim allowColorColor As Boolean = True Dim left As NameSyntax = node.Left Select Case left.Kind Case SyntaxKind.IdentifierName CollectSimpleNameSymbolsStrict(DirectCast(left, SimpleNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo, typeOrNamespaceOnly:=True) Case SyntaxKind.GenericName CollectSimpleNameSymbolsStrict(DirectCast(left, SimpleNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo, typeOrNamespaceOnly:=True) Case SyntaxKind.QualifiedName CollectQualifiedNameSymbolsStrict(DirectCast(left, QualifiedNameSyntax), typeParameters, symbols, preserveAlias:=False, useSiteInfo:=useSiteInfo) allowColorColor = False Case Else Throw ExceptionUtilities.UnexpectedValue(left.Kind) End Select If symbols.Count <> 1 Then ' Stop resolving typeParameters.Clear() symbols.Clear() Return End If Dim singleSymbol As Symbol = symbols(0) symbols.Clear() If singleSymbol.Kind = SymbolKind.Alias Then singleSymbol = DirectCast(singleSymbol, AliasSymbol).Target End If CollectOperatorsAndConversionsInType(node.Right, argCount, TryCast(singleSymbol, TypeSymbol), symbols, useSiteInfo) End Sub Private Sub CollectConstructorsSymbolsStrict(symbols As ArrayBuilder(Of Symbol)) Dim containingSymbol As Symbol = Me.ContainingMember If containingSymbol Is Nothing Then Return End If If containingSymbol.Kind <> SymbolKind.NamedType Then containingSymbol = containingSymbol.ContainingType End If Dim type = DirectCast(containingSymbol, NamedTypeSymbol) If type IsNot Nothing Then symbols.AddRange(type.InstanceConstructors) End If Return End Sub Private Shared Sub CollectConstructorsSymbolsStrict(containingSymbol As Symbol, symbols As ArrayBuilder(Of Symbol)) Debug.Assert(symbols.Count = 0) If containingSymbol.Kind = SymbolKind.NamedType Then symbols.AddRange(DirectCast(containingSymbol, NamedTypeSymbol).InstanceConstructors) End If End Sub Private Sub CollectSimpleNameSymbolsStrict(name As String, arity As Integer, symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), typeOrNamespaceOnly As Boolean) Debug.Assert(Not String.IsNullOrEmpty(name)) Debug.Assert(arity >= 0) Const options As LookupOptions = LookupOptions.UseBaseReferenceAccessibility Or LookupOptions.MustNotBeReturnValueVariable Or LookupOptions.IgnoreExtensionMethods Or LookupOptions.MustNotBeLocalOrParameter Or LookupOptions.NoSystemObjectLookupForInterfaces Dim result As LookupResult = LookupResult.GetInstance() Me.Lookup(result, name, arity, If(typeOrNamespaceOnly, options Or LookupOptions.NamespacesOrTypesOnly, options), useSiteInfo) If Not result.IsGoodOrAmbiguous OrElse Not result.HasSymbol Then result.Free() Return End If CollectGoodOrAmbiguousFromLookupResult(result, symbols, preserveAlias) result.Free() End Sub Private Sub CollectSimpleNameSymbolsStrict(containingSymbol As Symbol, allowColorColor As Boolean, name As String, arity As Integer, symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) Debug.Assert(Not String.IsNullOrEmpty(name)) Debug.Assert(arity >= 0) Dim lookupResult As LookupResult = lookupResult.GetInstance() Dim options As LookupOptions = LookupOptions.UseBaseReferenceAccessibility Or LookupOptions.MustNotBeReturnValueVariable Or LookupOptions.IgnoreExtensionMethods Or LookupOptions.MustNotBeLocalOrParameter Or LookupOptions.NoSystemObjectLookupForInterfaces lAgain: Select Case containingSymbol.Kind Case SymbolKind.Namespace LookupMember(lookupResult, DirectCast(containingSymbol, NamespaceSymbol), name, arity, options, useSiteInfo) Case SymbolKind.Alias containingSymbol = DirectCast(containingSymbol, AliasSymbol).Target GoTo lAgain Case SymbolKind.NamedType, SymbolKind.ArrayType LookupMember(lookupResult, DirectCast(containingSymbol, TypeSymbol), name, arity, options, useSiteInfo) Case SymbolKind.Property If allowColorColor Then ' Check for Color Color case Dim [property] = DirectCast(containingSymbol, PropertySymbol) Dim propertyType As TypeSymbol = [property].Type If IdentifierComparison.Equals([property].Name, propertyType.Name) Then containingSymbol = propertyType GoTo lAgain End If End If Case SymbolKind.Field If allowColorColor Then ' Check for Color Color case Dim field = DirectCast(containingSymbol, FieldSymbol) Dim fieldType As TypeSymbol = field.Type If IdentifierComparison.Equals(field.Name, fieldType.Name) Then containingSymbol = fieldType GoTo lAgain End If End If Case SymbolKind.Method ' Check for Color Color case If allowColorColor Then Dim method = DirectCast(containingSymbol, MethodSymbol) If Not method.IsSub Then Dim returnType As TypeSymbol = method.ReturnType If IdentifierComparison.Equals(method.Name, returnType.Name) Then containingSymbol = returnType GoTo lAgain End If End If End If Case Else ' Nothing can be found in context of these symbols End Select If Not lookupResult.IsGoodOrAmbiguous OrElse Not lookupResult.HasSymbol Then lookupResult.Free() Return End If CollectGoodOrAmbiguousFromLookupResult(lookupResult, symbols, preserveAlias) lookupResult.Free() End Sub Private Shared Sub CreateTypeParameterSymbolsAndConstructSymbols(genericName As GenericNameSyntax, symbols As ArrayBuilder(Of Symbol), typeParameters As Dictionary(Of String, CrefTypeParameterSymbol)) Dim arguments As SeparatedSyntaxList(Of TypeSyntax) = genericName.TypeArgumentList.Arguments Dim typeParameterSymbols(arguments.Count - 1) As TypeSymbol For i = 0 To arguments.Count - 1 Dim typeSyntax As TypeSyntax = arguments(i) Dim created As CrefTypeParameterSymbol = Nothing Select Case typeSyntax.Kind Case SyntaxKind.IdentifierName Dim identifier = DirectCast(typeSyntax, IdentifierNameSyntax) created = New CrefTypeParameterSymbol(i, identifier.Identifier.ValueText, identifier) typeParameterSymbols(i) = created Case Else ' An error case created = New CrefTypeParameterSymbol(i, StringConstants.NamedSymbolErrorName, typeSyntax) typeParameterSymbols(i) = created End Select typeParameters(created.Name) = created Next For i = 0 To symbols.Count - 1 Dim symbol As Symbol = symbols(i) lAgain: Select Case symbol.Kind Case SymbolKind.Method Dim method = DirectCast(symbol, MethodSymbol) Debug.Assert(method.Arity = genericName.TypeArgumentList.Arguments.Count) symbols(i) = method.Construct(typeParameterSymbols.AsImmutableOrNull.As(Of TypeSymbol)) Case SymbolKind.NamedType, SymbolKind.ErrorType Dim type = DirectCast(symbol, NamedTypeSymbol) Debug.Assert(type.Arity = genericName.TypeArgumentList.Arguments.Count) symbols(i) = type.Construct(typeParameterSymbols.AsImmutableOrNull.As(Of TypeSymbol)) Case SymbolKind.Alias symbol = DirectCast(symbol, AliasSymbol).Target GoTo lAgain End Select Next End Sub Private Shared Sub CollectGoodOrAmbiguousFromLookupResult(lookupResult As LookupResult, symbols As ArrayBuilder(Of Symbol), preserveAlias As Boolean) Dim di As DiagnosticInfo = lookupResult.Diagnostic If TypeOf di Is AmbiguousSymbolDiagnostic Then ' Several ambiguous symbols wrapped in 'AmbiguousSymbolDiagnostic', return ' unwrapped symbols in 'ambiguousSymbols' and return Nothing as a result Debug.Assert(lookupResult.Kind = LookupResultKind.Ambiguous) Dim ambiguousSymbols As ImmutableArray(Of Symbol) = DirectCast(di, AmbiguousSymbolDiagnostic).AmbiguousSymbols Debug.Assert(ambiguousSymbols.Length > 1) For Each sym In ambiguousSymbols symbols.Add(If(preserveAlias, sym, UnwrapAlias(sym))) Next Else ' Return result as a single good symbol For Each sym In lookupResult.Symbols symbols.Add(If(preserveAlias, sym, UnwrapAlias(sym))) Next End If End Sub Private Shared Sub CollectOperatorsAndConversionsInType(crefOperator As CrefOperatorReferenceSyntax, argCount As Integer, type As TypeSymbol, symbols As ArrayBuilder(Of Symbol), <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol)) If type Is Nothing Then Return End If If argCount > 2 OrElse argCount < 1 Then Return End If Select Case crefOperator.OperatorToken.Kind Case SyntaxKind.IsTrueKeyword If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(UnaryOperatorKind.IsTrue) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.TrueOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.IsFalseKeyword If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(UnaryOperatorKind.IsFalse) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.FalseOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.NotKeyword If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(UnaryOperatorKind.Not) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.OnesComplementOperatorName, opInfo, useSiteInfo, WellKnownMemberNames.LogicalNotOperatorName, opInfo) End If Case SyntaxKind.PlusToken If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(UnaryOperatorKind.Plus) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.UnaryPlusOperatorName, opInfo, useSiteInfo) Else Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Add) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.AdditionOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.MinusToken If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(UnaryOperatorKind.Minus) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.UnaryNegationOperatorName, opInfo, useSiteInfo) Else Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Subtract) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.SubtractionOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.AsteriskToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Multiply) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.MultiplyOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.SlashToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Divide) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.DivisionOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.BackslashToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.IntegerDivide) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.IntegerDivisionOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.ModKeyword If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Modulo) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.ModulusOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.CaretToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Power) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.ExponentOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.EqualsToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Equals) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.EqualityOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.LessThanGreaterThanToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.NotEquals) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.InequalityOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.LessThanToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.LessThan) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.LessThanOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.GreaterThanToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.GreaterThan) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.GreaterThanOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.LessThanEqualsToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.LessThanOrEqual) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.LessThanOrEqualOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.GreaterThanEqualsToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.GreaterThanOrEqual) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.GreaterThanOrEqualOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.LikeKeyword If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Like) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.LikeOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.AmpersandToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Concatenate) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.ConcatenateOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.AndKeyword If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.And) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.BitwiseAndOperatorName, opInfo, useSiteInfo, WellKnownMemberNames.LogicalAndOperatorName, opInfo) End If Case SyntaxKind.OrKeyword If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Or) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.BitwiseOrOperatorName, opInfo, useSiteInfo, WellKnownMemberNames.LogicalOrOperatorName, opInfo) End If Case SyntaxKind.XorKeyword If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.Xor) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.ExclusiveOrOperatorName, opInfo, useSiteInfo) End If Case SyntaxKind.LessThanLessThanToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.LeftShift) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.LeftShiftOperatorName, opInfo, useSiteInfo, WellKnownMemberNames.UnsignedLeftShiftOperatorName, opInfo) End If Case SyntaxKind.GreaterThanGreaterThanToken If argCount = 2 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.RightShift) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.UserDefinedOperator, WellKnownMemberNames.RightShiftOperatorName, opInfo, useSiteInfo, WellKnownMemberNames.UnsignedRightShiftOperatorName, opInfo) End If Case SyntaxKind.CTypeKeyword If argCount = 1 Then Dim opInfo As New OverloadResolution.OperatorInfo(BinaryOperatorKind.RightShift) CollectOperatorsAndConversionsInType(type, symbols, MethodKind.Conversion, WellKnownMemberNames.ImplicitConversionName, New OverloadResolution.OperatorInfo(UnaryOperatorKind.Implicit), useSiteInfo, WellKnownMemberNames.ExplicitConversionName, New OverloadResolution.OperatorInfo(UnaryOperatorKind.Explicit)) End If Case Else Throw ExceptionUtilities.UnexpectedValue(crefOperator.OperatorToken.Kind) End Select End Sub Private Shared Sub CollectOperatorsAndConversionsInType(type As TypeSymbol, symbols As ArrayBuilder(Of Symbol), kind As MethodKind, name1 As String, info1 As OverloadResolution.OperatorInfo, <[In], Out> ByRef useSiteInfo As CompoundUseSiteInfo(Of AssemblySymbol), Optional name2 As String = Nothing, Optional info2 As OverloadResolution.OperatorInfo = Nothing) Dim methods = ArrayBuilder(Of MethodSymbol).GetInstance() OverloadResolution.CollectUserDefinedOperators(type, Nothing, kind, name1, info1, name2, info2, methods, useSiteInfo) symbols.AddRange(methods) methods.Free() End Sub Private Shared Function NameSyntaxHasComplexGenericArguments(name As TypeSyntax) As Boolean Select Case name.Kind Case SyntaxKind.IdentifierName, SyntaxKind.CrefOperatorReference, SyntaxKind.GlobalName, SyntaxKind.PredefinedType Return False Case SyntaxKind.QualifiedCrefOperatorReference Return NameSyntaxHasComplexGenericArguments(DirectCast(name, QualifiedCrefOperatorReferenceSyntax).Left) Case SyntaxKind.QualifiedName Dim qualified = DirectCast(name, QualifiedNameSyntax) Return NameSyntaxHasComplexGenericArguments(qualified.Left) OrElse NameSyntaxHasComplexGenericArguments(qualified.Right) Case SyntaxKind.GenericName Dim genericArguments = DirectCast(name, GenericNameSyntax).TypeArgumentList.Arguments For i = 0 To genericArguments.Count - 1 If genericArguments(i).Kind <> SyntaxKind.IdentifierName Then Return True End If Next Return False Case Else Throw ExceptionUtilities.UnexpectedValue(name.Kind) End Select End Function End Class End Namespace