File: Binding\DocumentationCommentCrefBinder.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports System.Collections.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