' 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.Generic
Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic
    Partial Friend Class Binder
        Private Function BindXmlComment(
                                       syntax As XmlCommentSyntax,
                                       rootInfoOpt As XmlElementRootInfo,
                                       diagnostics As BindingDiagnosticBag) As BoundExpression
            If rootInfoOpt Is Nothing Then
                diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)
            End If

            Dim str = CreateStringLiteral(syntax, GetXmlString(syntax.TextTokens), compilerGenerated:=True, diagnostics:=diagnostics)
            Dim objectCreation = BindObjectCreationExpression(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XComment, syntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(str),
                diagnostics)
            Return New BoundXmlComment(syntax, str, objectCreation, objectCreation.Type)
        End Function

        Private Function BindXmlDocument(syntax As XmlDocumentSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)

            Dim declaration = BindXmlDeclaration(syntax.Declaration, diagnostics)

            ' Match the native compiler and invoke the XDocument(XDeclaration, Params Object())
            ' .ctor, with Nothing for the Params array argument.
            Dim objectCreation = BindObjectCreationExpression(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XDocument, syntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(declaration, New BoundLiteral(syntax, ConstantValue.Nothing, Nothing)),
                diagnostics)

            Dim childNodeBuilder = ArrayBuilder(Of BoundExpression).GetInstance()

            BindXmlContent(syntax.PrecedingMisc, childNodeBuilder, rootInfoOpt:=Nothing, diagnostics:=diagnostics)
            childNodeBuilder.Add(BindXmlContent(syntax.Root, rootInfoOpt:=Nothing, diagnostics:=diagnostics))
            BindXmlContent(syntax.FollowingMisc, childNodeBuilder, rootInfoOpt:=Nothing, diagnostics:=diagnostics)

            Dim childNodes = childNodeBuilder.ToImmutableAndFree()
            Dim rewriterInfo = BindXmlContainerRewriterInfo(syntax, objectCreation, childNodes, rootInfoOpt:=Nothing, diagnostics:=diagnostics)
            Return New BoundXmlDocument(syntax, declaration, childNodes, rewriterInfo, objectCreation.Type, rewriterInfo.HasErrors)
        End Function

        Private Function BindXmlDeclaration(syntax As XmlDeclarationSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim version = BindXmlDeclarationOption(syntax, syntax.Version, diagnostics)
            Dim encoding = BindXmlDeclarationOption(syntax, syntax.Encoding, diagnostics)
            Dim standalone = BindXmlDeclarationOption(syntax, syntax.Standalone, diagnostics)
            Dim objectCreation = BindObjectCreationExpression(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XDeclaration, syntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(version, encoding, standalone),
                diagnostics)
            Return New BoundXmlDeclaration(syntax, version, encoding, standalone, objectCreation, objectCreation.Type)
        End Function

        Private Function BindXmlDeclarationOption(syntax As XmlDeclarationSyntax, optionSyntax As XmlDeclarationOptionSyntax, diagnostics As BindingDiagnosticBag) As BoundLiteral
            If optionSyntax Is Nothing Then
                Return CreateStringLiteral(syntax, Nothing, compilerGenerated:=True, diagnostics:=diagnostics)
            Else
                Dim value = optionSyntax.Value
                Return CreateStringLiteral(value, GetXmlString(value.TextTokens), compilerGenerated:=False, diagnostics:=diagnostics)
            End If
        End Function

        Private Function BindXmlProcessingInstruction(syntax As XmlProcessingInstructionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim target = CreateStringLiteral(syntax, GetXmlName(syntax.Name), compilerGenerated:=True, diagnostics:=diagnostics)
            Dim data = CreateStringLiteral(syntax, GetXmlString(syntax.TextTokens), compilerGenerated:=True, diagnostics:=diagnostics)
            Dim objectCreation = BindObjectCreationExpression(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XProcessingInstruction, syntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(target, data),
                diagnostics)
            Return New BoundXmlProcessingInstruction(syntax, target, data, objectCreation, objectCreation.Type)
        End Function

        Private Function BindXmlEmptyElement(
                                            syntax As XmlEmptyElementSyntax,
                                            rootInfoOpt As XmlElementRootInfo,
                                            diagnostics As BindingDiagnosticBag) As BoundExpression
            Return BindXmlElement(syntax, syntax.Name, syntax.Attributes, Nothing, rootInfoOpt, diagnostics)
        End Function

        Private Function BindXmlElement(
                                       syntax As XmlElementSyntax,
                                       rootInfoOpt As XmlElementRootInfo,
                                       diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim startTag = syntax.StartTag
            Return BindXmlElement(syntax, startTag.Name, startTag.Attributes, syntax.Content, rootInfoOpt, diagnostics)
        End Function

        Private Function BindXmlElement(
                                       syntax As XmlNodeSyntax,
                                       nameSyntax As XmlNodeSyntax,
                                       attributes As SyntaxList(Of XmlNodeSyntax),
                                       content As SyntaxList(Of XmlNodeSyntax),
                                       rootInfoOpt As XmlElementRootInfo,
                                       diagnostics As BindingDiagnosticBag) As BoundExpression
            If rootInfoOpt Is Nothing Then
                diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)

                ' 'importedNamespaces' is the set of Imports statements that are referenced
                ' within the XmlElement, represented as { prefix, namespace } pairs. The set is
                ' used to ensure the necessary xmlns attributes are added to the resulting XML at
                ' runtime. The set is represented as a flat list rather than a dictionary so that the
                ' order of the xmlns attributes matches the XML generated by the native compiler.
                Dim importedNamespaces = ArrayBuilder(Of KeyValuePair(Of String, String)).GetInstance()
                Dim binder = New XmlRootElementBinder(Me)
                Dim result = binder.BindXmlElement(syntax, nameSyntax, attributes, content, New XmlElementRootInfo(Me, syntax, importedNamespaces), diagnostics)
                importedNamespaces.Free()

                Return result
            Else
                Dim allAttributes As Dictionary(Of XmlName, BoundXmlAttribute) = Nothing
                Dim xmlnsAttributes = ArrayBuilder(Of BoundXmlAttribute).GetInstance()
                Dim otherAttributes = ArrayBuilder(Of XmlNodeSyntax).GetInstance()
                Dim namespaces = BindXmlnsAttributes(attributes, allAttributes, xmlnsAttributes, otherAttributes, rootInfoOpt.ImportedNamespaces, diagnostics)
                Debug.Assert((namespaces Is Nothing) OrElse (namespaces.Count > 0))

                Dim binder = If(namespaces Is Nothing, Me, New XmlElementBinder(Me, namespaces))
                Dim result = binder.BindXmlElementWithoutAddingNamespaces(syntax, nameSyntax, allAttributes, xmlnsAttributes, otherAttributes, content, rootInfoOpt, diagnostics)

                otherAttributes.Free()
                xmlnsAttributes.Free()

                Return result
            End If
        End Function

        Private Function BindXmlElementWithoutAddingNamespaces(
                                                              syntax As XmlNodeSyntax,
                                                              nameSyntax As XmlNodeSyntax,
                                                              <Out()> ByRef allAttributes As Dictionary(Of XmlName, BoundXmlAttribute),
                                                              xmlnsAttributes As ArrayBuilder(Of BoundXmlAttribute),
                                                              otherAttributes As ArrayBuilder(Of XmlNodeSyntax),
                                                              content As SyntaxList(Of XmlNodeSyntax),
                                                              rootInfo As XmlElementRootInfo,
                                                              diagnostics As BindingDiagnosticBag) As BoundExpression
            ' Any expression type is allowed as long as there is an appropriate XElement
            ' constructor for that argument type. In particular, this allows expressions of type
            ' XElement since XElement includes New(other As XElement). This is consistent with
            ' the native compiler, but contradicts the spec (11.23.4: "... the embedded expression
            ' must be a value of a type implicitly convertible to System.Xml.Linq.XName").
            Dim argument As BoundExpression
            If nameSyntax.Kind = SyntaxKind.XmlEmbeddedExpression Then
                argument = BindXmlEmbeddedExpression(DirectCast(nameSyntax, XmlEmbeddedExpressionSyntax), diagnostics:=diagnostics)
            Else
                Dim fromImports = False
                Dim prefix As String = Nothing
                Dim localName As String = Nothing
                Dim [namespace] As String = Nothing
                argument = BindXmlName(DirectCast(nameSyntax, XmlNameSyntax), forElement:=True, rootInfoOpt:=rootInfo, fromImports:=fromImports, prefix:=prefix, localName:=localName, [namespace]:=[namespace], diagnostics:=diagnostics)

                If fromImports Then
                    AddImportedNamespaceIfNecessary(rootInfo.ImportedNamespaces, prefix, [namespace], forElement:=True)
                End If
            End If

            ' Expression* .Semantics::InterpretXmlName( [ ParseTree::Expression* Expr ] [ BCSym.[Alias]** ResolvedPrefix ] )
            ' . . . 
            'If NameExpr.ResultType Is GetFXSymbolProvider().GetObjectType() AndAlso Not m_UsingOptionTypeStrict Then
            '    NameExpr = AllocateExpression( _
            '        BILOP.SX_DIRECTCAST, _
            '        m_XmlSymbols.GetXName(), _
            '        NameExpr, _
            '        NameExpr.Loc)
            'End If

            If argument.Type.IsObjectType AndAlso OptionStrict <> VisualBasic.OptionStrict.On Then
                Dim xnameType = GetWellKnownType(WellKnownType.System_Xml_Linq_XName, syntax, diagnostics)
                argument = ApplyDirectCastConversion(syntax, argument, xnameType, diagnostics:=diagnostics)
            End If

            Dim objectCreation = BindObjectCreationExpression(
                nameSyntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XElement, nameSyntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(argument),
                diagnostics)

            Dim childNodeBuilder = ArrayBuilder(Of BoundExpression).GetInstance()

            For Each xmlnsAttribute In xmlnsAttributes
                childNodeBuilder.Add(xmlnsAttribute)
            Next

            Debug.Assert(otherAttributes.All(Function(a) (a.Kind = SyntaxKind.XmlAttribute) OrElse (a.Kind = SyntaxKind.XmlEmbeddedExpression)))
            BindXmlAttributes(allAttributes, otherAttributes, childNodeBuilder, rootInfo, diagnostics)

            If syntax.Kind <> SyntaxKind.XmlEmptyElement Then
                If content.Count > 0 Then
                    BindXmlContent(content, childNodeBuilder, rootInfo, diagnostics)
                Else
                    ' An XElement with a start and end tag but no content. Include a compiler-
                    ' generated empty string as content for consistency with the native compiler.
                    ' (This also ensures <x></x> is serialized as <x></x> rather than <x/>.)
                    childNodeBuilder.Add(CreateStringLiteral(syntax, String.Empty, compilerGenerated:=True, diagnostics:=diagnostics))
                End If
            End If

            Dim childNodes = childNodeBuilder.ToImmutableAndFree()
            Dim rewriterInfo = BindXmlContainerRewriterInfo(syntax, objectCreation, childNodes, rootInfo, diagnostics)
            Return New BoundXmlElement(syntax, argument, childNodes, rewriterInfo, objectCreation.Type, rewriterInfo.HasErrors)
        End Function

        Private Function BindXmlContainerRewriterInfo(
                                                     syntax As XmlNodeSyntax,
                                                     objectCreation As BoundExpression,
                                                     childNodes As ImmutableArray(Of BoundExpression),
                                                     rootInfoOpt As XmlElementRootInfo,
                                                     diagnostics As BindingDiagnosticBag) As BoundXmlContainerRewriterInfo
            If (childNodes.Length = 0) AndAlso
                ((rootInfoOpt Is Nothing) OrElse (rootInfoOpt.ImportedNamespaces.Count = 0)) Then
                Return New BoundXmlContainerRewriterInfo(objectCreation)
            End If

            Dim placeholder = (New BoundRValuePlaceholder(syntax, objectCreation.Type)).MakeCompilerGenerated()
            Dim sideEffectBuilder = ArrayBuilder(Of BoundExpression).GetInstance()
            Dim addGroup = GetXmlMethodOrPropertyGroup(syntax,
                                                        GetWellKnownType(WellKnownType.System_Xml_Linq_XContainer, syntax, diagnostics),
                                                        StringConstants.XmlAddMethodName,
                                                        placeholder,
                                                        diagnostics)
            ' The following are arguments to
            ' InternalXmlHelper.RemoveNamespaceAttributes(prefixes As String(),
            '     namespaces As XNamespace(), attributes As List(Of XAttribute), arg As XElement) As XElement
            Dim inScopeXmlNamespaces As ImmutableArray(Of KeyValuePair(Of String, String)) = Nothing
            Dim prefixesPlaceholder As BoundRValuePlaceholder = Nothing
            Dim namespacesPlaceholder As BoundRValuePlaceholder = Nothing

            For Each childNode In childNodes
                ' Skip attributes that match imports since those are redundant.
                If (childNode.Kind = BoundKind.XmlAttribute) AndAlso DirectCast(childNode, BoundXmlAttribute).MatchesImport Then
                    Continue For
                End If

                ' Any namespaces from Imports <xmlns:p="..."> that were used within an
                ' XElement require xmlns:p="..." attributes to be added to the root of the XML.
                ' (The xmlns declarations are added to the root to generate the simplest XML.)
                ' If the XML contains embedded expressions, those embedded expressions may
                ' also reference namespaces. For instance, the XML generated at runtime for
                ' <x <%= <p:y/> %>/> should be <x xmlns:p="..."><p:y/></x>. In general, these
                ' cases of embedded expressions are handled by adding xmlns attributes
                ' to the root of the XML within the embedded expression, then using methods
                ' at runtime (when stitching together the XML) to move any attributes to the
                ' containing XML. For instance, for <x <%= e %>/> we generate the following code:
                '
                '   Dim prefixes As New String() From { ... } ' prefixes in use at 'x'
                '   Dim namespaces As New XNamespace() From { ... } ' namespaces in use at 'x'
                '   Dim attribs As New List(Of XAttribute) ' attributes on 'x' plus any removed from 'e'
                '   e = InternalXmlHelper.RemoveNamespaceAttributes(prefixes, namespaces, attribs, e)
                '   x.Add(attribs)
                '   x.Add(e)
                '
                ' In a handful of cases where the namespaces on the embedded expression can
                ' be determined at compile time, the native compiler avoids the cost of calling
                ' RemoveNamespaceAttributes by moving namespaces at compile time. (See
                ' XmlSemantics::TraceLinqExpression.) That is an optimization only and for simplicity
                ' is not included. (If we do add static analysis, we'll need to handle cases where
                ' embedded expressions contain both namespaces that can be determined at compile
                ' time and namespaces that may be included at runtime. For instance, the expression
                ' <p:y> in <x <%= <p:y><%= e %></p:y> %>/> uses "p" but may also use namespaces
                ' in <%= e %>.)

                Dim expr = childNode
                Debug.Assert(expr.Type IsNot Nothing)

                ' If rootInfoOpt Is Nothing, we're binding an XDocument, not an XElement,
                ' in which case it's not possible to remove embedded xmlns attributes.
                If (rootInfoOpt IsNot Nothing) AndAlso
                    (expr.Kind = BoundKind.XmlEmbeddedExpression) AndAlso
                    HasImportedXmlNamespaces AndAlso
                    Not expr.Type.IsIntrinsicOrEnumType() Then

                    If inScopeXmlNamespaces.IsDefault Then
                        Dim builder = ArrayBuilder(Of KeyValuePair(Of String, String)).GetInstance()
                        GetInScopeXmlNamespaces(builder)
                        inScopeXmlNamespaces = builder.ToImmutableAndFree()
                    End If

                    If prefixesPlaceholder Is Nothing Then
                        Dim prefixesType = CreateArrayType(GetSpecialType(SpecialType.System_String, syntax, diagnostics))
                        prefixesPlaceholder = (New BoundRValuePlaceholder(syntax, prefixesType)).MakeCompilerGenerated()

                        Dim namespacesType = CreateArrayType(GetWellKnownType(WellKnownType.System_Xml_Linq_XNamespace, syntax, diagnostics))
                        namespacesPlaceholder = (New BoundRValuePlaceholder(syntax, namespacesType)).MakeCompilerGenerated()
                    End If

                    ' Generate update to child using RemoveNamespaceAttributes.
                    expr = rootInfoOpt.BindRemoveNamespaceAttributesInvocation(expr, prefixesPlaceholder, namespacesPlaceholder, diagnostics)
                End If

                sideEffectBuilder.Add(BindInvocationExpressionIfGroupNotNothing(syntax, addGroup, ImmutableArray.Create(Of BoundExpression)(expr), diagnostics))
            Next

            Dim xmlnsAttributesPlaceholder As BoundRValuePlaceholder = Nothing
            Dim xmlnsAttributes As BoundExpression = Nothing

            ' At the root element, add any xmlns attributes required from Imports,
            ' and any xmlns attributes removed from embedded expressions.
            Dim isRoot = (rootInfoOpt IsNot Nothing) AndAlso (rootInfoOpt.Syntax Is syntax)
            If isRoot Then
                ' Imports declarations are added in the reverse order that the
                ' prefixes were discovered, to match the native compiler.
                Dim importedNamespaces = rootInfoOpt.ImportedNamespaces
                For i = importedNamespaces.Count - 1 To 0 Step -1
                    Dim pair = importedNamespaces(i)
                    Dim attribute = BindXmlnsAttribute(syntax, pair.Key, pair.Value, diagnostics)
                    sideEffectBuilder.Add(BindInvocationExpressionIfGroupNotNothing(syntax, addGroup, ImmutableArray.Create(Of BoundExpression)(attribute), diagnostics))
                Next

                ' Add any xmlns attributes from embedded expressions. (If there were
                ' any embedded expressions, XmlnsAttributesPlaceholder will be set.)
                xmlnsAttributesPlaceholder = rootInfoOpt.XmlnsAttributesPlaceholder
                If xmlnsAttributesPlaceholder IsNot Nothing Then
                    xmlnsAttributes = BindObjectCreationExpression(syntax, xmlnsAttributesPlaceholder.Type, ImmutableArray(Of BoundExpression).Empty, diagnostics).MakeCompilerGenerated()
                    sideEffectBuilder.Add(BindInvocationExpressionIfGroupNotNothing(syntax, addGroup, ImmutableArray.Create(Of BoundExpression)(xmlnsAttributesPlaceholder), diagnostics))
                End If
            End If

            Return New BoundXmlContainerRewriterInfo(
                isRoot,
                placeholder,
                objectCreation,
                xmlnsAttributesPlaceholder:=xmlnsAttributesPlaceholder,
                xmlnsAttributes:=xmlnsAttributes,
                prefixesPlaceholder:=prefixesPlaceholder,
                namespacesPlaceholder:=namespacesPlaceholder,
                importedNamespaces:=If(isRoot, rootInfoOpt.ImportedNamespaces.ToImmutable(), Nothing),
                inScopeXmlNamespaces:=inScopeXmlNamespaces,
                sideEffects:=sideEffectBuilder.ToImmutableAndFree())
        End Function

        Private Function BindRemoveNamespaceAttributesInvocation(
                                                                syntax As VisualBasicSyntaxNode,
                                                                expr As BoundExpression,
                                                                prefixesPlaceholder As BoundRValuePlaceholder,
                                                                namespacesPlaceholder As BoundRValuePlaceholder,
                                                                <Out()> ByRef xmlnsAttributesPlaceholder As BoundRValuePlaceholder,
                                                                <Out()> ByRef removeNamespacesGroup As BoundMethodOrPropertyGroup,
                                                                diagnostics As BindingDiagnosticBag) As BoundExpression

            If xmlnsAttributesPlaceholder Is Nothing Then
                Dim listType = GetWellKnownType(WellKnownType.System_Collections_Generic_List_T, syntax, diagnostics).Construct(
                    GetWellKnownType(WellKnownType.System_Xml_Linq_XAttribute, syntax, diagnostics))
                xmlnsAttributesPlaceholder = (New BoundRValuePlaceholder(syntax, listType)).MakeCompilerGenerated()

                ' Generate method group and arguments for RemoveNamespaceAttributes.
                removeNamespacesGroup = GetXmlMethodOrPropertyGroup(syntax,
                                                                    GetInternalXmlHelperType(syntax, diagnostics),
                                                                    StringConstants.XmlRemoveNamespaceAttributesMethodName,
                                                                    Nothing,
                                                                    diagnostics)
            End If

            ' Invoke RemoveNamespaceAttributes.
            Return BindInvocationExpressionIfGroupNotNothing(expr.Syntax,
                                                             removeNamespacesGroup,
                                                             ImmutableArray.Create(Of BoundExpression)(prefixesPlaceholder, namespacesPlaceholder, xmlnsAttributesPlaceholder, expr),
                                                             diagnostics).MakeCompilerGenerated()
        End Function

        Private Function CreateArrayType(elementType As TypeSymbol) As ArrayTypeSymbol
            Return ArrayTypeSymbol.CreateSZArray(elementType, ImmutableArray(Of CustomModifier).Empty, compilation:=Compilation)
        End Function

        Private Shared Function GetXmlnsXmlName(prefix As String) As XmlName
            Dim localName = If(String.IsNullOrEmpty(prefix), StringConstants.XmlnsPrefix, prefix)
            Dim [namespace] = If(String.IsNullOrEmpty(prefix), StringConstants.DefaultXmlNamespace, StringConstants.XmlnsNamespace)
            Return New XmlName(localName, [namespace])
        End Function

        Private Function BindXmlnsAttribute(
                                           syntax As XmlNodeSyntax,
                                           prefix As String,
                                           namespaceName As String,
                                           diagnostics As BindingDiagnosticBag) As BoundXmlAttribute
            Dim name = BindXmlnsName(syntax, prefix, compilerGenerated:=True, diagnostics:=diagnostics)
            Dim [namespace] = BindXmlNamespace(syntax,
                                               CreateStringLiteral(syntax, namespaceName, compilerGenerated:=True, diagnostics:=diagnostics),
                                               diagnostics)
            Return BindXmlnsAttribute(syntax, name, [namespace], useConstructor:=False, matchesImport:=False, compilerGenerated:=True, hasErrors:=False, diagnostics:=diagnostics)
        End Function

        Private Function BindXmlnsName(
                                      syntax As XmlNodeSyntax,
                                      prefix As String,
                                      compilerGenerated As Boolean,
                                      diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim name = GetXmlnsXmlName(prefix)
            Return BindXmlName(syntax,
                                   CreateStringLiteral(syntax,
                                                       name.LocalName,
                                                       compilerGenerated,
                                                       diagnostics),
                                   CreateStringLiteral(syntax,
                                                       name.XmlNamespace,
                                                       compilerGenerated,
                                                       diagnostics),
                                   diagnostics)
        End Function

        Private Function BindXmlnsAttribute(
                                           syntax As XmlNodeSyntax,
                                           prefix As BoundExpression,
                                           [namespace] As BoundExpression,
                                           useConstructor As Boolean,
                                           matchesImport As Boolean,
                                           compilerGenerated As Boolean,
                                           hasErrors As Boolean,
                                           diagnostics As BindingDiagnosticBag) As BoundXmlAttribute
            Dim objectCreation As BoundExpression
            If useConstructor Then
                objectCreation = BindObjectCreationExpression(syntax,
                                                              GetWellKnownType(WellKnownType.System_Xml_Linq_XAttribute, syntax, diagnostics),
                                                              ImmutableArray.Create(Of BoundExpression)(prefix, [namespace]),
                                                              diagnostics)
            Else
                Dim type = GetInternalXmlHelperType(syntax, diagnostics)
                Dim group = GetXmlMethodOrPropertyGroup(syntax, type, StringConstants.XmlCreateNamespaceAttributeMethodName, Nothing, diagnostics)
                objectCreation = BindInvocationExpressionIfGroupNotNothing(syntax, group, ImmutableArray.Create(Of BoundExpression)(prefix, [namespace]), diagnostics)
            End If

            Dim result = New BoundXmlAttribute(syntax, prefix, [namespace], matchesImport, objectCreation, objectCreation.Type, hasErrors)
            If compilerGenerated Then
                result.SetWasCompilerGenerated()
            End If
            Return result
        End Function

        Private Function BindXmlAttribute(
                                         syntax As XmlAttributeSyntax,
                                         rootInfo As XmlElementRootInfo,
                                         <Out()> ByRef xmlName As XmlName,
                                         diagnostics As BindingDiagnosticBag) As BoundXmlAttribute
            Dim nameSyntax = syntax.Name
            Dim name As BoundExpression

            If nameSyntax.Kind = SyntaxKind.XmlEmbeddedExpression Then
                name = BindXmlEmbeddedExpression(DirectCast(nameSyntax, XmlEmbeddedExpressionSyntax), diagnostics:=diagnostics)
                xmlName = Nothing
            Else
                Dim fromImports = False
                Dim prefix As String = Nothing
                Dim localName As String = Nothing
                Dim [namespace] As String = Nothing
                name = BindXmlName(
                    DirectCast(nameSyntax, XmlNameSyntax),
                    forElement:=False,
                    rootInfoOpt:=rootInfo,
                    fromImports:=fromImports,
                    prefix:=prefix,
                    localName:=localName,
                    [namespace]:=[namespace],
                    diagnostics:=diagnostics)

                If fromImports Then
                    AddImportedNamespaceIfNecessary(rootInfo.ImportedNamespaces, prefix, [namespace], forElement:=False)
                End If

                xmlName = New XmlName(localName, [namespace])
            End If

            Dim value As BoundExpression
            Dim objectCreation As BoundExpression
            Dim valueSyntax = syntax.Value
            Dim matchesImport As Boolean = False

            If valueSyntax.Kind = SyntaxKind.XmlEmbeddedExpression Then
                ' Use InternalXmlHelper.CreateAttribute rather than 'New XAttribute()' for attributes
                ' with embedded expression values since CreateAttribute handles Nothing values.
                value = BindXmlEmbeddedExpression(DirectCast(valueSyntax, XmlEmbeddedExpressionSyntax), diagnostics)
                Dim group = GetXmlMethodOrPropertyGroup(valueSyntax,
                                                        GetInternalXmlHelperType(syntax, diagnostics),
                                                        StringConstants.XmlCreateAttributeMethodName,
                                                        Nothing,
                                                        diagnostics)
                objectCreation = BindInvocationExpressionIfGroupNotNothing(valueSyntax,
                                                                           group,
                                                                           ImmutableArray.Create(Of BoundExpression)(name, value),
                                                                           diagnostics)
            Else
                Dim str = GetXmlString(DirectCast(valueSyntax, XmlStringSyntax).TextTokens)

                ' Mark if this attribute is an xmlns declaration that matches an Imports,
                ' since xmlns declarations from Imports will be added directly at the
                ' XmlElement root, and this attribute can be dropped then.
                matchesImport = (nameSyntax.Kind = SyntaxKind.XmlName) AndAlso MatchesXmlnsImport(DirectCast(nameSyntax, XmlNameSyntax), str)

                value = CreateStringLiteral(valueSyntax, str, compilerGenerated:=False, diagnostics:=diagnostics)
                objectCreation = BindObjectCreationExpression(nameSyntax,
                                                              GetWellKnownType(WellKnownType.System_Xml_Linq_XAttribute, syntax, diagnostics),
                                                              ImmutableArray.Create(Of BoundExpression)(name, value),
                                                              diagnostics)
            End If

            Return New BoundXmlAttribute(syntax, name, value, matchesImport, objectCreation, objectCreation.Type)
        End Function

        ''' <summary>
        ''' Returns True if the xmlns { prefix, namespace } pair matches
        ''' an Imports declaration and there aren't any xmlns declarations
        ''' for the same prefix on any outer XElement scopes.
        ''' </summary>
        Private Function MatchesXmlnsImport(prefix As String, [namespace] As String) As Boolean
            Dim fromImports As Boolean = False
            Dim otherNamespace As String = Nothing
            Return LookupXmlNamespace(prefix, False, otherNamespace, fromImports) AndAlso
                fromImports AndAlso
                ([namespace] = otherNamespace)
        End Function

        Private Function MatchesXmlnsImport(name As XmlNameSyntax, value As String) As Boolean
            Dim prefix As String = Nothing
            TryGetXmlnsPrefix(name, prefix, BindingDiagnosticBag.Discarded)

            If prefix Is Nothing Then
                Return False
            End If

            ' Match using containing Binder since this Binder
            ' contains this xmlns attribute in XmlNamespaces.
            Return ContainingBinder.MatchesXmlnsImport(prefix, value)
        End Function

        ''' <summary>
        ''' Bind the expression within the XmlEmbeddedExpressionSyntax,
        ''' and wrap in a BoundXmlEmbeddedExpression.
        ''' </summary>
        Private Function BindXmlEmbeddedExpression(syntax As XmlEmbeddedExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim binder = New XmlEmbeddedExpressionBinder(Me)
            Dim expr = binder.BindRValue(syntax.Expression, diagnostics)
            Debug.Assert(expr IsNot Nothing)
            Debug.Assert(expr.Type IsNot Nothing)
            Return New BoundXmlEmbeddedExpression(syntax, expr, expr.Type)
        End Function

        Private Sub BindXmlAttributes(
                                      <Out()> ByRef allAttributes As Dictionary(Of XmlName, BoundXmlAttribute),
                                     attributes As ArrayBuilder(Of XmlNodeSyntax),
                                     childNodeBuilder As ArrayBuilder(Of BoundExpression),
                                     rootInfo As XmlElementRootInfo,
                                     diagnostics As BindingDiagnosticBag)
            For Each childSyntax In attributes
                If childSyntax.Kind = SyntaxKind.XmlAttribute Then
                    Dim attributeSyntax = DirectCast(childSyntax, XmlAttributeSyntax)
                    Dim name As XmlName = Nothing
                    Dim attribute = BindXmlAttribute(attributeSyntax, rootInfo, name, diagnostics)
                    childNodeBuilder.Add(attribute)

                    ' Name may be Nothing for embedded expressions.
                    ' Otherwise, check for duplicates.
                    If name.LocalName IsNot Nothing Then
                        AddXmlAttributeIfNotDuplicate(attributeSyntax.Name, name, attribute, allAttributes, diagnostics)
                    End If
                Else
                    Dim child = BindXmlContent(childSyntax, rootInfo, diagnostics)
                    childNodeBuilder.Add(child)
                End If
            Next
        End Sub

        Private Structure XmlName
            Public Sub New(localName As String, [namespace] As String)
                Me.LocalName = localName
                Me.XmlNamespace = [namespace]
            End Sub

            Public ReadOnly LocalName As String
            Public ReadOnly XmlNamespace As String
        End Structure

        Private NotInheritable Class XmlNameComparer
            Implements IEqualityComparer(Of XmlName)

            Public Shared ReadOnly Instance As New XmlNameComparer()

            Private Function IEqualityComparer_Equals(x As XmlName, y As XmlName) As Boolean Implements IEqualityComparer(Of XmlName).Equals
                Return String.Equals(x.LocalName, y.LocalName, StringComparison.Ordinal) AndAlso String.Equals(x.XmlNamespace, y.XmlNamespace, StringComparison.Ordinal)
            End Function

            Private Function IEqualityComparer_GetHashCode(obj As XmlName) As Integer Implements IEqualityComparer(Of XmlName).GetHashCode
                Dim result = obj.LocalName.GetHashCode()
                If obj.XmlNamespace IsNot Nothing Then
                    result = Hash.Combine(result, obj.XmlNamespace.GetHashCode())
                End If
                Return result
            End Function
        End Class

        Private Sub BindXmlContent(content As SyntaxList(Of XmlNodeSyntax), childNodeBuilder As ArrayBuilder(Of BoundExpression), rootInfoOpt As XmlElementRootInfo, diagnostics As BindingDiagnosticBag)
            For Each childSyntax In content
                childNodeBuilder.Add(BindXmlContent(childSyntax, rootInfoOpt, diagnostics))
            Next
        End Sub

        Private Function BindXmlContent(syntax As XmlNodeSyntax, rootInfoOpt As XmlElementRootInfo, diagnostics As BindingDiagnosticBag) As BoundExpression
            Select Case syntax.Kind
                Case SyntaxKind.XmlProcessingInstruction
                    Return BindXmlProcessingInstruction(DirectCast(syntax, XmlProcessingInstructionSyntax), diagnostics)

                Case SyntaxKind.XmlComment
                    Return BindXmlComment(DirectCast(syntax, XmlCommentSyntax), rootInfoOpt, diagnostics)

                Case SyntaxKind.XmlElement
                    Return BindXmlElement(DirectCast(syntax, XmlElementSyntax), rootInfoOpt, diagnostics)

                Case SyntaxKind.XmlEmptyElement
                    Return BindXmlEmptyElement(DirectCast(syntax, XmlEmptyElementSyntax), rootInfoOpt, diagnostics)

                Case SyntaxKind.XmlEmbeddedExpression
                    Return BindXmlEmbeddedExpression(DirectCast(syntax, XmlEmbeddedExpressionSyntax), diagnostics)

                Case SyntaxKind.XmlCDataSection
                    Return BindXmlCData(DirectCast(syntax, XmlCDataSectionSyntax), rootInfoOpt, diagnostics)

                Case SyntaxKind.XmlText
                    Return BindXmlText(DirectCast(syntax, XmlTextSyntax), diagnostics)

                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(syntax.Kind)
            End Select
        End Function

        Private Function BindXmlAttributeAccess(syntax As XmlMemberAccessExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)

            Dim receiver = BindXmlMemberAccessReceiver(syntax, diagnostics)
            Dim nameSyntax = If(syntax.Name.Kind = SyntaxKind.XmlName,
                                DirectCast(syntax.Name, XmlNameSyntax),
                                DirectCast(syntax.Name, XmlBracketedNameSyntax).Name)
            Dim name = BindXmlName(nameSyntax, forElement:=False, diagnostics:=diagnostics)
            Dim receiverType = receiver.Type
            Debug.Assert(receiverType IsNot Nothing)
            Dim memberAccess As BoundExpression = Nothing

            If receiverType.SpecialType = SpecialType.System_Object Then
                ReportDiagnostic(diagnostics, syntax, ERRID.ERR_NoXmlAxesLateBinding)
            ElseIf Not receiverType.IsErrorType() Then
                Dim group As BoundMethodOrPropertyGroup = Nothing
                ' Determine the appropriate overload, allowing
                ' XElement or IEnumerable(Of XElement) argument.
                Dim xmlType = GetWellKnownType(WellKnownType.System_Xml_Linq_XElement, syntax, diagnostics)
                Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
                If receiverType.IsOrDerivedFrom(xmlType, useSiteInfo) OrElse receiverType.IsCompatibleWithGenericIEnumerableOfType(xmlType, useSiteInfo) Then
                    group = GetXmlMethodOrPropertyGroup(syntax,
                                                            GetInternalXmlHelperType(syntax, diagnostics),
                                                            StringConstants.XmlAttributeValueMethodName,
                                                            Nothing,
                                                            diagnostics)
                End If

                diagnostics.Add(syntax, useSiteInfo)

                If group IsNot Nothing Then
                    memberAccess = BindInvocationExpressionIfGroupNotNothing(syntax, group, ImmutableArray.Create(Of BoundExpression)(receiver, name), diagnostics)
                    memberAccess = MakeValue(memberAccess, diagnostics)
                Else
                    ReportDiagnostic(diagnostics, syntax, ERRID.ERR_TypeDisallowsAttributes, receiverType)
                End If
            End If

            If memberAccess Is Nothing Then
                memberAccess = BadExpression(syntax, ImmutableArray.Create(receiver, name), Compilation.GetSpecialType(SpecialType.System_String))
            End If

            Return New BoundXmlMemberAccess(syntax, memberAccess, memberAccess.Type)
        End Function

        Private Function BindXmlElementAccess(syntax As XmlMemberAccessExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            Return BindXmlElementAccess(syntax, StringConstants.XmlElementsMethodName, ERRID.ERR_TypeDisallowsElements, diagnostics)
        End Function

        Private Function BindXmlDescendantAccess(syntax As XmlMemberAccessExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            Return BindXmlElementAccess(syntax, StringConstants.XmlDescendantsMethodName, ERRID.ERR_TypeDisallowsDescendants, diagnostics)
        End Function

        Private Function BindXmlElementAccess(syntax As XmlMemberAccessExpressionSyntax, memberName As String, typeDisallowsError As ERRID, diagnostics As BindingDiagnosticBag) As BoundExpression
            diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)

            Dim receiver = BindXmlMemberAccessReceiver(syntax, diagnostics)
            Dim name = BindXmlName(DirectCast(syntax.Name, XmlBracketedNameSyntax).Name, forElement:=True, diagnostics:=diagnostics)
            Dim receiverType = receiver.Type
            Debug.Assert(receiverType IsNot Nothing)
            Dim memberAccess As BoundExpression = Nothing

            If receiverType.SpecialType = SpecialType.System_Object Then
                ReportDiagnostic(diagnostics, syntax, ERRID.ERR_NoXmlAxesLateBinding)
            ElseIf Not receiverType.IsErrorType() Then
                Dim group As BoundMethodOrPropertyGroup = Nothing
                Dim arguments As ImmutableArray(Of BoundExpression) = Nothing
                ' Determine the appropriate overload, allowing
                ' XContainer or IEnumerable(Of XContainer) argument.
                Dim xmlType = GetWellKnownType(WellKnownType.System_Xml_Linq_XContainer, syntax, diagnostics)
                Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)

                If receiverType.IsOrDerivedFrom(xmlType, useSiteInfo) Then
                    group = GetXmlMethodOrPropertyGroup(syntax,
                                                            xmlType,
                                                            memberName,
                                                            receiver,
                                                            diagnostics)
                    arguments = ImmutableArray.Create(Of BoundExpression)(name)
                ElseIf receiverType.IsCompatibleWithGenericIEnumerableOfType(xmlType, useSiteInfo) Then
                    group = GetXmlMethodOrPropertyGroup(syntax,
                                                            GetWellKnownType(WellKnownType.System_Xml_Linq_Extensions, syntax, diagnostics),
                                                            memberName,
                                                            Nothing,
                                                            diagnostics)
                    arguments = ImmutableArray.Create(Of BoundExpression)(receiver, name)
                End If

                diagnostics.Add(syntax, useSiteInfo)

                If group IsNot Nothing Then
                    memberAccess = BindInvocationExpressionIfGroupNotNothing(syntax, group, arguments, diagnostics)
                    memberAccess = MakeRValue(memberAccess, diagnostics)
                Else
                    ReportDiagnostic(diagnostics, syntax, typeDisallowsError, receiverType)
                End If
            End If

            If memberAccess Is Nothing Then
                memberAccess = BadExpression(syntax, ImmutableArray.Create(receiver, name), ErrorTypeSymbol.UnknownResultType)
            End If

            Return New BoundXmlMemberAccess(syntax, memberAccess, memberAccess.Type)
        End Function

        Private Function BindXmlMemberAccessReceiver(syntax As XmlMemberAccessExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            If syntax.Base Is Nothing Then
                Dim receiver As BoundExpression

                Dim conditionalAccess As ConditionalAccessExpressionSyntax = syntax.GetCorrespondingConditionalAccessExpression()

                If conditionalAccess IsNot Nothing Then
                    receiver = GetConditionalAccessReceiver(conditionalAccess)
                Else
                    receiver = TryBindOmittedLeftForXmlMemberAccess(syntax, diagnostics, Me)
                End If

                If receiver Is Nothing Then
                    Return ReportDiagnosticAndProduceBadExpression(diagnostics, syntax, ERRID.ERR_BadWithRef)
                End If
                Return receiver
            Else
                Dim receiver = BindValue(syntax.Base, diagnostics)
                Debug.Assert(receiver IsNot Nothing)
                Return AdjustReceiverValue(receiver, syntax, diagnostics)
            End If
        End Function

        Private Function BindXmlName(
                                    syntax As XmlNameSyntax,
                                    forElement As Boolean,
                                    diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim fromImports = False
            Dim prefix As String = Nothing
            Dim localName As String = Nothing
            Dim [namespace] As String = Nothing
            Return BindXmlName(syntax, forElement, Nothing, fromImports, prefix, localName, [namespace], diagnostics)
        End Function

        Private Function BindXmlName(
                                    syntax As XmlNameSyntax,
                                    forElement As Boolean,
                                    rootInfoOpt As XmlElementRootInfo,
                                    <Out()> ByRef fromImports As Boolean,
                                    <Out()> ByRef prefix As String,
                                    <Out()> ByRef localName As String,
                                    <Out()> ByRef [namespace] As String,
                                    diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim prefixSyntax = syntax.Prefix
            Dim namespaceExpr As BoundLiteral

            fromImports = False
            localName = GetXmlName(syntax.LocalName)
            [namespace] = Nothing

            If prefixSyntax IsNot Nothing Then
                Dim prefixToken = prefixSyntax.Name
                prefix = GetXmlName(prefixToken)

                If forElement AndAlso (prefix = StringConstants.XmlnsPrefix) Then
                    ' "Element names cannot use the 'xmlns' prefix."
                    ReportDiagnostic(diagnostics, prefixToken, ERRID.ERR_IllegalXmlnsPrefix)
                    Return BadExpression(syntax, Compilation.GetSpecialType(SpecialType.System_String))
                End If

                If Not LookupXmlNamespace(prefix, False, [namespace], fromImports) Then
                    Return ReportXmlNamespacePrefixNotDefined(syntax, prefixSyntax.Name, prefix, compilerGenerated:=False, diagnostics:=diagnostics)
                End If

                namespaceExpr = CreateStringLiteral(prefixSyntax, [namespace], compilerGenerated:=False, diagnostics:=diagnostics)
            Else
                prefix = StringConstants.DefaultXmlnsPrefix

                If forElement Then
                    Dim found = LookupXmlNamespace(prefix, False, [namespace], fromImports)
                    Debug.Assert(found)
                Else
                    [namespace] = StringConstants.DefaultXmlNamespace
                End If

                namespaceExpr = CreateStringLiteral(syntax, [namespace], compilerGenerated:=True, diagnostics:=diagnostics)
            End If

            ' LocalName is marked as CompilerGenerated to avoid confusing the semantic model
            ' with two BoundNodes (LocalName and entire XName) for the same syntax node.
            Dim localNameExpr = CreateStringLiteral(syntax, localName, compilerGenerated:=True, diagnostics:=diagnostics)
            Return BindXmlName(syntax, localNameExpr, namespaceExpr, diagnostics)
        End Function

        Private Shared Sub AddImportedNamespaceIfNecessary(
                                                          importedNamespaces As ArrayBuilder(Of KeyValuePair(Of String, String)),
                                                          prefix As String,
                                                          [namespace] As String,
                                                          forElement As Boolean)
            Debug.Assert(prefix IsNot Nothing)
            Debug.Assert([namespace] IsNot Nothing)

            ' If the namespace is the default, create an xmlns="" attribute
            ' if the reference was for an XmlElement name. Otherwise,
            ' avoid adding an attribute for the default namespace.
            If [namespace] = StringConstants.DefaultXmlNamespace Then
                If Not forElement OrElse (prefix = StringConstants.DefaultXmlnsPrefix) Then
                    Return
                End If
                prefix = StringConstants.DefaultXmlnsPrefix
            End If

            For Each pair In importedNamespaces
                If pair.Key = prefix Then
                    Return
                End If
            Next

            importedNamespaces.Add(New KeyValuePair(Of String, String)(prefix, [namespace]))
        End Sub

        Private Function BindXmlName(syntax As VisualBasicSyntaxNode, localName As BoundExpression, [namespace] As BoundExpression, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim group = GetXmlMethodOrPropertyGroup(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XName, syntax, diagnostics),
                StringConstants.XmlGetMethodName,
                Nothing,
                diagnostics)
            Dim objectCreation = BindInvocationExpressionIfGroupNotNothing(syntax, group, ImmutableArray.Create(Of BoundExpression)(localName, [namespace]), diagnostics)
            Return New BoundXmlName(syntax, [namespace], localName, objectCreation, objectCreation.Type)
        End Function

        Private Function BindGetXmlNamespace(syntax As GetXmlNamespaceExpressionSyntax, diagnostics As BindingDiagnosticBag) As BoundExpression
            diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)

            Dim nameSyntax = syntax.Name
            Dim [namespace] As String = Nothing
            Dim fromImports = False
            Dim expr As BoundExpression

            If nameSyntax IsNot Nothing Then
                Dim prefixToken = nameSyntax.Name
                Dim prefix = GetXmlName(prefixToken)
                If LookupXmlNamespace(prefix, False, [namespace], fromImports) Then
                    expr = CreateStringLiteral(nameSyntax, [namespace], compilerGenerated:=False, diagnostics:=diagnostics)
                Else
                    expr = ReportXmlNamespacePrefixNotDefined(nameSyntax, prefixToken, prefix, compilerGenerated:=False, diagnostics:=diagnostics)
                End If
            Else
                Dim found = LookupXmlNamespace(StringConstants.DefaultXmlnsPrefix, False, [namespace], fromImports)
                Debug.Assert(found)
                expr = CreateStringLiteral(syntax, [namespace], compilerGenerated:=True, diagnostics:=diagnostics)
            End If

            Return BindXmlNamespace(syntax, expr, diagnostics)
        End Function

        Private Function BindXmlNamespace(syntax As VisualBasicSyntaxNode, [namespace] As BoundExpression, diagnostics As BindingDiagnosticBag) As BoundExpression
            Dim group = GetXmlMethodOrPropertyGroup(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XNamespace, syntax, diagnostics),
                StringConstants.XmlGetMethodName,
                Nothing,
                diagnostics)
            Dim objectCreation = BindInvocationExpressionIfGroupNotNothing(syntax, group, ImmutableArray.Create(Of BoundExpression)([namespace]), diagnostics)
            Return New BoundXmlNamespace(syntax, [namespace], objectCreation, objectCreation.Type)
        End Function

        Private Function ReportXmlNamespacePrefixNotDefined(syntax As VisualBasicSyntaxNode, prefixToken As SyntaxToken, prefix As String, compilerGenerated As Boolean, diagnostics As BindingDiagnosticBag) As BoundBadExpression
            Debug.Assert(prefix IsNot Nothing)
            Debug.Assert(prefix = GetXmlName(prefixToken))
            ' "XML namespace prefix '{0}' is not defined."
            ReportDiagnostic(diagnostics, prefixToken, ERRID.ERR_UndefinedXmlPrefix, prefix)
            Dim result = BadExpression(syntax, Compilation.GetSpecialType(SpecialType.System_String))
            If compilerGenerated Then
                result.SetWasCompilerGenerated()
            End If
            Return result
        End Function

        Private Function BindXmlCData(syntax As XmlCDataSectionSyntax, rootInfoOpt As XmlElementRootInfo, diagnostics As BindingDiagnosticBag) As BoundExpression
            If rootInfoOpt Is Nothing Then
                diagnostics = CheckXmlFeaturesAllowed(syntax, diagnostics)
            End If

            Dim value = CreateStringLiteral(syntax, GetXmlString(syntax.TextTokens), compilerGenerated:=True, diagnostics:=diagnostics)
            Dim objectCreation = BindObjectCreationExpression(
                syntax,
                GetWellKnownType(WellKnownType.System_Xml_Linq_XCData, syntax, diagnostics),
                ImmutableArray.Create(Of BoundExpression)(value),
                diagnostics)
            Return New BoundXmlCData(syntax, value, objectCreation, objectCreation.Type)
        End Function

        Private Function BindXmlText(syntax As XmlTextSyntax, diagnostics As BindingDiagnosticBag) As BoundLiteral
            Return CreateStringLiteral(syntax, GetXmlString(syntax.TextTokens), compilerGenerated:=False, diagnostics:=diagnostics)
        End Function

        Friend Shared Function GetXmlString(tokens As SyntaxTokenList) As String
            Dim n = tokens.Count
            If n = 0 Then
                Return String.Empty
            ElseIf n = 1 Then
                Return GetXmlString(tokens(0))
            Else
                Dim pooledBuilder = PooledStringBuilder.GetInstance()
                Dim builder = pooledBuilder.Builder
                For Each token In tokens
                    builder.Append(GetXmlString(token))
                Next
                Dim result = builder.ToString()
                pooledBuilder.Free()
                Return result
            End If
        End Function

        Private Shared Function GetXmlString(token As SyntaxToken) As String
            Select Case token.Kind
                Case SyntaxKind.XmlTextLiteralToken, SyntaxKind.XmlEntityLiteralToken
                    Return token.ValueText
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(token.Kind)
            End Select
        End Function

        Private Function GetXmlMethodOrPropertyGroup(syntax As VisualBasicSyntaxNode, type As NamedTypeSymbol, memberName As String, receiverOpt As BoundExpression, diagnostics As BindingDiagnosticBag) As BoundMethodOrPropertyGroup
            If type.IsErrorType() Then
                Return Nothing
            End If

            Debug.Assert((receiverOpt Is Nothing) OrElse
                         receiverOpt.Type.IsErrorType() OrElse
                         receiverOpt.Type.IsOrDerivedFrom(type, CompoundUseSiteInfo(Of AssemblySymbol).Discarded))

            Dim group As BoundMethodOrPropertyGroup = Nothing
            Dim result = LookupResult.GetInstance()

            ' Match the lookup of XML members in the native compiler: consider members
            ' on this type only, not base types, and ignore extension methods or properties
            ' from the current scope. (Extension methods and properties will be included,
            ' as shared members, if the members are defined on 'type' however.)
            Dim useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics)
            LookupMember(result,
                         type,
                         memberName,
                         arity:=0,
                         options:=LookupOptions.AllMethodsOfAnyArity Or LookupOptions.NoBaseClassLookup Or LookupOptions.IgnoreExtensionMethods,
                         useSiteInfo:=useSiteInfo)

            diagnostics.Add(syntax, useSiteInfo)

            If result.IsGood Then
                Debug.Assert(result.Symbols.Count > 0)
                Dim symbol0 = result.Symbols(0)
                Select Case result.Symbols(0).Kind
                    Case SymbolKind.Method
                        group = New BoundMethodGroup(syntax,
                                                    Nothing,
                                                    result.Symbols.ToDowncastedImmutable(Of MethodSymbol),
                                                    result.Kind,
                                                    receiverOpt,
                                                    QualificationKind.QualifiedViaValue)
                    Case SymbolKind.Property
                        group = New BoundPropertyGroup(syntax,
                                                    result.Symbols.ToDowncastedImmutable(Of PropertySymbol),
                                                    result.Kind,
                                                    receiverOpt,
                                                    QualificationKind.QualifiedViaValue)
                End Select
            End If

            If group Is Nothing Then
                ReportDiagnostic(diagnostics,
                                 syntax,
                                 If(result.HasDiagnostic,
                                    result.Diagnostic,
                                    ErrorFactory.ErrorInfo(ERRID.ERR_NameNotMember2, memberName, type)))
            End If

            result.Free()
            Return group
        End Function

        ''' <summary>
        ''' If the method or property group is not Nothing, bind as an invocation expression.
        ''' Otherwise return a BoundBadExpression containing the arguments.
        ''' </summary>
        Private Function BindInvocationExpressionIfGroupNotNothing(syntax As SyntaxNode, groupOpt As BoundMethodOrPropertyGroup, arguments As ImmutableArray(Of BoundExpression), diagnostics As BindingDiagnosticBag) As BoundExpression
            If groupOpt Is Nothing Then
                Return BadExpression(syntax, arguments, ErrorTypeSymbol.UnknownResultType)
            Else
                Return BindInvocationExpression(syntax,
                                                syntax,
                                                TypeCharacter.None,
                                                groupOpt,
                                                arguments,
                                                argumentNames:=Nothing,
                                                diagnostics:=diagnostics,
                                                callerInfoOpt:=Nothing)
            End If
        End Function

        ''' <summary>
        ''' Check if XML features are allowed. If not, report an error and return a
        ''' separate DiagnosticBag that can be used for binding sub-expressions.
        ''' </summary>
        Private Function CheckXmlFeaturesAllowed(syntax As VisualBasicSyntaxNode, diagnostics As BindingDiagnosticBag) As BindingDiagnosticBag
            ' Check if XObject is available, which matches the native compiler.
            Dim type = Compilation.GetWellKnownType(WellKnownType.System_Xml_Linq_XObject)
            If type.IsErrorType() Then
                ' "XML literals and XML axis properties are not available. Add references to System.Xml, System.Xml.Linq, and System.Core."
                ReportDiagnostic(diagnostics, syntax, ERRID.ERR_XmlFeaturesNotAvailable)
                ' DiagnosticBag does not need to be created from the pool
                ' since this is an error recovery scenario only.
                Return BindingDiagnosticBag.Discarded
            Else
                Return diagnostics
            End If
        End Function

        Private Function CreateStringLiteral(
                                            syntax As SyntaxNode,
                                            str As String,
                                            compilerGenerated As Boolean,
                                            diagnostics As BindingDiagnosticBag,
                                            Optional hasErrors As Boolean = False) As BoundLiteral
            Debug.Assert(syntax IsNot Nothing)
            Dim result = New BoundLiteral(syntax, ConstantValue.Create(str), GetSpecialType(SpecialType.System_String, syntax, diagnostics), hasErrors:=hasErrors)
            If compilerGenerated Then
                result.SetWasCompilerGenerated()
            End If
            Return result
        End Function

        ''' <summary>
        ''' Bind any xmlns declaration attributes and return the bound nodes plus a Dictionary
        ''' of { prefix, namespace } pairs that will be used for namespace lookup at and below
        ''' the containing XmlElement. Any xmlns declarations that are redundant with Imports
        ''' in scope (same prefix and namespace) are dropped, and instead, an entry is added
        ''' to the 'importedNamespaces' collection. When the root XmlElement is generated,
        ''' xmlns attributes will be added for all entries in importedNamespaces. Any attributes
        ''' other than xmlns are added to the 'otherAttributes' collection for binding by the caller.
        ''' </summary>
        Private Function BindXmlnsAttributes(
                                      attributes As SyntaxList(Of XmlNodeSyntax),
                                      <Out()> ByRef allAttributes As Dictionary(Of XmlName, BoundXmlAttribute),
                                      xmlnsAttributes As ArrayBuilder(Of BoundXmlAttribute),
                                      otherAttributes As ArrayBuilder(Of XmlNodeSyntax),
                                      importedNamespaces As ArrayBuilder(Of KeyValuePair(Of String, String)),
                                      diagnostics As BindingDiagnosticBag) As Dictionary(Of String, String)
            Debug.Assert(xmlnsAttributes.Count = 0)
            Debug.Assert(otherAttributes.Count = 0)

            Dim namespaces As Dictionary(Of String, String) = Nothing

            For Each attribute In attributes
                Dim syntax = TryCast(attribute, XmlAttributeSyntax)

                Dim prefix As String = Nothing
                Dim namespaceName As String = Nothing
                Dim [namespace] As BoundExpression = Nothing
                Dim hasErrors As Boolean = False

                If (syntax IsNot Nothing) AndAlso
                    TryGetXmlnsAttribute(syntax, prefix, namespaceName, [namespace], hasErrors, fromImport:=False, diagnostics:=diagnostics) Then
                    Debug.Assert(prefix IsNot Nothing)
                    Debug.Assert(hasErrors OrElse (namespaceName IsNot Nothing))
                    Debug.Assert(hasErrors OrElse ([namespace] IsNot Nothing))

                    Dim matchesImport = Not hasErrors AndAlso MatchesXmlnsImport(prefix, namespaceName)

                    ' Generate a BoundXmlAttribute, even if we'll drop the
                    ' attribute, since the semantic model will need one.
                    Dim xmlnsAttribute = BindXmlnsAttribute(
                        syntax,
                        BindXmlnsName(syntax.Name, prefix, compilerGenerated:=False, diagnostics:=diagnostics),
                        [namespace],
                        useConstructor:=True,
                        matchesImport:=matchesImport,
                        compilerGenerated:=False,
                        hasErrors:=hasErrors,
                        diagnostics:=diagnostics)
                    xmlnsAttributes.Add(xmlnsAttribute)

                    If Not hasErrors Then
                        If matchesImport Then
                            AddImportedNamespaceIfNecessary(importedNamespaces, prefix, namespaceName, forElement:=False)
                        End If

                        ' Check for duplicates.
                        If AddXmlAttributeIfNotDuplicate(syntax.Name, GetXmlnsXmlName(prefix), xmlnsAttribute, allAttributes, diagnostics) Then
                            If namespaces Is Nothing Then
                                namespaces = New Dictionary(Of String, String)
                            End If

                            namespaces.Add(prefix, namespaceName)
                        End If
                    End If
                Else
                    ' Not an xmlns attribute. Defer binding to the caller, to
                    ' allow the caller to include any namespaces found here
                    ' in the lookup of the prefix on this and other attributes.
                    otherAttributes.Add(attribute)
                End If
            Next

            Return namespaces
        End Function

        Private Shared Function AddXmlAttributeIfNotDuplicate(
                                                      syntax As XmlNodeSyntax,
                                                      name As XmlName,
                                                      attribute As BoundXmlAttribute,
                                                      <Out()> ByRef allAttributes As Dictionary(Of XmlName, BoundXmlAttribute),
                                                      diagnostics As BindingDiagnosticBag) As Boolean
            If allAttributes Is Nothing Then
                allAttributes = New Dictionary(Of XmlName, BoundXmlAttribute)(XmlNameComparer.Instance)
            End If

            If allAttributes.ContainsKey(name) Then
                ' "Duplicate XML attribute '{0}'."
                ReportDiagnostic(diagnostics, syntax, ERRID.ERR_DuplicateXmlAttribute, syntax.ToString())
                Return False
            Else
                allAttributes.Add(name, attribute)
                Return True
            End If
        End Function

        ''' <summary>
        ''' If the attribute represents an xmlns declaration, populate 'prefix' and 'namespace',
        ''' and generate diagnostics and set hasErrors if there are errors. Returns True if this
        ''' is an xmlns declaration, even if there are errors. Unless this attribute is from an
        ''' Imports statement, generate the BoundExpression for the namespace as well.
        ''' (For Imports, binding is skipped, since a BoundNode is not needed, and in the
        ''' invalid case of "xmlns:p=&lt;%= expr %&gt;", expr may result in a cycle.
        ''' </summary>
        Private Function TryGetXmlnsAttribute(
                                             syntax As XmlAttributeSyntax,
                                             <Out()> ByRef prefix As String,
                                             <Out()> ByRef namespaceName As String,
                                             <Out()> ByRef [namespace] As BoundExpression,
                                             <Out()> ByRef hasErrors As Boolean,
                                             fromImport As Boolean,
                                             diagnostics As BindingDiagnosticBag) As Boolean
            prefix = Nothing
            namespaceName = Nothing
            [namespace] = Nothing
            hasErrors = False

            ' If the name is an embedded expression, it should not be treated as an
            ' "xmlns" declaration at compile-time, regardless of the expression value.
            If syntax.Name.Kind = SyntaxKind.XmlEmbeddedExpression Then
                Return False
            End If

            Debug.Assert(syntax.Name.Kind = SyntaxKind.XmlName)
            Dim nameSyntax = DirectCast(syntax.Name, XmlNameSyntax)

            If Not TryGetXmlnsPrefix(nameSyntax, prefix, diagnostics) Then
                Return False
            End If

            Debug.Assert(prefix IsNot Nothing)

            Dim valueSyntax = syntax.Value
            If valueSyntax.Kind <> SyntaxKind.XmlString Then
                Debug.Assert(valueSyntax.Kind = SyntaxKind.XmlEmbeddedExpression)
                ' "An embedded expression cannot be used here."
                ReportDiagnostic(diagnostics, valueSyntax, ERRID.ERR_EmbeddedExpression)
                hasErrors = True

                ' Avoid binding Imports since that might result in a cycle.
                If Not fromImport Then
                    [namespace] = BindXmlEmbeddedExpression(DirectCast(valueSyntax, XmlEmbeddedExpressionSyntax), diagnostics)
                End If

            Else
                namespaceName = GetXmlString(DirectCast(valueSyntax, XmlStringSyntax).TextTokens)
                Debug.Assert(namespaceName IsNot Nothing)

                If (prefix = StringConstants.XmlnsPrefix) OrElse
                    ((prefix = StringConstants.XmlPrefix) AndAlso (namespaceName <> StringConstants.XmlNamespace)) Then
                    ' "XML namespace prefix '{0}' is reserved for use by XML and the namespace URI cannot be changed."
                    ReportDiagnostic(diagnostics, nameSyntax.LocalName, ERRID.ERR_ReservedXmlPrefix, prefix)
                    hasErrors = True

                ElseIf Not fromImport AndAlso
                    String.IsNullOrEmpty(namespaceName) AndAlso
                    Not String.IsNullOrEmpty(prefix) Then
                    ' "Namespace declaration with prefix cannot have an empty value inside an XML literal."
                    ReportDiagnostic(diagnostics, nameSyntax.LocalName, ERRID.ERR_IllegalDefaultNamespace)
                    hasErrors = True

                ElseIf RedefinesReservedXmlNamespace(syntax.Value, prefix, StringConstants.XmlnsPrefix, namespaceName, StringConstants.XmlnsNamespace, diagnostics) OrElse
                    RedefinesReservedXmlNamespace(syntax.Value, prefix, StringConstants.XmlPrefix, namespaceName, StringConstants.XmlNamespace, diagnostics) Then
                    hasErrors = True

                End If

                If Not fromImport Then
                    [namespace] = CreateStringLiteral(
                        valueSyntax,
                        namespaceName,
                        compilerGenerated:=False,
                        diagnostics:=diagnostics)
                End If
            End If

            Return True
        End Function

        Private Shared Function RedefinesReservedXmlNamespace(syntax As VisualBasicSyntaxNode, prefix As String, reservedPrefix As String, [namespace] As String, reservedNamespace As String, diagnostics As BindingDiagnosticBag) As Boolean
            If ([namespace] = reservedNamespace) AndAlso (prefix <> reservedPrefix) Then
                ' "Prefix '{0}' cannot be bound to namespace name reserved for '{1}'."
                ReportDiagnostic(diagnostics, syntax, ERRID.ERR_ReservedXmlNamespace, prefix, reservedPrefix)
                Return True
            End If
            Return False
        End Function

        ''' <summary>
        ''' If name is "xmlns", set prefix to String.Empty and return True.
        ''' If name is "xmlns:p", set prefix to p and return True.
        ''' Otherwise return False.
        ''' </summary>
        Private Function TryGetXmlnsPrefix(syntax As XmlNameSyntax, <Out()> ByRef prefix As String, diagnostics As BindingDiagnosticBag) As Boolean
            Dim localName = GetXmlName(syntax.LocalName)
            Dim prefixName As String = Nothing

            If syntax.Prefix IsNot Nothing Then
                prefixName = GetXmlName(syntax.Prefix.Name)
                If prefixName = StringConstants.XmlnsPrefix Then
                    prefix = localName
                    Return True
                End If
            End If

            If localName = StringConstants.XmlnsPrefix Then
                ' Dev11 treats as p:xmlns="..." as an xmlns declaration, and ignores 'p',
                ' treating it as a declaration of the default namespace in all cases. Since
                ' the user probably intended to write xmlns:p="...", we now issue a warning.
                If Not String.IsNullOrEmpty(prefixName) Then
                    ' If 'p' maps to the empty namespace, we'll end up generating an attribute
                    ' with local name "xmlns" in the empty namespace, which the runtime will
                    ' interpret as an xmlns declaration of the default namespace. So, in that
                    ' case, we treat p:xmlns="..." as an xmlns declaration as in Dev11.
                    Dim fromImports = False
                    Dim [namespace] As String = Nothing
                    ' Lookup can ignore namespaces defined on XElements since we're interested
                    ' in the default namespace and that can only be defined with Imports.
                    If LookupXmlNamespace(prefixName, True, [namespace], fromImports) AndAlso ([namespace] = StringConstants.DefaultXmlNamespace) Then
                        ReportDiagnostic(diagnostics, syntax, ERRID.WRN_EmptyPrefixAndXmlnsLocalName)
                    Else
                        ReportDiagnostic(diagnostics, syntax, ERRID.WRN_PrefixAndXmlnsLocalName, prefixName)
                        prefix = Nothing
                        Return False
                    End If
                End If

                prefix = String.Empty
                Return True
            End If

            prefix = Nothing
            Return False
        End Function

        Private Shared Function GetXmlName(token As SyntaxToken) As String
            Select Case token.Kind
                Case SyntaxKind.XmlNameToken
                    Return token.ValueText
                Case Else
                    Throw ExceptionUtilities.UnexpectedValue(token.Kind)
            End Select
        End Function

        ''' <summary>
        ''' State tracked for the root XmlElement while binding nodes within the
        ''' tree. This state is mutable since it includes the set of namespaces from
        ''' Imports referenced within the tree. Ideally, this state would be part of the
        ''' XmlRootElementBinder, but since this state is mutable, there would be
        ''' issues caching and reusing the Binder. Instead, the state is passed
        ''' explicitly as an argument to each binding method.
        ''' </summary>
        Private NotInheritable Class XmlElementRootInfo
            Private ReadOnly _binder As Binder
            Private ReadOnly _syntax As XmlNodeSyntax
            Private ReadOnly _importedNamespaces As ArrayBuilder(Of KeyValuePair(Of String, String))
            Private _xmlnsAttributesPlaceholder As BoundRValuePlaceholder
            Private _removeNamespacesGroup As BoundMethodOrPropertyGroup

            Public Sub New(binder As Binder, syntax As XmlNodeSyntax, importedNamespaces As ArrayBuilder(Of KeyValuePair(Of String, String)))
                _binder = binder
                _syntax = syntax
                _importedNamespaces = importedNamespaces
            End Sub

            Public ReadOnly Property Syntax As XmlNodeSyntax
                Get
                    Return _syntax
                End Get
            End Property

            Public ReadOnly Property ImportedNamespaces As ArrayBuilder(Of KeyValuePair(Of String, String))
                Get
                    Return _importedNamespaces
                End Get
            End Property

            Public ReadOnly Property XmlnsAttributesPlaceholder As BoundRValuePlaceholder
                Get
                    Return _xmlnsAttributesPlaceholder
                End Get
            End Property

            Public Function BindRemoveNamespaceAttributesInvocation(
                                                                    expr As BoundExpression,
                                                                    prefixes As BoundRValuePlaceholder,
                                                                    namespaces As BoundRValuePlaceholder,
                                                                    diagnostics As BindingDiagnosticBag) As BoundExpression
                Return _binder.BindRemoveNamespaceAttributesInvocation(
                    _syntax,
                    expr,
                    prefixes,
                    namespaces,
                    _xmlnsAttributesPlaceholder,
                    _removeNamespacesGroup,
                    diagnostics)
            End Function
        End Class

    End Class

    ''' <summary>
    ''' Binding state used by the rewriter for XContainer derived types.
    ''' </summary>
    Friend NotInheritable Class BoundXmlContainerRewriterInfo
        Public Sub New(objectCreation As BoundExpression)
            Debug.Assert(objectCreation IsNot Nothing)
            Me.ObjectCreation = objectCreation
            Me.SideEffects = ImmutableArray(Of BoundExpression).Empty

            Me.HasErrors = objectCreation.HasErrors
        End Sub

        Public Sub New(isRoot As Boolean,
                       placeholder As BoundRValuePlaceholder,
                       objectCreation As BoundExpression,
                       xmlnsAttributesPlaceholder As BoundRValuePlaceholder,
                       xmlnsAttributes As BoundExpression,
                       prefixesPlaceholder As BoundRValuePlaceholder,
                       namespacesPlaceholder As BoundRValuePlaceholder,
                       importedNamespaces As ImmutableArray(Of KeyValuePair(Of String, String)),
                       inScopeXmlNamespaces As ImmutableArray(Of KeyValuePair(Of String, String)),
                       sideEffects As ImmutableArray(Of BoundExpression))
            Debug.Assert(isRoot = Not importedNamespaces.IsDefault)
            Debug.Assert(placeholder IsNot Nothing)
            Debug.Assert(objectCreation IsNot Nothing)
            Debug.Assert((xmlnsAttributesPlaceholder IsNot Nothing) = (xmlnsAttributes IsNot Nothing))
            Debug.Assert((prefixesPlaceholder IsNot Nothing) = (namespacesPlaceholder IsNot Nothing))
            Debug.Assert(Not sideEffects.IsDefault)

            Me.IsRoot = isRoot
            Me.Placeholder = placeholder
            Me.ObjectCreation = objectCreation
            Me.XmlnsAttributesPlaceholder = xmlnsAttributesPlaceholder
            Me.XmlnsAttributes = xmlnsAttributes
            Me.PrefixesPlaceholder = prefixesPlaceholder
            Me.NamespacesPlaceholder = namespacesPlaceholder
            Me.ImportedNamespaces = importedNamespaces
            Me.InScopeXmlNamespaces = inScopeXmlNamespaces
            Me.SideEffects = sideEffects

            Me.HasErrors = objectCreation.HasErrors OrElse sideEffects.Any(Function(s) s.HasErrors)
        End Sub

        Public ReadOnly IsRoot As Boolean
        Public ReadOnly Placeholder As BoundRValuePlaceholder
        Public ReadOnly ObjectCreation As BoundExpression
        Public ReadOnly XmlnsAttributesPlaceholder As BoundRValuePlaceholder
        Public ReadOnly XmlnsAttributes As BoundExpression
        Public ReadOnly PrefixesPlaceholder As BoundRValuePlaceholder
        Public ReadOnly NamespacesPlaceholder As BoundRValuePlaceholder
        Public ReadOnly ImportedNamespaces As ImmutableArray(Of KeyValuePair(Of String, String))
        Public ReadOnly InScopeXmlNamespaces As ImmutableArray(Of KeyValuePair(Of String, String))
        Public ReadOnly SideEffects As ImmutableArray(Of BoundExpression)
        Public ReadOnly HasErrors As Boolean
    End Class

    ''' <summary>
    ''' A binder to expose namespaces from Imports&lt;xmlns:...&gt; statements.
    ''' </summary>
    Friend NotInheritable Class XmlNamespaceImportsBinder
        Inherits Binder

        Private ReadOnly _namespaces As IReadOnlyDictionary(Of String, XmlNamespaceAndImportsClausePosition)

        Public Sub New(containingBinder As Binder, namespaces As IReadOnlyDictionary(Of String, XmlNamespaceAndImportsClausePosition))
            MyBase.New(containingBinder)
            Debug.Assert(namespaces IsNot Nothing)
            Debug.Assert(namespaces.Count > 0)
            _namespaces = namespaces
        End Sub

        Public Function GetImportChainData() As ImmutableArray(Of ImportedXmlNamespace)
            Return _namespaces.SelectAsArray(Function(kvp) New ImportedXmlNamespace(kvp.Value.XmlNamespace, kvp.Value.SyntaxReference))
        End Function

        Friend Overrides ReadOnly Property HasImportedXmlNamespaces As Boolean
            Get
                Return True
            End Get
        End Property

        Friend Overrides Function LookupXmlNamespace(prefix As String,
                                                     ignoreXmlNodes As Boolean,
                                                     <Out()> ByRef [namespace] As String,
                                                     <Out()> ByRef fromImports As Boolean) As Boolean
            Dim result As XmlNamespaceAndImportsClausePosition = Nothing
            If _namespaces.TryGetValue(prefix, result) Then
                [namespace] = result.XmlNamespace
                Me.Compilation.MarkImportDirectiveAsUsed(Me.SyntaxTree, result.ImportsClausePosition)
                fromImports = True
                Return True
            End If

            Return MyBase.LookupXmlNamespace(prefix, ignoreXmlNodes, [namespace], fromImports)
        End Function
    End Class

    Friend NotInheritable Class XmlRootElementBinder
        Inherits Binder

        Public Sub New(containingBinder As Binder)
            MyBase.New(containingBinder)
        End Sub

        Friend Overrides Sub GetInScopeXmlNamespaces(builder As ArrayBuilder(Of KeyValuePair(Of String, String)))
        End Sub
    End Class

    ''' <summary>
    ''' A binder for XmlElement declarations.
    ''' </summary>
    Friend NotInheritable Class XmlElementBinder
        Inherits Binder
        Private ReadOnly _namespaces As Dictionary(Of String, String)

        Public Sub New(containingBinder As Binder, namespaces As Dictionary(Of String, String))
            MyBase.New(containingBinder)
            Debug.Assert(namespaces IsNot Nothing)
            Debug.Assert(namespaces.Count > 0)
            _namespaces = namespaces
        End Sub

        Friend Overrides Function LookupXmlNamespace(prefix As String, ignoreXmlNodes As Boolean, <Out()> ByRef [namespace] As String, <Out()> ByRef fromImports As Boolean) As Boolean
            If Not ignoreXmlNodes Then
                If _namespaces.TryGetValue(prefix, [namespace]) Then
                    fromImports = False
                    Return True
                End If
            End If
            Return MyBase.LookupXmlNamespace(prefix, ignoreXmlNodes, [namespace], fromImports)
        End Function

        Friend Overrides Sub GetInScopeXmlNamespaces(builder As ArrayBuilder(Of KeyValuePair(Of String, String)))
            builder.AddRange(_namespaces)
            ContainingBinder.GetInScopeXmlNamespaces(builder)
        End Sub
    End Class

    Friend NotInheritable Class XmlEmbeddedExpressionBinder
        Inherits Binder

        Public Sub New(containingBinder As Binder)
            MyBase.New(containingBinder)
        End Sub

        Friend Overrides Function LookupXmlNamespace(prefix As String, ignoreXmlNodes As Boolean, <Out()> ByRef [namespace] As String, <Out()> ByRef fromImports As Boolean) As Boolean
            ' Perform further namespace lookup on the nearest containing binder
            ' that is outside any XML to avoid inheriting xmlns declarations
            ' from XML nodes outside of the embedded expression.
            Return MyBase.LookupXmlNamespace(prefix, True, [namespace], fromImports)
        End Function

        Friend Overrides Sub GetInScopeXmlNamespaces(builder As ArrayBuilder(Of KeyValuePair(Of String, String)))
        End Sub
    End Class

    ''' <summary>
    ''' An extension property in reduced form, with first parameter
    ''' removed and exposed as an explicit receiver type.
    ''' </summary>
    Friend NotInheritable Class ReducedExtensionPropertySymbol
        Inherits PropertySymbol

        Private ReadOnly _originalDefinition As PropertySymbol

        Public Sub New(originalDefinition As PropertySymbol)
            Debug.Assert(originalDefinition IsNot Nothing)
            Debug.Assert(originalDefinition.IsShared)
            Debug.Assert(originalDefinition.ParameterCount = 1)

            _originalDefinition = originalDefinition
        End Sub

        Friend Overrides ReadOnly Property ReducedFrom As PropertySymbol
            Get
                Return _originalDefinition
            End Get
        End Property

        Friend Overrides ReadOnly Property ReducedFromDefinition As PropertySymbol
            Get
                Return _originalDefinition
            End Get
        End Property

        Friend Overrides ReadOnly Property ReceiverType As TypeSymbol
            Get
                Return _originalDefinition.Parameters(0).Type
            End Get
        End Property

        Public Overrides ReadOnly Property Name As String
            Get
                Return _originalDefinition.Name
            End Get
        End Property

        Friend Overrides ReadOnly Property HasSpecialName As Boolean
            Get
                Return _originalDefinition.HasSpecialName
            End Get
        End Property

        Friend Overrides ReadOnly Property CallingConvention As Microsoft.Cci.CallingConvention
            Get
                Return _originalDefinition.CallingConvention
            End Get
        End Property

        Public Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return _originalDefinition.ContainingSymbol
            End Get
        End Property

        Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
            Get
                Return _originalDefinition.DeclaredAccessibility
            End Get
        End Property

        Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
            Get
                Return _originalDefinition.DeclaringSyntaxReferences
            End Get
        End Property

        Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of PropertySymbol)
            Get
                Return ImmutableArray(Of PropertySymbol).Empty
            End Get
        End Property

        Public Overrides ReadOnly Property GetMethod As MethodSymbol
            Get
                Return ReduceAccessorIfAny(_originalDefinition.GetMethod)
            End Get
        End Property

        Friend Overrides ReadOnly Property AssociatedField As FieldSymbol
            Get
                Return _originalDefinition.AssociatedField
            End Get
        End Property

        Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
            Get
                Return _originalDefinition.ObsoleteAttributeData
            End Get
        End Property

        Public Overrides ReadOnly Property IsDefault As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsMustOverride As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsNotOverridable As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsOverloads As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides Function GetOverloadResolutionPriority() As Integer
            Return _originalDefinition.GetOverloadResolutionPriority()
        End Function

        Public Overrides ReadOnly Property IsOverridable As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsOverrides As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsShared As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return _originalDefinition.Locations
            End Get
        End Property

        Public Overrides ReadOnly Property Parameters As ImmutableArray(Of ParameterSymbol)
            Get
                Return ImmutableArray(Of ParameterSymbol).Empty
            End Get
        End Property

        Public Overrides ReadOnly Property ParameterCount As Integer
            Get
                Return 0
            End Get
        End Property

        Public Overrides ReadOnly Property SetMethod As MethodSymbol
            Get
                Return ReduceAccessorIfAny(_originalDefinition.SetMethod)
            End Get
        End Property

        Public Overrides ReadOnly Property ReturnsByRef As Boolean
            Get
                Return _originalDefinition.ReturnsByRef
            End Get
        End Property

        Public Overrides ReadOnly Property Type As TypeSymbol
            Get
                Return _originalDefinition.Type
            End Get
        End Property

        Public Overrides ReadOnly Property TypeCustomModifiers As ImmutableArray(Of CustomModifier)
            Get
                Return _originalDefinition.TypeCustomModifiers
            End Get
        End Property

        Public Overrides ReadOnly Property RefCustomModifiers As ImmutableArray(Of CustomModifier)
            Get
                Return _originalDefinition.RefCustomModifiers
            End Get
        End Property

        Private Function ReduceAccessorIfAny(methodOpt As MethodSymbol) As ReducedExtensionAccessorSymbol
            Return If(methodOpt Is Nothing, Nothing, New ReducedExtensionAccessorSymbol(Me, methodOpt))
        End Function

        Friend Overrides ReadOnly Property IsMyGroupCollectionProperty As Boolean
            Get
                Debug.Assert(Not _originalDefinition.IsMyGroupCollectionProperty)
                Return False
            End Get
        End Property

        Public Overrides ReadOnly Property IsRequired As Boolean
            Get
                Return False
            End Get
        End Property

        Private NotInheritable Class ReducedExtensionAccessorSymbol
            Inherits MethodSymbol

            Private ReadOnly _associatedProperty As ReducedExtensionPropertySymbol
            Private ReadOnly _originalDefinition As MethodSymbol
            Private _lazyParameters As ImmutableArray(Of ParameterSymbol)

            Public Sub New(associatedProperty As ReducedExtensionPropertySymbol, originalDefinition As MethodSymbol)
                _associatedProperty = associatedProperty
                _originalDefinition = originalDefinition
            End Sub

            Friend Overrides ReadOnly Property CallsiteReducedFromMethod As MethodSymbol
                Get
                    Return _originalDefinition
                End Get
            End Property

            Public Overrides ReadOnly Property ReducedFrom As MethodSymbol
                Get
                    Return _originalDefinition
                End Get
            End Property

            Public Overrides ReadOnly Property Arity As Integer
                Get
                    Return 0
                End Get
            End Property

            Public Overrides ReadOnly Property AssociatedSymbol As Symbol
                Get
                    Return _associatedProperty
                End Get
            End Property

            Friend Overrides ReadOnly Property HasSpecialName As Boolean
                Get
                    Return _originalDefinition.HasSpecialName
                End Get
            End Property

            Friend Overrides ReadOnly Property CallingConvention As Microsoft.Cci.CallingConvention
                Get
                    Return Microsoft.Cci.CallingConvention.HasThis
                End Get
            End Property

            Public Overrides ReadOnly Property ContainingSymbol As Symbol
                Get
                    Return _originalDefinition.ContainingSymbol
                End Get
            End Property

            Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
                Get
                    Return _originalDefinition.DeclaredAccessibility
                End Get
            End Property

            Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
                Get
                    Return _originalDefinition.DeclaringSyntaxReferences
                End Get
            End Property

            Public Overrides ReadOnly Property ExplicitInterfaceImplementations As ImmutableArray(Of MethodSymbol)
                Get
                    Return ImmutableArray(Of MethodSymbol).Empty
                End Get
            End Property

            Public Overrides ReadOnly Property IsExtensionMethod As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsExternalMethod As Boolean
                Get
                    Return _originalDefinition.IsExternalMethod
                End Get
            End Property

            Public Overrides Function GetDllImportData() As DllImportData
                Return _originalDefinition.GetDllImportData()
            End Function

            Friend Overrides ReadOnly Property ReturnTypeMarshallingInformation As MarshalPseudoCustomAttributeData
                Get
                    Return _originalDefinition.ReturnTypeMarshallingInformation
                End Get
            End Property

            Friend Overrides ReadOnly Property ImplementationAttributes As Reflection.MethodImplAttributes
                Get
                    Return _originalDefinition.ImplementationAttributes
                End Get
            End Property

            Friend Overrides ReadOnly Property HasDeclarativeSecurity As Boolean
                Get
                    Return _originalDefinition.HasDeclarativeSecurity
                End Get
            End Property

            Friend Overrides Function GetSecurityInformation() As IEnumerable(Of Microsoft.Cci.SecurityAttribute)
                Return _originalDefinition.GetSecurityInformation()
            End Function

            Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
                Get
                    Return _originalDefinition.ObsoleteAttributeData
                End Get
            End Property

            Public Overrides ReadOnly Property IsMustOverride As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsNotOverridable As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsOverloads As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides Function GetOverloadResolutionPriority() As Integer
                Return _originalDefinition.GetOverloadResolutionPriority()
            End Function

            Public Overrides ReadOnly Property IsOverridable As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsOverrides As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsShared As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsSub As Boolean
                Get
                    Return _originalDefinition.IsSub
                End Get
            End Property

            Public Overrides ReadOnly Property IsAsync As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsIterator As Boolean
                Get
                    Return False
                End Get
            End Property

            Public Overrides ReadOnly Property IsInitOnly As Boolean
                Get
                    Return _originalDefinition.IsInitOnly
                End Get
            End Property

            Public Overrides ReadOnly Property IsVararg As Boolean
                Get
                    Return _originalDefinition.IsVararg
                End Get
            End Property

            Friend Overrides Function GetAppliedConditionalSymbols() As ImmutableArray(Of String)
                Return _originalDefinition.GetAppliedConditionalSymbols()
            End Function

            Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
                Get
                    Return _originalDefinition.Locations
                End Get
            End Property

            Public Overrides ReadOnly Property MethodKind As MethodKind
                Get
                    Return _originalDefinition.MethodKind
                End Get
            End Property

            Friend Overrides ReadOnly Property IsMethodKindBasedOnSyntax As Boolean
                Get
                    Return _originalDefinition.IsMethodKindBasedOnSyntax
                End Get
            End Property

            Friend Overrides ReadOnly Property ParameterCount As Integer
                Get
                    Return _originalDefinition.ParameterCount - 1
                End Get
            End Property

            Public Overrides ReadOnly Property Parameters As ImmutableArray(Of ParameterSymbol)
                Get
                    If _lazyParameters.IsDefault Then
                        ImmutableInterlocked.InterlockedInitialize(_lazyParameters, ReducedAccessorParameterSymbol.MakeParameters(Me, _originalDefinition.Parameters))
                    End If
                    Return _lazyParameters
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnsByRef As Boolean
                Get
                    Return _originalDefinition.ReturnsByRef
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnType As TypeSymbol
                Get
                    Return _originalDefinition.ReturnType
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnTypeCustomModifiers As ImmutableArray(Of CustomModifier)
                Get
                    Return _originalDefinition.ReturnTypeCustomModifiers
                End Get
            End Property

            Public Overrides ReadOnly Property RefCustomModifiers As ImmutableArray(Of CustomModifier)
                Get
                    Return _originalDefinition.RefCustomModifiers
                End Get
            End Property

            Friend Overrides ReadOnly Property Syntax As SyntaxNode
                Get
                    Return _originalDefinition.Syntax
                End Get
            End Property

            Public Overrides ReadOnly Property TypeArguments As ImmutableArray(Of TypeSymbol)
                Get
                    Return _originalDefinition.TypeArguments
                End Get
            End Property

            Public Overrides ReadOnly Property TypeParameters As ImmutableArray(Of TypeParameterSymbol)
                Get
                    Return _originalDefinition.TypeParameters
                End Get
            End Property

            Friend Overrides Function IsMetadataNewSlot(Optional ignoreInterfaceImplementationChanges As Boolean = False) As Boolean
                Return False
            End Function

            Friend Overrides ReadOnly Property GenerateDebugInfoImpl As Boolean
                Get
                    Return _originalDefinition.GenerateDebugInfo
                End Get
            End Property

            Friend Overrides Function CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer
                Throw ExceptionUtilities.Unreachable
            End Function

            Friend Overrides ReadOnly Property HasSetsRequiredMembers As Boolean
                Get
                    Return False
                End Get
            End Property
        End Class

        Private NotInheritable Class ReducedAccessorParameterSymbol
            Inherits ReducedParameterSymbolBase

            Public Shared Function MakeParameters(propertyOrAccessor As Symbol, originalParameters As ImmutableArray(Of ParameterSymbol)) As ImmutableArray(Of ParameterSymbol)
                Dim n = originalParameters.Length

                If n <= 1 Then
                    Debug.Assert(n = 1)
                    Return ImmutableArray(Of ParameterSymbol).Empty
                Else
                    Dim parameters(n - 2) As ParameterSymbol
                    For i = 0 To n - 2
                        parameters(i) = New ReducedAccessorParameterSymbol(propertyOrAccessor, originalParameters(i + 1))
                    Next
                    Return parameters.AsImmutableOrNull()
                End If
            End Function

            Private ReadOnly _propertyOrAccessor As Symbol

            Public Sub New(propertyOrAccessor As Symbol, underlyingParameter As ParameterSymbol)
                MyBase.New(underlyingParameter)
                _propertyOrAccessor = propertyOrAccessor
            End Sub

            Public Overrides ReadOnly Property ContainingSymbol As Symbol
                Get
                    Return _propertyOrAccessor
                End Get
            End Property

            Public Overrides ReadOnly Property Type As TypeSymbol
                Get
                    Return m_CurriedFromParameter.Type
                End Get
            End Property
        End Class
    End Class

End Namespace
