File: CodeModel\VisualBasicCodeModelService.vb
Web Access
Project: src\src\VisualStudio\VisualBasic\Impl\Microsoft.VisualStudio.LanguageServices.VisualBasic.vbproj (Microsoft.VisualStudio.LanguageServices.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports System.Text
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeGeneration
Imports Microsoft.CodeAnalysis.Editor
Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.InternalElements
Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.Interop
Imports Microsoft.VisualStudio.LanguageServices.Implementation.Utilities
Imports Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.Extenders
Imports Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXml
Imports Microsoft.VisualStudio.Text
Imports Microsoft.VisualStudio.Text.Editor
 
Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel
    Partial Friend Class VisualBasicCodeModelService
        Inherits AbstractCodeModelService
 
        Private Shared ReadOnly s_emptyTree As SyntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From("", encoding:=Nothing, SourceHashAlgorithms.Default))
 
        Private ReadOnly _commitBufferManagerFactory As CommitBufferManagerFactory
 
        Friend Sub New(
            provider As HostLanguageServices,
            editorOptionsService As EditorOptionsService,
            refactorNotifyServices As IEnumerable(Of IRefactorNotifyService),
            commitBufferManagerFactory As CommitBufferManagerFactory,
            threadingContext As IThreadingContext)
 
            MyBase.New(
                provider,
                editorOptionsService,
                refactorNotifyServices,
                LineAdjustmentFormattingRule.Instance,
                EndRegionFormattingRule.Instance,
                threadingContext)
 
            Me._commitBufferManagerFactory = commitBufferManagerFactory
        End Sub
 
        Private Shared ReadOnly s_codeTypeRefAsFullNameFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.ExpandNullable)
 
        Private Shared ReadOnly s_codeTypeRefAsStringFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.UseSpecialTypes)
 
        Private Shared ReadOnly s_externalNameFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.ExpandNullable,
                parameterOptions:=SymbolDisplayParameterOptions.IncludeName)
 
        Private Shared ReadOnly s_externalfullNameFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                memberOptions:=SymbolDisplayMemberOptions.IncludeContainingType,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.ExpandNullable,
                parameterOptions:=SymbolDisplayParameterOptions.IncludeName)
 
        Private Shared ReadOnly s_setTypeFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.ExpandNullable Or SymbolDisplayMiscellaneousOptions.UseSpecialTypes)
 
        Private Shared ReadOnly s_raiseEventSignatureFormat As SymbolDisplayFormat =
            New SymbolDisplayFormat(
                typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
                genericsOptions:=SymbolDisplayGenericsOptions.IncludeTypeParameters,
                parameterOptions:=SymbolDisplayParameterOptions.IncludeName Or SymbolDisplayParameterOptions.IncludeParamsRefOut Or SymbolDisplayParameterOptions.IncludeType,
                miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.UseSpecialTypes)
 
        Private Shared Function IsNameableNode(node As SyntaxNode) As Boolean
            Select Case node.Kind
                Case SyntaxKind.Attribute,
                     SyntaxKind.ClassBlock,
                     SyntaxKind.ConstructorBlock,
                     SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement,
                     SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement,
                     SyntaxKind.EnumBlock,
                     SyntaxKind.EnumMemberDeclaration,
                     SyntaxKind.EventBlock,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.InterfaceBlock,
                     SyntaxKind.ModuleBlock,
                     SyntaxKind.NamespaceBlock,
                     SyntaxKind.OperatorBlock,
                     SyntaxKind.Parameter,
                     SyntaxKind.PropertyBlock,
                     SyntaxKind.StructureBlock,
                     SyntaxKind.SubBlock,
                     SyntaxKind.OptionStatement,
                     SyntaxKind.SimpleImportsClause,
                     SyntaxKind.InheritsStatement,
                     SyntaxKind.ImplementsStatement
 
                    Return True
 
                Case SyntaxKind.NameColonEquals
                    Return True
 
                Case SyntaxKind.SimpleArgument,
                     SyntaxKind.OmittedArgument
                    ' Only arguments in attributes are valid
                    Return node.FirstAncestorOrSelf(Of AttributeSyntax) IsNot Nothing
 
                Case SyntaxKind.ModifiedIdentifier
                    Return node.FirstAncestorOrSelf(Of FieldDeclarationSyntax)() IsNot Nothing
 
                Case SyntaxKind.EventStatement
                    ' Only top-level event statements that aren't included in an event block are valid (e.g. single line events)
                    Return node.FirstAncestorOrSelf(Of EventBlockSyntax)() Is Nothing
 
                Case SyntaxKind.PropertyStatement
                    ' Only top-level property statements that aren't included in an property block are valid (e.g. auto-properties)
                    Return node.FirstAncestorOrSelf(Of PropertyBlockSyntax)() Is Nothing
 
                Case SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement
                    Return node.FirstAncestorOrSelf(Of MethodBlockSyntax)() Is Nothing
 
                Case Else
                    Return False
            End Select
        End Function
 
        Public Overrides Function GetElementKind(node As SyntaxNode) As EnvDTE.vsCMElement
            Select Case node.Kind
                Case SyntaxKind.ModuleBlock
                    Return EnvDTE.vsCMElement.vsCMElementModule
                Case SyntaxKind.ClassBlock
                    Return EnvDTE.vsCMElement.vsCMElementClass
                Case Else
                    Debug.Fail("Unsupported element kind" & CType(node.Kind, SyntaxKind))
                    Throw Exceptions.ThrowEInvalidArg()
            End Select
        End Function
 
        Public Overrides Function MatchesScope(node As SyntaxNode, scope As EnvDTE.vsCMElement) As Boolean
            'TODO: This has been copied from CSharpCodeModelService. Tweak to implement VB semantics.
            Select Case node.Kind
                Case SyntaxKind.NamespaceBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementNamespace AndAlso
                        node.Parent IsNot Nothing Then
                        Return True
                    End If
 
                Case SyntaxKind.ModuleBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementModule Then
                        Return True
                    End If
 
                Case SyntaxKind.ClassBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementClass Then
                        Return True
                    End If
                Case SyntaxKind.StructureBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementStruct Then
                        Return True
                    End If
 
                Case SyntaxKind.FunctionStatement,
                     SyntaxKind.SubStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementFunction AndAlso
                        node.FirstAncestorOrSelf(Of MethodBlockSyntax)() Is Nothing Then
                        Return True
                    End If
 
                Case SyntaxKind.ConstructorBlock,
                     SyntaxKind.SubBlock,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.OperatorBlock,
                     SyntaxKind.GetAccessorBlock,
                     SyntaxKind.SetAccessorBlock,
                     SyntaxKind.AddHandlerAccessorBlock,
                     SyntaxKind.RemoveHandlerAccessorBlock,
                     SyntaxKind.RaiseEventAccessorBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementFunction Then
                        Return True
                    End If
 
                Case SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementDeclareDecl Then
                        Return True
                    End If
 
                Case SyntaxKind.EnumMemberDeclaration
                    If scope = EnvDTE.vsCMElement.vsCMElementVariable Then
                        Return True
                    End If
 
                Case SyntaxKind.FieldDeclaration
                    If scope = EnvDTE.vsCMElement.vsCMElementVariable Then
                        Return True
                    End If
 
                Case SyntaxKind.EventBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementEvent Then
                        Return True
                    End If
 
                Case SyntaxKind.EventStatement
                    If Not TypeOf node.Parent Is EventBlockSyntax Then
                        If scope = EnvDTE.vsCMElement.vsCMElementEvent Then
                            Return True
                        End If
                    End If
 
                Case SyntaxKind.PropertyBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementProperty Then
                        Return True
                    End If
 
                Case SyntaxKind.PropertyStatement
                    If Not TypeOf node.Parent Is PropertyBlockSyntax Then
                        If scope = EnvDTE.vsCMElement.vsCMElementProperty Then
                            Return True
                        End If
                    End If
 
                Case SyntaxKind.Attribute
                    If scope = EnvDTE.vsCMElement.vsCMElementAttribute Then
                        Return True
                    End If
 
                Case SyntaxKind.InterfaceBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementInterface Then
                        Return True
                    End If
 
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementDelegate Then
                        Return True
                    End If
 
                Case SyntaxKind.EnumBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementEnum Then
                        Return True
                    End If
 
                Case SyntaxKind.StructureBlock
                    If scope = EnvDTE.vsCMElement.vsCMElementStruct Then
                        Return True
                    End If
 
                Case SyntaxKind.SimpleImportsClause
                    If scope = EnvDTE.vsCMElement.vsCMElementImportStmt Then
                        Return True
                    End If
 
                Case SyntaxKind.ModifiedIdentifier,
                     SyntaxKind.VariableDeclarator
                    If node.Parent.Kind <> SyntaxKind.Parameter Then
                        ' The parent of an identifier/variable declarator may be a
                        ' field. If the parent matches the desired scope, then this
                        ' node matches as well.
                        Return MatchesScope(node.Parent, scope)
                    End If
 
                Case SyntaxKind.Parameter
                    If scope = EnvDTE.vsCMElement.vsCMElementParameter Then
                        Return True
                    End If
 
                Case SyntaxKind.OptionStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementOptionStmt Then
                        Return True
                    End If
 
                Case SyntaxKind.InheritsStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementInheritsStmt Then
                        Return True
                    End If
 
                Case SyntaxKind.ImplementsStatement
                    If scope = EnvDTE.vsCMElement.vsCMElementImplementsStmt Then
                        Return True
                    End If
 
                Case Else
                    Return False
            End Select
 
            Return False
        End Function
 
        Public Overrides Function GetOptionNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is CompilationUnitSyntax Then
                Return DirectCast(parent, CompilationUnitSyntax).Options.AsEnumerable()
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Private Overloads Shared Function GetImportNodes(parent As CompilationUnitSyntax) As IEnumerable(Of SyntaxNode)
            Dim result = New List(Of SyntaxNode)
 
            For Each importStatement In parent.Imports
                For Each importClause In importStatement.ImportsClauses
                    ' NOTE: XmlNamespaceImportsClause is not support by VB Code Model
                    If importClause.IsKind(SyntaxKind.SimpleImportsClause) Then
                        result.Add(importClause)
                    End If
                Next
            Next
 
            Return result
        End Function
 
        Public Overrides Function GetImportNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is CompilationUnitSyntax Then
                Return GetImportNodes(DirectCast(parent, CompilationUnitSyntax))
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Private Overloads Shared Function GetAttributeNodes(attributesBlockList As SyntaxList(Of AttributeListSyntax)) As IEnumerable(Of SyntaxNode)
            Dim result = New List(Of SyntaxNode)
 
            For Each attributeBlock In attributesBlockList
                For Each attribute In attributeBlock.Attributes
                    result.Add(attribute)
                Next
            Next
 
            Return result
        End Function
 
        Private Overloads Shared Function GetAttributeNodes(attributesStatementList As SyntaxList(Of AttributesStatementSyntax)) As IEnumerable(Of SyntaxNode)
            Dim result = New List(Of SyntaxNode)
 
            For Each attributesStatement In attributesStatementList
                For Each attributeBlock In attributesStatement.AttributeLists
                    For Each attribute In attributeBlock.Attributes
                        result.Add(attribute)
                    Next
                Next
            Next
 
            Return result
        End Function
 
        Public Overrides Function GetAttributeNodes(node As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf node Is CompilationUnitSyntax Then
                Return GetAttributeNodes(DirectCast(node, CompilationUnitSyntax).Attributes)
            ElseIf TypeOf node Is TypeBlockSyntax Then
                Return GetAttributeNodes(DirectCast(node, TypeBlockSyntax).BlockStatement.AttributeLists)
            ElseIf TypeOf node Is EnumBlockSyntax Then
                Return GetAttributeNodes(DirectCast(node, EnumBlockSyntax).EnumStatement.AttributeLists)
            ElseIf TypeOf node Is DelegateStatementSyntax Then
                Return GetAttributeNodes(DirectCast(node, DelegateStatementSyntax).AttributeLists)
            ElseIf TypeOf node Is DeclareStatementSyntax Then
                Return GetAttributeNodes(DirectCast(node, DeclareStatementSyntax).AttributeLists)
            ElseIf TypeOf node Is MethodStatementSyntax Then
                Return GetAttributeNodes(DirectCast(node, MethodStatementSyntax).AttributeLists)
            ElseIf TypeOf node Is MethodBlockBaseSyntax Then
                Return GetAttributeNodes(DirectCast(node, MethodBlockBaseSyntax).BlockStatement.AttributeLists)
            ElseIf TypeOf node Is PropertyBlockSyntax Then
                Return GetAttributeNodes(DirectCast(node, PropertyBlockSyntax).PropertyStatement.AttributeLists)
            ElseIf TypeOf node Is PropertyStatementSyntax Then
                Return GetAttributeNodes(DirectCast(node, PropertyStatementSyntax).AttributeLists)
            ElseIf TypeOf node Is EventBlockSyntax Then
                Return GetAttributeNodes(DirectCast(node, EventBlockSyntax).EventStatement.AttributeLists)
            ElseIf TypeOf node Is EventStatementSyntax Then
                Return GetAttributeNodes(DirectCast(node, EventStatementSyntax).AttributeLists)
            ElseIf TypeOf node Is FieldDeclarationSyntax Then
                Return GetAttributeNodes(DirectCast(node, FieldDeclarationSyntax).AttributeLists)
            ElseIf TypeOf node Is ParameterSyntax Then
                Return GetAttributeNodes(DirectCast(node, ParameterSyntax).AttributeLists)
            ElseIf TypeOf node Is EnumMemberDeclarationSyntax Then
                Return GetAttributeNodes(DirectCast(node, EnumMemberDeclarationSyntax).AttributeLists)
            ElseIf TypeOf node Is ModifiedIdentifierSyntax OrElse
                   TypeOf node Is VariableDeclaratorSyntax Then
                Return GetAttributeNodes(node.Parent)
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Public Overrides Function GetAttributeArgumentNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is AttributeSyntax Then
                Dim attribute = DirectCast(parent, AttributeSyntax)
 
                If attribute.ArgumentList Is Nothing Then
                    Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
                End If
 
                Return attribute.ArgumentList.Arguments
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Public Overrides Function GetInheritsNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is TypeBlockSyntax Then
                Dim typeBlock = DirectCast(parent, TypeBlockSyntax)
 
                Return typeBlock.Inherits.AsEnumerable()
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Public Overrides Function GetImplementsNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is TypeBlockSyntax Then
                Dim typeBlock = DirectCast(parent, TypeBlockSyntax)
 
                Return typeBlock.Implements.AsEnumerable()
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
        End Function
 
        Private Shared Function IsContainerNode(container As SyntaxNode) As Boolean
            Return TypeOf container Is CompilationUnitSyntax OrElse
                   TypeOf container Is NamespaceBlockSyntax OrElse
                   TypeOf container Is TypeBlockSyntax OrElse
                   TypeOf container Is EnumBlockSyntax
        End Function
 
        Private Shared Function IsNamespaceOrTypeDeclaration(node As SyntaxNode) As Boolean
            Return node.Kind() = SyntaxKind.NamespaceBlock OrElse
                   TypeOf node Is TypeBlockSyntax OrElse
                   TypeOf node Is EnumBlockSyntax OrElse
                   TypeOf node Is DelegateStatementSyntax
        End Function
 
        Private Shared Iterator Function GetChildMemberNodes(container As SyntaxNode) As IEnumerable(Of DeclarationStatementSyntax)
            If TypeOf container Is CompilationUnitSyntax Then
                For Each member In DirectCast(container, CompilationUnitSyntax).Members
                    If IsNamespaceOrTypeDeclaration(member) Then
                        Yield DirectCast(member, DeclarationStatementSyntax)
                    End If
                Next
            ElseIf TypeOf container Is NamespaceBlockSyntax Then
                For Each member In DirectCast(container, NamespaceBlockSyntax).Members
                    If IsNamespaceOrTypeDeclaration(member) Then
                        Yield DirectCast(member, DeclarationStatementSyntax)
                    End If
                Next
            ElseIf TypeOf container Is TypeBlockSyntax Then
                For Each member In DirectCast(container, TypeBlockSyntax).Members
                    If member.Kind() <> SyntaxKind.NamespaceBlock AndAlso TypeOf member Is DeclarationStatementSyntax Then
                        Yield DirectCast(member, DeclarationStatementSyntax)
                    End If
                Next
            ElseIf TypeOf container Is EnumBlockSyntax Then
                For Each member In DirectCast(container, EnumBlockSyntax).Members
                    If member.Kind() = SyntaxKind.EnumMemberDeclaration Then
                        Yield DirectCast(member, DeclarationStatementSyntax)
                    End If
                Next
            End If
        End Function
 
        Private Shared Function NodeIsSupported(test As Boolean, node As SyntaxNode) As Boolean
            Return Not test OrElse IsNameableNode(node)
        End Function
 
        ''' <summary>
        ''' Retrieves the members of a specified <paramref name="container"/> node. The members that are
        ''' returned can be controlled by passing various parameters.
        ''' </summary>
        ''' <param name="container">The <see cref="SyntaxNode"/> from which to retrieve members.</param>
        ''' <param name="includeSelf">If true, the container Is returned as well.</param>
        ''' <param name="recursive">If true, members are recursed to return descendant members as well
        ''' as immediate children. For example, a namespace would return the namespaces And types within.
        ''' However, if <paramref name="recursive"/> Is true, members with the namespaces And types would
        ''' also be returned.</param>
        ''' <param name="logicalFields">If true, field declarations are broken into their respective declarators.
        ''' For example, the field "Dim x, y As Integer" would return two nodes, one for x And one for y in place
        ''' of the field.</param>
        ''' <param name="onlySupportedNodes">If true, only members supported by Code Model are returned.</param>
        Public Overrides Iterator Function GetMemberNodes(container As SyntaxNode, includeSelf As Boolean, recursive As Boolean, logicalFields As Boolean, onlySupportedNodes As Boolean) As IEnumerable(Of SyntaxNode)
 
            If Not IsContainerNode(container) Then
                Exit Function
            End If
 
            If includeSelf AndAlso NodeIsSupported(onlySupportedNodes, container) Then
                Yield container
            End If
 
            For Each member In GetChildMemberNodes(container)
 
                If member.Kind = SyntaxKind.FieldDeclaration Then
                    ' For fields, the 'logical' and 'supported' flags are intrinsically tied.
                    '   * If 'logical' is true, only declarators should be returned, regardless of the value of 'supported'.
                    '   * If 'logical' is false, the field should only be returned if 'supported' is also false.
 
                    If logicalFields Then
 
                        For Each declarator In DirectCast(member, FieldDeclarationSyntax).Declarators
 
                            ' We know that declarators are supported, so there's no need to check them here.
                            For Each identifier In declarator.Names
                                Yield identifier
                            Next
                        Next
 
                    ElseIf Not onlySupportedNodes Then
                        ' Only return fields if the supported flag Is false.
                        Yield member
                    End If
 
                ElseIf NodeIsSupported(onlySupportedNodes, member) Then
                    Yield member
                End If
 
                If recursive AndAlso IsContainerNode(member) Then
                    For Each innerMember In GetMemberNodes(member, includeSelf:=False, recursive:=True, logicalFields:=logicalFields, onlySupportedNodes:=onlySupportedNodes)
                        Yield innerMember
                    Next
                End If
            Next
        End Function
 
        Public Overrides ReadOnly Property Language As String
            Get
                Return EnvDTE.CodeModelLanguageConstants.vsCMLanguageVB
            End Get
        End Property
 
        Public Overrides ReadOnly Property AssemblyAttributeString As String
            Get
                Return "Assembly"
            End Get
        End Property
 
        ''' <summary>
        ''' Do not use this method directly! Instead, go through <see cref="FileCodeModel.GetOrCreateCodeElement(Of T)(SyntaxNode)"/>
        ''' </summary>
        Public Overloads Overrides Function CreateInternalCodeElement(
            state As CodeModelState,
            fileCodeModel As FileCodeModel,
            node As SyntaxNode
        ) As EnvDTE.CodeElement
 
            Select Case node.Kind
                Case SyntaxKind.Attribute
                    Return CType(CreateInternalCodeAttribute(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.NameColonEquals
                    Return Nothing
                Case SyntaxKind.SimpleArgument
                    Return CType(CreateInternalCodeAttributeArgument(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.SimpleImportsClause
                    Return CType(CreateInternalCodeImport(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.ImportsStatement
                    Dim importsStatement = DirectCast(node, ImportsStatementSyntax)
                    Return CreateInternalCodeElement(state, fileCodeModel, importsStatement.ImportsClauses(0))
                Case SyntaxKind.Parameter
                    Return CType(CreateInternalCodeParameter(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.OptionStatement
                    Return CType(CreateInternalCodeOptionStatement(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.InheritsStatement
                    Return CType(CreateInternalCodeInheritsStatement(state, fileCodeModel, node), EnvDTE.CodeElement)
                Case SyntaxKind.ImplementsStatement
                    Return CType(CreateInternalCodeImplementsStatement(state, fileCodeModel, node), EnvDTE.CodeElement)
            End Select
 
            If IsAccessorNode(node) Then
                Return CType(CreateInternalCodeAccessorFunction(state, fileCodeModel, node), EnvDTE.CodeElement)
            End If
 
            Dim nodeKey = GetNodeKey(node)
 
            Select Case node.Kind
                Case SyntaxKind.ClassBlock,
                     SyntaxKind.ModuleBlock
                    Return CType(CodeClass.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.StructureBlock
                    Return CType(CodeStruct.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.InterfaceBlock
                    Return CType(CodeInterface.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.EnumBlock
                    Return CType(CodeEnum.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    Return CType(CodeDelegate.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.ConstructorBlock,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.OperatorBlock,
                     SyntaxKind.SubBlock,
                     SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement
                    Return CType(CodeFunctionWithEventHandler.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement
                    Return CType(CodeFunctionDeclareDecl.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.PropertyBlock,
                     SyntaxKind.PropertyStatement
                    Return CType(CodeProperty.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.EventBlock,
                     SyntaxKind.EventStatement
                    Return CType(CodeEvent.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.NamespaceBlock
                    Return CType(CodeNamespace.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case SyntaxKind.ModifiedIdentifier,
                     SyntaxKind.EnumMemberDeclaration
                    Return CType(CodeVariable.Create(state, fileCodeModel, nodeKey, node.Kind), EnvDTE.CodeElement)
                Case Else
                    Throw New NotImplementedException()
            End Select
        End Function
 
        Public Overrides Function CreateUnknownCodeElement(state As CodeModelState, fileCodeModel As FileCodeModel, node As SyntaxNode) As EnvDTE.CodeElement
            Select Case node.Kind
                Case SyntaxKind.ClassBlock,
                     SyntaxKind.ModuleBlock
                    Return CType(CodeClass.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.StructureBlock
                    Return CType(CodeStruct.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.InterfaceBlock
                    Return CType(CodeInterface.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.EnumBlock
                    Return CType(CodeEnum.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    Return CType(CodeDelegate.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.ConstructorBlock,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.OperatorBlock,
                     SyntaxKind.SubBlock,
                     SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement
                    Return CType(CodeFunctionWithEventHandler.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement
                    Return CType(CodeFunctionDeclareDecl.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.PropertyBlock,
                     SyntaxKind.PropertyStatement
                    Return CType(CodeProperty.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.EventBlock,
                     SyntaxKind.EventStatement
                    Return CType(CodeEvent.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.NamespaceBlock
                    Return CType(CodeNamespace.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.ModifiedIdentifier,
                     SyntaxKind.EnumMemberDeclaration
                    Return CType(CodeVariable.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.SimpleImportsClause
                    Return CType(CodeImport.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.OptionStatement
                    Return CType(CodeOptionsStatement.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.InheritsStatement
                    Return CType(CodeInheritsStatement.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
                Case SyntaxKind.ImplementsStatement
                    Return CType(CodeImplementsStatement.CreateUnknown(state, fileCodeModel, node.Kind, GetName(node)), EnvDTE.CodeElement)
 
                Case Else
                    Throw New NotImplementedException()
            End Select
        End Function
 
        Public Overrides Function CreateUnknownRootNamespaceCodeElement(state As CodeModelState, fileCodeModel As FileCodeModel) As EnvDTE.CodeElement
            Dim compilation = CType(fileCodeModel.GetCompilation(), Compilation)
            Dim rootNamespace = DirectCast(compilation.Options, VisualBasicCompilationOptions).RootNamespace
            Return CType(CodeNamespace.CreateUnknown(state, fileCodeModel, SyntaxKind.NamespaceBlock, rootNamespace), EnvDTE.CodeElement)
        End Function
 
        Private Shared Function IsValidTypeRefKind(kind As EnvDTE.vsCMTypeRef) As Boolean
            Return kind = EnvDTE.vsCMTypeRef.vsCMTypeRefVoid OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefObject OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefBool OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefByte OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefShort OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefInt OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefLong OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefDecimal OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefFloat OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefDouble OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefChar OrElse
                   kind = EnvDTE.vsCMTypeRef.vsCMTypeRefString OrElse
                   kind = EnvDTE80.vsCMTypeRef2.vsCMTypeRefSByte OrElse
                   kind = EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedInt OrElse
                   kind = EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedLong OrElse
                   kind = EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedShort
        End Function
 
        Public Overrides Function CreateCodeTypeRef(state As CodeModelState, projectId As ProjectId, type As Object) As EnvDTE.CodeTypeRef
            Dim project = state.Workspace.CurrentSolution.GetProject(projectId)
            If project Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim compilation = project.GetCompilationAsync().Result
 
            If TypeOf type Is Byte OrElse
               TypeOf type Is Short OrElse
               TypeOf type Is Integer Then
 
                Dim typeRefKind = CType(type, EnvDTE.vsCMTypeRef)
                If Not IsValidTypeRefKind(typeRefKind) Then
                    Throw Exceptions.ThrowEInvalidArg()
                End If
 
                Dim specialType = GetSpecialType(typeRefKind)
                Return CodeTypeRef.Create(state, Nothing, projectId, compilation.GetSpecialType(specialType))
            End If
 
            Dim typeName As String
            Dim parent As Object = Nothing
 
            If TypeOf type Is String Then
                typeName = CStr(type)
            ElseIf TypeOf type Is EnvDTE.CodeType Then
                typeName = CType(type, EnvDTE.CodeType).FullName
                parent = type
            Else
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim typeSymbol = GetTypeSymbolFromFullName(typeName, compilation)
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Return CodeTypeRef.Create(state, parent, projectId, typeSymbol)
        End Function
 
        Public Overrides Function GetTypeKindForCodeTypeRef(typeSymbol As ITypeSymbol) As EnvDTE.vsCMTypeRef
            ' Rough translation of CodeModelSymbol::GetTypeKind from vb\Language\VsPackage\CodeModelHelpers.cpp
 
            If typeSymbol.SpecialType = SpecialType.System_Void Then
                Return EnvDTE.vsCMTypeRef.vsCMTypeRefVoid
            End If
 
            If typeSymbol.TypeKind = TypeKind.Array Then
                Return EnvDTE.vsCMTypeRef.vsCMTypeRefArray
            End If
 
            If typeSymbol.TypeKind = TypeKind.Pointer Then
                typeSymbol = DirectCast(typeSymbol, IPointerTypeSymbol).PointedAtType
            End If
 
            If typeSymbol IsNot Nothing AndAlso Not typeSymbol.TypeKind = TypeKind.Error Then
                If typeSymbol.SpecialType = SpecialType.System_Object Then
                    Return EnvDTE.vsCMTypeRef.vsCMTypeRefObject
                End If
 
                If typeSymbol.TypeKind = TypeKind.Enum Then
                    Return EnvDTE.vsCMTypeRef.vsCMTypeRefCodeType
                End If
 
                Select Case typeSymbol.SpecialType
                    Case SpecialType.System_Boolean
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefBool
                    Case SpecialType.System_SByte
                        Return CType(EnvDTE80.vsCMTypeRef2.vsCMTypeRefSByte, EnvDTE.vsCMTypeRef)
                    Case SpecialType.System_Byte
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefByte
                    Case SpecialType.System_Int16
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefShort
                    Case SpecialType.System_UInt16
                        Return CType(EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedShort, EnvDTE.vsCMTypeRef)
                    Case SpecialType.System_Int32
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefInt
                    Case SpecialType.System_UInt32
                        Return CType(EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedInt, EnvDTE.vsCMTypeRef)
                    Case SpecialType.System_Int64
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefLong
                    Case SpecialType.System_UInt64
                        Return CType(EnvDTE80.vsCMTypeRef2.vsCMTypeRefUnsignedLong, EnvDTE.vsCMTypeRef)
                    Case SpecialType.System_Decimal
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefDecimal
                    Case SpecialType.System_Single
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefFloat
                    Case SpecialType.System_Double
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefDouble
                    Case SpecialType.System_Char
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefChar
                    Case SpecialType.System_String
                        Return EnvDTE.vsCMTypeRef.vsCMTypeRefString
                End Select
 
                If typeSymbol.TypeKind = TypeKind.Pointer Then
                    Return EnvDTE.vsCMTypeRef.vsCMTypeRefPointer
                End If
 
                If typeSymbol.TypeKind = TypeKind.TypeParameter Then
                    Return EnvDTE.vsCMTypeRef.vsCMTypeRefOther
                End If
 
                Return EnvDTE.vsCMTypeRef.vsCMTypeRefCodeType
            End If
 
            Return EnvDTE.vsCMTypeRef.vsCMTypeRefOther
        End Function
 
        Public Overrides Function GetAsFullNameForCodeTypeRef(typeSymbol As ITypeSymbol) As String
            Return typeSymbol.ToDisplayString(s_codeTypeRefAsFullNameFormat)
        End Function
 
        Public Overrides Function GetAsStringForCodeTypeRef(typeSymbol As ITypeSymbol) As String
            Return typeSymbol.ToDisplayString(s_codeTypeRefAsStringFormat)
        End Function
 
        Public Overrides Function IsParameterNode(node As SyntaxNode) As Boolean
            Return TypeOf node Is ParameterSyntax
        End Function
 
        Public Overrides Function IsAttributeNode(node As SyntaxNode) As Boolean
            Return TypeOf node Is AttributeSyntax
        End Function
 
        Public Overrides Function IsAttributeArgumentNode(node As SyntaxNode) As Boolean
            Return TypeOf node Is SimpleArgumentSyntax OrElse
                   TypeOf node Is OmittedArgumentSyntax
        End Function
 
        Public Overrides Function IsOptionNode(node As SyntaxNode) As Boolean
            Return TypeOf node Is OptionStatementSyntax
        End Function
 
        Public Overrides Function IsImportNode(node As SyntaxNode) As Boolean
            Return TypeOf node Is SimpleImportsClauseSyntax
        End Function
 
        Public Overrides Function GetUnescapedName(name As String) As String
            Return If(name IsNot Nothing AndAlso name.Length > 2 AndAlso name.StartsWith("[", StringComparison.Ordinal) AndAlso name.EndsWith("]", StringComparison.Ordinal),
                      name.Substring(1, name.Length - 2),
                      name)
        End Function
 
        Private Shared Function GetNormalizedName(node As SyntaxNode) As String
            Dim nameBuilder = New StringBuilder()
 
            Dim token = node.GetFirstToken(includeSkipped:=True)
            While True
                nameBuilder.Append(token.ToString())
 
                Dim nextToken = token.GetNextToken(includeSkipped:=True)
                If Not nextToken.IsDescendantOf(node) Then
                    Exit While
                End If
 
                If (token.IsKeyword() OrElse token.Kind = SyntaxKind.IdentifierToken) AndAlso
                   (nextToken.IsKeyword() OrElse nextToken.Kind = SyntaxKind.IdentifierToken) Then
 
                    nameBuilder.Append(" "c)
                End If
 
                token = nextToken
            End While
 
            Return nameBuilder.ToString().Trim()
        End Function
 
        Public Overrides Function GetName(node As SyntaxNode) As String
            If node Is Nothing Then
                Throw New ArgumentNullException(NameOf(node))
            End If
 
            Debug.Assert(TypeOf node Is SyntaxNode)
            Debug.Assert(IsNameableNode(node))
 
            Select Case node.Kind
                Case SyntaxKind.Attribute
                    Return GetNormalizedName(DirectCast(node, AttributeSyntax).Name)
                Case SyntaxKind.ClassBlock,
                     SyntaxKind.InterfaceBlock,
                     SyntaxKind.ModuleBlock,
                     SyntaxKind.StructureBlock
                    Return DirectCast(node, TypeBlockSyntax).BlockStatement.Identifier.ToString()
                Case SyntaxKind.EnumBlock
                    Return DirectCast(node, EnumBlockSyntax).EnumStatement.Identifier.ToString()
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    Return DirectCast(node, DelegateStatementSyntax).Identifier.ToString()
                Case SyntaxKind.NamespaceBlock
                    Return DirectCast(node, NamespaceBlockSyntax).NamespaceStatement.Name.ToString()
                Case SyntaxKind.SubBlock,
                     SyntaxKind.FunctionBlock
                    Dim methodBlock = DirectCast(node, MethodBlockSyntax)
                    Return methodBlock.SubOrFunctionStatement.Identifier.ToString()
                Case SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement
                    Return DirectCast(node, MethodStatementSyntax).Identifier.ToString()
                Case SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement
                    Return DirectCast(node, DeclareStatementSyntax).Identifier.ToString()
                Case SyntaxKind.ConstructorBlock
                    Dim methodBlock = DirectCast(node, ConstructorBlockSyntax)
                    Return methodBlock.SubNewStatement.NewKeyword.ToString()
                Case SyntaxKind.OperatorBlock
                    Dim operatorBlock = DirectCast(node, OperatorBlockSyntax)
                    Return operatorBlock.OperatorStatement.OperatorToken.ToString()
                Case SyntaxKind.PropertyBlock
                    Dim propertyBlock = DirectCast(node, PropertyBlockSyntax)
                    Return propertyBlock.PropertyStatement.Identifier.ToString()
                Case SyntaxKind.PropertyStatement
                    Return DirectCast(node, PropertyStatementSyntax).Identifier.ToString()
                Case SyntaxKind.EventBlock
                    Return DirectCast(node, EventBlockSyntax).EventStatement.Identifier.ToString()
                Case SyntaxKind.EventStatement
                    Return DirectCast(node, EventStatementSyntax).Identifier.ToString()
                Case SyntaxKind.ModifiedIdentifier
                    Return DirectCast(node, ModifiedIdentifierSyntax).Identifier.ToString()
                Case SyntaxKind.EnumMemberDeclaration
                    Return DirectCast(node, EnumMemberDeclarationSyntax).Identifier.ToString()
                Case SyntaxKind.SimpleArgument
                    Dim simpleArgument = DirectCast(node, SimpleArgumentSyntax)
                    Return If(simpleArgument.IsNamed,
                              simpleArgument.NameColonEquals.Name.ToString(),
                              String.Empty)
                Case SyntaxKind.OmittedArgument
                    Return String.Empty
                Case SyntaxKind.Parameter
                    Return GetParameterName(node)
                Case SyntaxKind.OptionStatement
                    Return GetNormalizedName(node)
                Case SyntaxKind.SimpleImportsClause
                    Return GetNormalizedName(DirectCast(node, ImportsClauseSyntax).GetName())
                Case SyntaxKind.InheritsStatement
                    Return DirectCast(node, InheritsStatementSyntax).InheritsKeyword.ToString()
                Case SyntaxKind.ImplementsStatement
                    Return DirectCast(node, ImplementsStatementSyntax).ImplementsKeyword.ToString()
                Case Else
                    Debug.Fail(String.Format("Invalid node kind: {0}", node.Kind))
                    Throw New ArgumentException()
            End Select
        End Function
 
        Public Overrides Function SetName(node As SyntaxNode, name As String) As SyntaxNode
            If node Is Nothing Then
                Throw New ArgumentNullException(NameOf(node))
            End If
 
            ' In all cases, the resulting syntax for the new name has elastic trivia attached,
            ' whether via this call to SyntaxFactory.Identifier or via explicitly added elastic
            ' markers.
            Dim identifier As SyntaxToken = SyntaxFactory.Identifier(name)
 
            Select Case node.Kind
                Case SyntaxKind.Attribute
                    Return DirectCast(node, AttributeSyntax).WithName(
                        SyntaxFactory.ParseTypeName(name) _
                            .WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)) _
                            .WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)))
                Case SyntaxKind.ClassStatement
                    Return DirectCast(node, ClassStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.InterfaceStatement
                    Return DirectCast(node, InterfaceStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.ModuleStatement
                    Return DirectCast(node, ModuleStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.StructureStatement
                    Return DirectCast(node, StructureStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.EnumStatement
                    Return DirectCast(node, EnumStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    Return DirectCast(node, DelegateStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.NamespaceStatement
                    Return DirectCast(node, NamespaceStatementSyntax).WithName(
                        SyntaxFactory.ParseName(name) _
                            .WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)) _
                            .WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)))
                Case SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement,
                     SyntaxKind.SubNewStatement
                    Return DirectCast(node, MethodStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareFunctionStatement
                    Return DirectCast(node, DeclareStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.PropertyStatement
                    Return DirectCast(node, PropertyStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.EventStatement
                    Return DirectCast(node, EventStatementSyntax).WithIdentifier(identifier)
                Case SyntaxKind.ModifiedIdentifier
                    Return DirectCast(node, ModifiedIdentifierSyntax).WithIdentifier(identifier)
                Case SyntaxKind.SimpleArgument
                    Return DirectCast(node, SimpleArgumentSyntax).WithNameColonEquals(SyntaxFactory.NameColonEquals(SyntaxFactory.IdentifierName(name)))
                Case Else
                    Debug.Fail("Invalid node kind: " & CType(node.Kind, SyntaxKind))
                    Throw Exceptions.ThrowEFail()
            End Select
 
        End Function
 
        Public Overrides Function GetNodeWithName(node As SyntaxNode) As SyntaxNode
            If node Is Nothing Then
                Throw New ArgumentNullException(NameOf(node))
            End If
 
            If node.Kind = SyntaxKind.OperatorBlock Then
                Throw Exceptions.ThrowEFail
            End If
 
            Debug.Assert(IsNameableNode(node))
 
            Select Case node.Kind
                Case SyntaxKind.Attribute
                    Return node
                Case SyntaxKind.ClassBlock,
                     SyntaxKind.InterfaceBlock,
                     SyntaxKind.ModuleBlock,
                     SyntaxKind.StructureBlock
                    Return DirectCast(node, TypeBlockSyntax).BlockStatement
                Case SyntaxKind.EnumBlock
                    Return DirectCast(node, EnumBlockSyntax).EnumStatement
                Case SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement
                    Return node
                Case SyntaxKind.NamespaceBlock
                    Return DirectCast(node, NamespaceBlockSyntax).NamespaceStatement
                Case SyntaxKind.SubBlock,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.ConstructorBlock
                    Return DirectCast(node, MethodBlockBaseSyntax).BlockStatement
                Case SyntaxKind.PropertyBlock
                    Return DirectCast(node, PropertyBlockSyntax).PropertyStatement
                Case SyntaxKind.EventBlock
                    Return DirectCast(node, EventBlockSyntax).EventStatement
                Case SyntaxKind.ModifiedIdentifier
                    Return node
                Case SyntaxKind.SimpleArgument
                    Dim simpleArgument = DirectCast(node, SimpleArgumentSyntax)
 
                    Return If(simpleArgument.IsNamed, simpleArgument.NameColonEquals.Name, node)
                Case SyntaxKind.SubStatement,
                     SyntaxKind.FunctionStatement,
                     SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement
                    Return node
                Case SyntaxKind.EventStatement
                    Return node
                Case Else
                    Debug.Fail("Invalid node kind: " & CType(node.Kind, SyntaxKind))
                    Throw New ArgumentException()
            End Select
        End Function
 
        Public Overrides Function GetFullName(node As SyntaxNode, semanticModel As SemanticModel) As String
            If node.Kind = SyntaxKind.SimpleImportsClause Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim symbol = If(TypeOf node Is AttributeSyntax,
                            semanticModel.GetTypeInfo(node).Type,
                            semanticModel.GetDeclaredSymbol(node))
 
            Return GetExternalSymbolFullName(symbol)
        End Function
 
        Public Overrides Function IsExpressionBodiedProperty(node As SyntaxNode) As Boolean
            Return False
        End Function
 
        Public Overrides Function TryGetAutoPropertyExpressionBody(parentNode As SyntaxNode, ByRef accessorNode As SyntaxNode) As Boolean
            Return False
        End Function
 
        Public Overrides Function IsAccessorNode(node As SyntaxNode) As Boolean
            Select Case node.Kind
                Case SyntaxKind.GetAccessorBlock,
                     SyntaxKind.SetAccessorBlock,
                     SyntaxKind.AddHandlerAccessorBlock,
                     SyntaxKind.RemoveHandlerAccessorBlock,
                     SyntaxKind.RaiseEventAccessorBlock
 
                    Return True
            End Select
 
            Return False
        End Function
 
        Public Overrides Function GetAccessorKind(node As SyntaxNode) As MethodKind
            Select Case node.Kind
                Case SyntaxKind.GetAccessorBlock
                    Return MethodKind.PropertyGet
                Case SyntaxKind.SetAccessorBlock
                    Return MethodKind.PropertySet
                Case SyntaxKind.AddHandlerAccessorBlock
                    Return MethodKind.EventAdd
                Case SyntaxKind.RemoveHandlerAccessorBlock
                    Return MethodKind.EventRemove
                Case SyntaxKind.RaiseEventAccessorBlock
                    Return MethodKind.EventRaise
                Case Else
                    Throw Exceptions.ThrowEUnexpected()
            End Select
        End Function
 
        Private Overloads Shared Function GetAccessorKind(methodKind As MethodKind) As SyntaxKind
            Select Case methodKind
                Case MethodKind.PropertyGet
                    Return SyntaxKind.GetAccessorBlock
                Case MethodKind.PropertySet
                    Return SyntaxKind.SetAccessorBlock
                Case MethodKind.EventAdd
                    Return SyntaxKind.AddHandlerAccessorBlock
                Case MethodKind.EventRemove
                    Return SyntaxKind.RemoveHandlerAccessorBlock
                Case MethodKind.EventRaise
                    Return SyntaxKind.RaiseEventAccessorBlock
                Case Else
                    Throw Exceptions.ThrowEUnexpected()
            End Select
        End Function
 
        Private Shared Function GetAccessors(node As SyntaxNode) As SyntaxList(Of AccessorBlockSyntax)
            Select Case node.Kind()
                Case SyntaxKind.PropertyBlock
                    Return DirectCast(node, PropertyBlockSyntax).Accessors
                Case SyntaxKind.EventBlock
                    Return DirectCast(node, EventBlockSyntax).Accessors
                Case Else
                    Return Nothing
            End Select
        End Function
 
        Public Overrides Function TryGetAccessorNode(parentNode As SyntaxNode, kind As MethodKind, ByRef accessorNode As SyntaxNode) As Boolean
            Dim accessorKind = GetAccessorKind(kind)
            For Each accessor In GetAccessors(parentNode)
                If accessor.Kind = accessorKind Then
                    accessorNode = accessor
                    Return True
                End If
            Next
 
            accessorNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetParameterNode(parentNode As SyntaxNode, name As String, ByRef parameterNode As SyntaxNode) As Boolean
            For Each parameter As ParameterSyntax In GetParameterNodes(parentNode)
                Dim parameterName = GetNameFromParameter(parameter)
                If String.Equals(parameterName, name, StringComparison.OrdinalIgnoreCase) Then
                    parameterNode = parameter
                    Return True
                End If
            Next
 
            parameterNode = Nothing
            Return False
        End Function
 
        Private Overloads Shared Function GetParameterNodes(methodStatement As MethodBaseSyntax) As IEnumerable(Of ParameterSyntax)
            Return If(methodStatement.ParameterList IsNot Nothing,
                      methodStatement.ParameterList.Parameters,
                      SpecializedCollections.EmptyEnumerable(Of ParameterSyntax))
        End Function
 
        Public Overloads Overrides Function GetParameterNodes(parent As SyntaxNode) As IEnumerable(Of SyntaxNode)
            If TypeOf parent Is MethodBaseSyntax Then
                Return GetParameterNodes(DirectCast(parent, MethodBaseSyntax))
            ElseIf TypeOf parent Is MethodBlockBaseSyntax Then
                Return GetParameterNodes(DirectCast(parent, MethodBlockBaseSyntax).BlockStatement)
            ElseIf TypeOf parent Is PropertyBlockSyntax Then
                Return GetParameterNodes(DirectCast(parent, PropertyBlockSyntax).PropertyStatement)
            End If
 
            Return SpecializedCollections.EmptyEnumerable(Of ParameterSyntax)()
        End Function
 
        Public Overrides Function TryGetImportNode(parentNode As SyntaxNode, dottedName As String, ByRef importNode As SyntaxNode) As Boolean
            For Each node In GetImportNodes(parentNode)
                If GetImportNamespaceOrType(node) = dottedName Then
                    importNode = node
                    Return True
                End If
            Next
 
            importNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetOptionNode(parentNode As SyntaxNode, name As String, ordinal As Integer, ByRef optionNode As SyntaxNode) As Boolean
            Dim count = -1
            For Each [option] As OptionStatementSyntax In GetOptionNodes(parentNode)
                If [option].ToString() = name Then
                    count += 1
                    If count = ordinal Then
                        optionNode = [option]
                        Return True
                    End If
                End If
            Next
 
            optionNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetInheritsNode(parentNode As SyntaxNode, name As String, ordinal As Integer, ByRef inheritsNode As SyntaxNode) As Boolean
            Dim count = -1
            For Each [inherits] As InheritsStatementSyntax In GetInheritsNodes(parentNode)
                If [inherits].Types.ToString() = name Then
                    count += 1
                    If count = ordinal Then
                        inheritsNode = [inherits]
                        Return True
                    End If
                End If
            Next
 
            inheritsNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetImplementsNode(parentNode As SyntaxNode, name As String, ordinal As Integer, ByRef implementsNode As SyntaxNode) As Boolean
            Dim count = -1
            For Each [implements] As ImplementsStatementSyntax In GetImplementsNodes(parentNode)
                If [implements].Types.ToString() = name Then
                    count += 1
                    If count = ordinal Then
                        implementsNode = [implements]
                        Return True
                    End If
                End If
            Next
 
            implementsNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetAttributeNode(parentNode As SyntaxNode, name As String, ordinal As Integer, ByRef attributeNode As SyntaxNode) As Boolean
            Dim count = -1
            For Each attribute As AttributeSyntax In GetAttributeNodes(parentNode)
                If attribute.Name.ToString() = name Then
                    count += 1
                    If count = ordinal Then
                        attributeNode = attribute
                        Return True
                    End If
                End If
            Next
 
            attributeNode = Nothing
            Return False
        End Function
 
        Public Overrides Function TryGetAttributeArgumentNode(attributeNode As SyntaxNode, index As Integer, ByRef attributeArgumentNode As SyntaxNode) As Boolean
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            Dim attribute = DirectCast(attributeNode, AttributeSyntax)
            If attribute.ArgumentList IsNot Nothing AndAlso
                attribute.ArgumentList.Arguments.Count > index Then
 
                attributeArgumentNode = attribute.ArgumentList.Arguments(index)
                Return True
            End If
 
            attributeArgumentNode = Nothing
            Return False
        End Function
 
        Private Shared Function DeleteMember(document As Document, node As SyntaxNode) As Document
            Dim text = document.GetTextSynchronously(CancellationToken.None)
 
            Dim deletionEnd = node.FullSpan.End
            Dim deletionStart = node.SpanStart
            Dim contiguousEndOfLines = 0
 
            For Each trivia In node.GetLeadingTrivia().Reverse()
                If trivia.IsDirective Then
                    Exit For
                End If
 
                If trivia.Kind = SyntaxKind.EndOfLineTrivia Then
                    If contiguousEndOfLines > 0 Then
                        Exit For
                    Else
                        contiguousEndOfLines += 1
                    End If
                ElseIf trivia.Kind <> SyntaxKind.WhitespaceTrivia Then
                    contiguousEndOfLines = 0
                End If
 
                deletionStart = trivia.FullSpan.Start
            Next
 
            text = text.Replace(TextSpan.FromBounds(deletionStart, deletionEnd), String.Empty)
 
            Return document.WithText(text)
        End Function
 
        Public Overrides Function Delete(document As Document, node As SyntaxNode) As Document
            Select Case node.Kind
                Case SyntaxKind.Attribute
                    Return Delete(document, DirectCast(node, AttributeSyntax))
                Case SyntaxKind.SimpleArgument
                    Return Delete(document, DirectCast(node, ArgumentSyntax))
                Case SyntaxKind.Parameter
                    Return Delete(document, DirectCast(node, ParameterSyntax))
                Case SyntaxKind.ModifiedIdentifier
                    Return Delete(document, DirectCast(node, ModifiedIdentifierSyntax))
                Case SyntaxKind.VariableDeclarator
                    Return Delete(document, DirectCast(node, VariableDeclaratorSyntax))
                Case Else
                    Return DeleteMember(document, node)
            End Select
        End Function
 
        Private Overloads Function Delete(document As Document, node As ModifiedIdentifierSyntax) As Document
            Dim declarator = node.FirstAncestorOrSelf(Of VariableDeclaratorSyntax)()
 
            ' If this is the only name in declarator, then delete the entire
            ' declarator.
            If declarator.Names.Count = 1 Then
                Return Delete(document, declarator)
            Else
                Dim newDeclarator = declarator.RemoveNode(node, SyntaxRemoveOptions.KeepEndOfLine).WithAdditionalAnnotations(Formatter.Annotation)
                Return document.ReplaceNodeSynchronously(declarator, newDeclarator, CancellationToken.None)
            End If
        End Function
 
        Private Overloads Function Delete(document As Document, node As VariableDeclaratorSyntax) As Document
            Dim declaration = node.FirstAncestorOrSelf(Of FieldDeclarationSyntax)()
 
            ' If this is the only declarator in the declaration, then delete
            ' the entire declarator.
            If declaration.Declarators.Count = 1 Then
                Return Delete(document, declaration)
            Else
                Dim newDeclaration = declaration.RemoveNode(node, SyntaxRemoveOptions.KeepEndOfLine).WithAdditionalAnnotations(Formatter.Annotation)
                Return document.ReplaceNodeSynchronously(declaration, newDeclaration, CancellationToken.None)
            End If
        End Function
 
        Private Overloads Shared Function Delete(document As Document, node As AttributeSyntax) As Document
            Dim attributeList = node.FirstAncestorOrSelf(Of AttributeListSyntax)()
 
            ' If we don't have anything left, then just delete the whole attribute list.
            ' Keep all leading trivia, but delete all trailing trivia.
            If attributeList.Attributes.Count = 1 Then
                Dim spanStart = attributeList.SpanStart
                Dim spanEnd = attributeList.FullSpan.End
 
                Dim text = document.GetTextSynchronously(CancellationToken.None)
 
                text = text.Replace(TextSpan.FromBounds(spanStart, spanEnd), String.Empty)
 
                Return document.WithText(text)
            Else
                Dim newAttributeList = attributeList.RemoveNode(node, SyntaxRemoveOptions.KeepEndOfLine)
 
                Return document.ReplaceNodeSynchronously(attributeList, newAttributeList, CancellationToken.None)
            End If
        End Function
 
        Private Overloads Shared Function Delete(document As Document, node As ArgumentSyntax) As Document
            Dim argumentList = node.FirstAncestorOrSelf(Of ArgumentListSyntax)()
            Dim newArgumentList = argumentList.RemoveNode(node, SyntaxRemoveOptions.KeepEndOfLine).WithAdditionalAnnotations(Formatter.Annotation)
 
            Return document.ReplaceNodeSynchronously(argumentList, newArgumentList, CancellationToken.None)
        End Function
 
        Private Overloads Shared Function Delete(document As Document, node As ParameterSyntax) As Document
            Dim parameterList = node.FirstAncestorOrSelf(Of ParameterListSyntax)()
            Dim newParameterList = parameterList.RemoveNode(node, SyntaxRemoveOptions.KeepEndOfLine).WithAdditionalAnnotations(Formatter.Annotation)
 
            Return document.ReplaceNodeSynchronously(parameterList, newParameterList, CancellationToken.None)
        End Function
 
        Public Overrides Function IsValidExternalSymbol(symbol As ISymbol) As Boolean
            Dim methodSymbol = TryCast(symbol, IMethodSymbol)
            If methodSymbol IsNot Nothing Then
                If methodSymbol.MethodKind = MethodKind.PropertyGet OrElse
                   methodSymbol.MethodKind = MethodKind.PropertySet OrElse
                   methodSymbol.MethodKind = MethodKind.EventAdd OrElse
                   methodSymbol.MethodKind = MethodKind.EventRemove OrElse
                   methodSymbol.MethodKind = MethodKind.EventRaise Then
 
                    Return False
                End If
            End If
 
            Dim fieldSymbol = TryCast(symbol, IFieldSymbol)
            If fieldSymbol IsNot Nothing Then
                Dim propertySymbol = TryCast(fieldSymbol.AssociatedSymbol, IPropertySymbol)
                If propertySymbol?.IsWithEvents Then
                    Return True
                End If
            End If
 
            Return symbol.DeclaredAccessibility = Accessibility.Public OrElse
                   symbol.DeclaredAccessibility = Accessibility.Protected OrElse
                   symbol.DeclaredAccessibility = Accessibility.ProtectedOrFriend OrElse
                   symbol.DeclaredAccessibility = Accessibility.ProtectedAndFriend OrElse
                   symbol.DeclaredAccessibility = Accessibility.Friend
        End Function
 
        Public Overrides Function GetExternalSymbolName(symbol As ISymbol) As String
            If symbol Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Return symbol.ToDisplayString(s_externalNameFormat)
        End Function
 
        Public Overrides Function GetExternalSymbolFullName(symbol As ISymbol) As String
            If symbol Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Return symbol.ToDisplayString(s_externalfullNameFormat)
        End Function
 
        Public Overrides Function GetAccess(symbol As ISymbol) As EnvDTE.vsCMAccess
            Debug.Assert(symbol IsNot Nothing)
 
            Dim access As EnvDTE.vsCMAccess = 0
 
            Select Case symbol.DeclaredAccessibility
                Case Accessibility.Private
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessPrivate
                Case Accessibility.Protected
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessProtected
                Case Accessibility.Internal, Accessibility.Friend
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessProject
                Case Accessibility.ProtectedOrInternal, Accessibility.ProtectedOrFriend
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected
                Case Accessibility.ProtectedAndInternal, Accessibility.ProtectedAndFriend
                    ' there is no appropriate mapping for private protected in EnvDTE.vsCMAccess
                    ' See https://github.com/dotnet/roslyn/issues/22406
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessProject
                Case Accessibility.Public
                    access = access Or EnvDTE.vsCMAccess.vsCMAccessPublic
                Case Else
                    Throw Exceptions.ThrowEFail()
            End Select
 
            If TryCast(symbol, IPropertySymbol)?.IsWithEvents Then
                access = access Or EnvDTE.vsCMAccess.vsCMAccessWithEvents
            End If
 
            Return access
        End Function
 
        Public Overrides Function GetAccess(node As SyntaxNode) As EnvDTE.vsCMAccess
            Dim member = TryCast(Me.GetNodeWithModifiers(node), StatementSyntax)
 
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
 
            Dim access As EnvDTE.vsCMAccess
 
            If (flags And ModifierFlags.Public) <> 0 Then
                access = EnvDTE.vsCMAccess.vsCMAccessPublic
            ElseIf (flags And ModifierFlags.Protected) <> 0 AndAlso
                   (flags And ModifierFlags.Friend) <> 0 Then
                access = EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected
            ElseIf (flags And ModifierFlags.Friend) <> 0 Then
                access = EnvDTE.vsCMAccess.vsCMAccessProject
            ElseIf (flags And ModifierFlags.Protected) <> 0 Then
                access = EnvDTE.vsCMAccess.vsCMAccessProtected
            ElseIf (flags And ModifierFlags.Private) <> 0 Then
                access = EnvDTE.vsCMAccess.vsCMAccessPrivate
            Else
                ' The code does not specify the accessibility, so we need to
                ' determine the default accessibility
                access = GetDefaultAccessibility(member)
            End If
 
            If (flags And ModifierFlags.WithEvents) <> 0 Then
                access = access Or EnvDTE.vsCMAccess.vsCMAccessWithEvents
            End If
 
            Return access
        End Function
 
        Public Overrides Function GetNodeWithModifiers(node As SyntaxNode) As SyntaxNode
            Return If(TypeOf node Is ModifiedIdentifierSyntax,
                      node.GetAncestor(Of DeclarationStatementSyntax)(),
                      node)
        End Function
 
        Public Overrides Function GetNodeWithType(node As SyntaxNode) As SyntaxNode
            Return If(TypeOf node Is ModifiedIdentifierSyntax,
                      node.GetAncestor(Of VariableDeclaratorSyntax)(),
                      node)
        End Function
 
        Public Overrides Function GetNodeWithInitializer(node As SyntaxNode) As SyntaxNode
            Return If(TypeOf node Is ModifiedIdentifierSyntax,
                      node.GetAncestor(Of VariableDeclaratorSyntax)(),
                      node)
        End Function
 
        Public Overrides Function SetAccess(node As SyntaxNode, newAccess As EnvDTE.vsCMAccess) As SyntaxNode
            Dim member = TryCast(node, StatementSyntax)
 
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If member.Parent.Kind = SyntaxKind.InterfaceBlock OrElse
                member.Parent.Kind = SyntaxKind.EnumBlock Then
                If newAccess = EnvDTE.vsCMAccess.vsCMAccessDefault OrElse
                    newAccess = EnvDTE.vsCMAccess.vsCMAccessPublic Then
                    Return node
                Else
                    Throw Exceptions.ThrowEInvalidArg()
                End If
            End If
 
            If TypeOf member Is TypeBlockSyntax OrElse
                TypeOf member Is EnumBlockSyntax Then
                If Not TypeOf member.Parent Is TypeBlockSyntax AndAlso
                    (newAccess = EnvDTE.vsCMAccess.vsCMAccessPrivate OrElse
                     newAccess = EnvDTE.vsCMAccess.vsCMAccessProtected OrElse
                     newAccess = EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected) Then
                    Throw Exceptions.ThrowEInvalidArg()
                End If
            End If
 
            Dim flags = member.GetModifierFlags() And Not (ModifierFlags.AccessModifierMask Or ModifierFlags.Dim Or ModifierFlags.WithEvents)
 
            If (newAccess And EnvDTE.vsCMAccess.vsCMAccessPrivate) <> 0 Then
                flags = flags Or ModifierFlags.Private
            ElseIf (newAccess And EnvDTE.vsCMAccess.vsCMAccessProtected) <> 0 Then
                flags = flags Or ModifierFlags.Protected
 
                If (newAccess And EnvDTE.vsCMAccess.vsCMAccessProject) <> 0 Then
                    flags = flags Or ModifierFlags.Friend
                End If
            ElseIf (newAccess And EnvDTE.vsCMAccess.vsCMAccessPublic) <> 0 Then
                flags = flags Or ModifierFlags.Public
            ElseIf (newAccess And EnvDTE.vsCMAccess.vsCMAccessProject) <> 0 Then
                flags = flags Or ModifierFlags.Friend
            ElseIf (newAccess And EnvDTE.vsCMAccess.vsCMAccessProjectOrProtected) <> 0 Then
                flags = flags Or ModifierFlags.Protected Or ModifierFlags.Friend
            ElseIf (newAccess And EnvDTE.vsCMAccess.vsCMAccessDefault) <> 0 Then
                ' No change
            End If
 
            If (newAccess And EnvDTE.vsCMAccess.vsCMAccessWithEvents) <> 0 Then
                flags = flags Or ModifierFlags.WithEvents
            End If
 
            If flags = 0 AndAlso member.IsKind(SyntaxKind.FieldDeclaration) Then
                flags = flags Or ModifierFlags.Dim
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Private Overloads Shared Function GetDefaultAccessibility(node As SyntaxNode) As EnvDTE.vsCMAccess
            If node.HasAncestor(Of StructureBlockSyntax)() Then
                Return EnvDTE.vsCMAccess.vsCMAccessPublic
            End If
 
            If TypeOf node Is FieldDeclarationSyntax Then
                Return EnvDTE.vsCMAccess.vsCMAccessPrivate
            ElseIf (TypeOf node Is MethodBlockBaseSyntax OrElse
                    TypeOf node Is TypeBlockSyntax OrElse
                    TypeOf node Is EnumBlockSyntax OrElse
                    TypeOf node Is MethodBaseSyntax OrElse
                    TypeOf node Is EnumMemberDeclarationSyntax) Then
                Return EnvDTE.vsCMAccess.vsCMAccessPublic
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Protected Overrides Function GetAttributeIndexInContainer(containerNode As SyntaxNode, predicate As Func(Of SyntaxNode, Boolean)) As Integer
            Dim attributes = GetAttributeNodes(containerNode).ToArray()
 
            Dim index = 0
            While index < attributes.Length
                Dim attribute = DirectCast(attributes(index), AttributeSyntax)
 
                If predicate(attribute) Then
                    Dim attributeBlock = DirectCast(attribute.Parent, AttributeListSyntax)
 
                    ' If this attribute is part of a block with multiple attributes,
                    ' make sure to return the index of the last attribute in the block.
                    If attributeBlock.Attributes.Count > 1 Then
                        Dim indexOfAttributeInBlock = attributeBlock.Attributes.IndexOf(attribute)
                        Return index + (attributeBlock.Attributes.Count - indexOfAttributeInBlock)
                    End If
 
                    Return index + 1
                End If
 
                index += 1
            End While
 
            Return -1
        End Function
 
        Protected Overrides Function GetAttributeArgumentIndexInContainer(containerNode As SyntaxNode, predicate As Func(Of SyntaxNode, Boolean)) As Integer
            Dim attributeArguments = GetAttributeArgumentNodes(containerNode).ToArray()
 
            Dim index = 0
            While index < attributeArguments.Length
                If predicate(attributeArguments(index)) Then
                    Return index + 1
                End If
 
                index += 1
            End While
 
            Return -1
        End Function
 
        Protected Overrides Function GetImportIndexInContainer(containerNode As SyntaxNode, predicate As Func(Of SyntaxNode, Boolean)) As Integer
            Dim importsClauses = GetImportNodes(containerNode).ToArray()
 
            Dim index = 0
            While index < importsClauses.Length
                Dim importsClause = DirectCast(importsClauses(index), ImportsClauseSyntax)
 
                If predicate(importsClause) Then
                    Dim importsStatement = DirectCast(importsClause.Parent, ImportsStatementSyntax)
 
                    ' If this attribute is part of a block with multiple attributes,
                    ' make sure to return the index of the last attribute in the block.
                    If importsStatement.ImportsClauses.Count > 1 Then
                        Dim indexOfImportClauseInStatement = importsStatement.ImportsClauses.IndexOf(importsClause)
                        Return index + (importsStatement.ImportsClauses.Count - indexOfImportClauseInStatement)
                    End If
 
                    Return index + 1
                End If
 
                index += 1
            End While
 
            Return -1
        End Function
 
        Protected Overrides Function GetParameterIndexInContainer(containerNode As SyntaxNode, predicate As Func(Of SyntaxNode, Boolean)) As Integer
            Dim parameters = GetParameterNodes(containerNode).ToArray()
 
            For index = 0 To parameters.Length - 1
                If predicate(parameters(index)) Then
                    Return index + 1
                End If
            Next
 
            Return -1
        End Function
 
        Protected Overrides Function GetMemberIndexInContainer(containerNode As SyntaxNode, predicate As Func(Of SyntaxNode, Boolean)) As Integer
            Dim members = GetLogicalMemberNodes(containerNode).ToArray()
 
            Dim index = 0
            While index < members.Length
                Dim member = members(index)
                If predicate(member) Then
                    ' Special case: if a modified identifier was specified, make sure we return the index
                    ' of the last modified identifier of the last variable declarator in the parenting field
                    ' declaration.
                    If member.Kind = SyntaxKind.ModifiedIdentifier Then
                        Dim modifiedIdentifier = DirectCast(member, ModifiedIdentifierSyntax)
                        Dim variableDeclarator = DirectCast(member.Parent, VariableDeclaratorSyntax)
                        Dim fieldDeclaration = DirectCast(variableDeclarator.Parent, FieldDeclarationSyntax)
 
                        Dim indexOfNameInDeclarator = variableDeclarator.Names.IndexOf(modifiedIdentifier)
                        Dim indexOfDeclaratorInField = fieldDeclaration.Declarators.IndexOf(variableDeclarator)
 
                        Dim indexOfNameInField = indexOfNameInDeclarator
                        If indexOfDeclaratorInField > 0 Then
                            For i = 0 To indexOfDeclaratorInField - 1
                                indexOfNameInField += fieldDeclaration.Declarators(i).Names.Count
                            Next
                        End If
 
                        Dim namesInFieldCount = fieldDeclaration.Declarators.SelectMany(Function(v) v.Names).Count()
 
                        Return index + (namesInFieldCount - indexOfNameInField)
                    End If
 
                    Return index + 1
                End If
 
                index += 1
            End While
 
            Return -1
        End Function
 
        Public Overrides Sub GetOptionNameAndOrdinal(parentNode As SyntaxNode, optionNode As SyntaxNode, ByRef name As String, ByRef ordinal As Integer)
            Debug.Assert(TypeOf optionNode Is OptionStatementSyntax)
 
            name = GetNormalizedName(DirectCast(optionNode, OptionStatementSyntax))
 
            ordinal = -1
            For Each [option] As OptionStatementSyntax In GetOptionNodes(parentNode)
                If GetNormalizedName([option]) = name Then
                    ordinal += 1
                End If
 
                If [option].Equals(optionNode) Then
                    Exit For
                End If
            Next
        End Sub
 
        Public Overrides Sub GetInheritsNamespaceAndOrdinal(parentNode As SyntaxNode, inheritsNode As SyntaxNode, ByRef namespaceName As String, ByRef ordinal As Integer)
            Debug.Assert(TypeOf inheritsNode Is InheritsStatementSyntax)
 
            namespaceName = DirectCast(inheritsNode, InheritsStatementSyntax).Types.ToString()
 
            ordinal = -1
            For Each [inherits] As InheritsStatementSyntax In GetInheritsNodes(parentNode)
                If [inherits].Types.ToString() = namespaceName Then
                    ordinal += 1
                End If
 
                If [inherits].Equals(inheritsNode) Then
                    Exit For
                End If
            Next
        End Sub
 
        Public Overrides Sub GetImplementsNamespaceAndOrdinal(parentNode As SyntaxNode, implementsNode As SyntaxNode, ByRef namespaceName As String, ByRef ordinal As Integer)
            Debug.Assert(TypeOf implementsNode Is ImplementsStatementSyntax)
 
            namespaceName = DirectCast(implementsNode, ImplementsStatementSyntax).Types.ToString()
 
            ordinal = -1
            For Each [implements] As ImplementsStatementSyntax In GetImplementsNodes(parentNode)
                If [implements].Types.ToString() = namespaceName Then
                    ordinal += 1
                End If
 
                If [implements].Equals(implementsNode) Then
                    Exit For
                End If
            Next
        End Sub
 
        Public Overrides Sub GetAttributeNameAndOrdinal(parentNode As SyntaxNode, attributeNode As SyntaxNode, ByRef name As String, ByRef ordinal As Integer)
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            name = DirectCast(attributeNode, AttributeSyntax).Name.ToString()
 
            ordinal = -1
            For Each attribute As AttributeSyntax In GetAttributeNodes(parentNode)
                If attribute.Name.ToString() = name Then
                    ordinal += 1
                End If
 
                If attribute.Equals(attributeNode) Then
                    Exit For
                End If
            Next
        End Sub
 
        Public Overrides Function GetAttributeTargetNode(attributeNode As SyntaxNode) As SyntaxNode
            If TypeOf attributeNode Is AttributeSyntax Then
                Return attributeNode
            End If
 
            Throw Exceptions.ThrowEUnexpected()
        End Function
 
        Public Overrides Function GetAttributeTarget(attributeNode As SyntaxNode) As String
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            Dim attribute = DirectCast(attributeNode, AttributeSyntax)
 
            Return If(attribute.Target IsNot Nothing,
                      attribute.Target.AttributeModifier.ToString(),
                      String.Empty)
        End Function
 
        Public Overrides Function SetAttributeTarget(attributeNode As SyntaxNode, value As String) As SyntaxNode
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            Dim attribute = DirectCast(attributeNode, AttributeSyntax)
            Dim target = attribute.Target
 
            If Not String.IsNullOrEmpty(value) Then
                ' VB only supports Assembly and Module as attribute modifiers.
                Dim newModifier As SyntaxToken
                If String.Equals(value, "Assembly", StringComparison.OrdinalIgnoreCase) Then
                    newModifier = SyntaxFactory.Token(SyntaxKind.AssemblyKeyword)
                ElseIf String.Equals(value, "Module", StringComparison.OrdinalIgnoreCase) Then
                    newModifier = SyntaxFactory.Token(SyntaxKind.ModuleKeyword)
                Else
                    Throw Exceptions.ThrowEInvalidArg()
                End If
 
                Dim newTarget = If(target IsNot Nothing,
                                   target.WithAttributeModifier(newModifier),
                                   SyntaxFactory.AttributeTarget(newModifier))
 
                Return attribute.WithTarget(newTarget)
            Else
                Return attribute.WithTarget(Nothing)
            End If
        End Function
 
        Public Overrides Function GetAttributeValue(attributeNode As SyntaxNode) As String
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            Dim attribute = DirectCast(attributeNode, AttributeSyntax)
            Dim argumentList = attribute.ArgumentList
            If argumentList IsNot Nothing Then
                Return argumentList.Arguments.ToString()
            End If
 
            Return String.Empty
        End Function
 
        Public Overrides Function SetAttributeValue(attributeNode As SyntaxNode, value As String) As SyntaxNode
            Debug.Assert(TypeOf attributeNode Is AttributeSyntax)
 
            Dim attribute = DirectCast(attributeNode, AttributeSyntax)
            Dim argumentList = attribute.ArgumentList
 
            Dim parsedArgumentList = SyntaxFactory.ParseArgumentList("(" & value & ")")
            Dim newArgumentList = If(argumentList IsNot Nothing,
                                     argumentList.WithArguments(parsedArgumentList.Arguments),
                                     parsedArgumentList)
 
            Return attribute.WithArgumentList(newArgumentList)
        End Function
 
        Public Overrides Function GetNodeWithAttributes(node As SyntaxNode) As SyntaxNode
            Return If(TypeOf node Is ModifiedIdentifierSyntax,
                      node.GetAncestor(Of FieldDeclarationSyntax),
                      node)
        End Function
 
        Public Overrides Function GetEffectiveParentForAttribute(node As SyntaxNode) As SyntaxNode
            If node.HasAncestor(Of FieldDeclarationSyntax)() Then
                Return node.GetAncestor(Of FieldDeclarationSyntax).Declarators.First().Names.First()
            ElseIf node.HasAncestor(Of ParameterSyntax)() Then
                Return node.GetAncestor(Of ParameterSyntax)()
            Else
                Return node.Parent
            End If
        End Function
 
        Public Overrides Sub GetAttributeArgumentParentAndIndex(attributeArgumentNode As SyntaxNode, ByRef attributeNode As SyntaxNode, ByRef index As Integer)
            Debug.Assert(TypeOf attributeArgumentNode Is ArgumentSyntax)
 
            Dim argument = DirectCast(attributeArgumentNode, ArgumentSyntax)
            Dim attribute = DirectCast(argument.Ancestors.FirstOrDefault(Function(n) n.Kind = SyntaxKind.Attribute), AttributeSyntax)
 
            attributeNode = attribute
            index = attribute.ArgumentList.Arguments.IndexOf(DirectCast(attributeArgumentNode, ArgumentSyntax))
        End Sub
 
        Public Overrides Function CreateAttributeNode(name As String, value As String, Optional target As String = Nothing) As SyntaxNode
            Dim specifier As AttributeTargetSyntax = Nothing
            If target IsNot Nothing Then
                Dim contextualKeywordKind = SyntaxFacts.GetContextualKeywordKind(target)
                If contextualKeywordKind = SyntaxKind.AssemblyKeyword OrElse
                    contextualKeywordKind = SyntaxKind.ModuleKeyword Then
                    specifier = SyntaxFactory.AttributeTarget(SyntaxFactory.Token(contextualKeywordKind, text:=target))
                Else
                    specifier = SyntaxFactory.AttributeTarget(SyntaxFactory.ParseToken(target))
                End If
            End If
 
            Return SyntaxFactory.AttributeList(
                SyntaxFactory.SingletonSeparatedList(
                    SyntaxFactory.Attribute(
                        target:=specifier,
                        name:=SyntaxFactory.ParseName(name),
                        argumentList:=SyntaxFactory.ParseArgumentList("(" & value & ")"))))
 
        End Function
 
        Public Overrides Function CreateAttributeArgumentNode(name As String, value As String) As SyntaxNode
            If Not String.IsNullOrEmpty(name) Then
                Return SyntaxFactory.SimpleArgument(
                           SyntaxFactory.NameColonEquals(SyntaxFactory.IdentifierName(name)),
                           SyntaxFactory.ParseExpression(value))
            Else
                Return SyntaxFactory.SimpleArgument(SyntaxFactory.ParseExpression(value))
            End If
        End Function
 
        Public Overrides Function CreateImportNode(name As String, Optional [alias] As String = Nothing) As SyntaxNode
            Dim nameSyntax = SyntaxFactory.ParseName(name)
 
            Dim importsClause As ImportsClauseSyntax
            If Not String.IsNullOrEmpty([alias]) Then
                importsClause = SyntaxFactory.SimpleImportsClause(SyntaxFactory.ImportAliasClause([alias]), nameSyntax)
            Else
                importsClause = SyntaxFactory.SimpleImportsClause(nameSyntax)
            End If
 
            Return SyntaxFactory.ImportsStatement(SyntaxFactory.SingletonSeparatedList(importsClause))
        End Function
 
        Public Overrides Function CreateParameterNode(name As String, type As String) As SyntaxNode
            Return SyntaxFactory.Parameter(SyntaxFactory.ModifiedIdentifier(name)).WithAsClause(SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(type)))
        End Function
 
        Public Overrides Function GetAttributeArgumentValue(attributeArgumentNode As SyntaxNode) As String
            Select Case attributeArgumentNode.Kind
                Case SyntaxKind.SimpleArgument
                    Return DirectCast(attributeArgumentNode, SimpleArgumentSyntax).Expression.ToString()
            End Select
 
            Throw New InvalidOperationException()
        End Function
 
        Public Overrides Function GetImportAlias(node As SyntaxNode) As String
            Select Case node.Kind
                Case SyntaxKind.SimpleImportsClause
                    Dim simpleImportsClause = DirectCast(node, SimpleImportsClauseSyntax)
                    Return If(simpleImportsClause.Alias IsNot Nothing,
                              simpleImportsClause.Alias.Identifier.ToString(),
                              String.Empty)
                Case Else
                    Throw New InvalidOperationException()
            End Select
 
        End Function
 
        Public Overrides Function GetImportNamespaceOrType(node As SyntaxNode) As String
            Select Case node.Kind
                Case SyntaxKind.SimpleImportsClause
                    Return GetNormalizedName(DirectCast(node, SimpleImportsClauseSyntax).Name)
                Case Else
                    Throw New InvalidOperationException()
            End Select
        End Function
 
        Public Overrides Sub GetImportParentAndName(node As SyntaxNode, ByRef parentNode As SyntaxNode, ByRef name As String)
            parentNode = Nothing
 
            Select Case node.Kind
                Case SyntaxKind.SimpleImportsClause
                    name = GetNormalizedName(DirectCast(node, SimpleImportsClauseSyntax).Name)
                Case Else
                    Throw New InvalidOperationException()
            End Select
        End Sub
 
        Public Overrides Function GetParameterName(node As SyntaxNode) As String
            Dim parameter = TryCast(node, ParameterSyntax)
            If parameter IsNot Nothing Then
                Return GetNameFromParameter(parameter)
            End If
 
            Throw New InvalidOperationException()
        End Function
 
        Private Function GetNameFromParameter(parameter As ParameterSyntax) As String
            Dim parameterName As String = parameter.Identifier.Identifier.ToString()
            Return If(Not String.IsNullOrEmpty(parameterName) AndAlso SyntaxFactsService.IsTypeCharacter(parameterName.Last()),
                parameterName.Substring(0, parameterName.Length - 1),
                parameterName)
        End Function
 
        Public Overrides Function GetParameterFullName(node As SyntaxNode) As String
            Dim parameter = TryCast(node, ParameterSyntax)
            If parameter IsNot Nothing Then
                Return parameter.Identifier.ToString()
            End If
 
            Throw New InvalidOperationException()
        End Function
 
        Public Overrides Function GetParameterKind(node As SyntaxNode) As EnvDTE80.vsCMParameterKind
            Dim parameter = TryCast(node, ParameterSyntax)
            If parameter IsNot Nothing Then
                Dim kind = EnvDTE80.vsCMParameterKind.vsCMParameterKindNone
 
                Dim modifiers = parameter.Modifiers
 
                If modifiers.Any(SyntaxKind.OptionalKeyword) Then
                    kind = kind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional
                End If
 
                If modifiers.Any(SyntaxKind.ParamArrayKeyword) Then
                    kind = kind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindParamArray
                End If
 
                If modifiers.Any(SyntaxKind.ByRefKeyword) Then
                    kind = kind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindRef
                Else
                    kind = kind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindIn
                End If
 
                Return kind
 
            End If
 
            Throw New InvalidOperationException()
        End Function
 
        Public Overrides Function SetParameterKind(node As SyntaxNode, kind As EnvDTE80.vsCMParameterKind) As SyntaxNode
            Dim parameter = TryCast(node, ParameterSyntax)
 
            If parameter Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If Not IsValidParameterKind(kind) Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim newModifierList = New List(Of SyntaxToken)
 
            ' TODO (tomescht): The Dev11 code allowed different sets of modifiers to be
            ' set when in batch mode vs non-batch mode.
 
            If (kind And EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional) <> 0 Then
                newModifierList.Add(SyntaxFactory.Token(SyntaxKind.OptionalKeyword))
            End If
 
            If (kind And EnvDTE80.vsCMParameterKind.vsCMParameterKindIn) <> 0 AndAlso parameter.Modifiers.Any(SyntaxKind.ByValKeyword) Then
                ' Ensure that we keep ByVal if it was already present.
                newModifierList.Add(SyntaxFactory.Token(SyntaxKind.ByValKeyword))
            ElseIf (kind And EnvDTE80.vsCMParameterKind.vsCMParameterKindRef) <> 0 Then
                newModifierList.Add(SyntaxFactory.Token(SyntaxKind.ByRefKeyword))
            End If
 
            If (kind And EnvDTE80.vsCMParameterKind.vsCMParameterKindParamArray) <> 0 Then
                newModifierList.Add(SyntaxFactory.Token(SyntaxKind.ParamArrayKeyword))
            End If
 
            Return parameter.WithModifiers(SyntaxFactory.TokenList(newModifierList))
        End Function
 
        Private Shared Function IsValidParameterKind(kind As EnvDTE80.vsCMParameterKind) As Boolean
            Select Case kind
                Case EnvDTE80.vsCMParameterKind.vsCMParameterKindNone,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindIn,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindRef,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional Or EnvDTE80.vsCMParameterKind.vsCMParameterKindIn,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional Or EnvDTE80.vsCMParameterKind.vsCMParameterKindRef,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindParamArray,
                     EnvDTE80.vsCMParameterKind.vsCMParameterKindParamArray Or EnvDTE80.vsCMParameterKind.vsCMParameterKindIn
                    Return True
            End Select
 
            Return False
        End Function
 
        Public Overrides Function UpdateParameterKind(parameterKind As EnvDTE80.vsCMParameterKind, passingMode As PARAMETER_PASSING_MODE) As EnvDTE80.vsCMParameterKind
            Dim updatedParameterKind = parameterKind
 
            Select Case passingMode
                Case PARAMETER_PASSING_MODE.cmParameterTypeIn
                    updatedParameterKind = updatedParameterKind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindIn
                    updatedParameterKind = updatedParameterKind And Not EnvDTE80.vsCMParameterKind.vsCMParameterKindRef
                    updatedParameterKind = updatedParameterKind And Not EnvDTE80.vsCMParameterKind.vsCMParameterKindOut
 
                Case PARAMETER_PASSING_MODE.cmParameterTypeInOut
                    updatedParameterKind = updatedParameterKind And Not EnvDTE80.vsCMParameterKind.vsCMParameterKindIn
                    updatedParameterKind = updatedParameterKind Or EnvDTE80.vsCMParameterKind.vsCMParameterKindRef
                    updatedParameterKind = updatedParameterKind And Not EnvDTE80.vsCMParameterKind.vsCMParameterKindOut
 
                Case PARAMETER_PASSING_MODE.cmParameterTypeOut
                    Throw Exceptions.ThrowEInvalidArg()
            End Select
 
            Return updatedParameterKind
        End Function
 
        Public Overrides Function ValidateFunctionKind(containerNode As SyntaxNode, kind As EnvDTE.vsCMFunction, name As String) As EnvDTE.vsCMFunction
            If kind = EnvDTE.vsCMFunction.vsCMFunctionSub Then
                Return If(name = "New" AndAlso Not TypeOf containerNode Is InterfaceBlockSyntax,
                          EnvDTE.vsCMFunction.vsCMFunctionConstructor,
                          kind)
            End If
 
            If kind = EnvDTE.vsCMFunction.vsCMFunctionFunction Then
                Return kind
            End If
 
            Throw Exceptions.ThrowEInvalidArg()
        End Function
 
        Public Overrides ReadOnly Property SupportsEventThrower As Boolean
            Get
                Return True
            End Get
        End Property
 
        Public Overrides Function GetCanOverride(memberNode As SyntaxNode) As Boolean
            Debug.Assert(TypeOf memberNode Is StatementSyntax)
 
            Dim member = TryCast(memberNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If member.Parent.Kind = SyntaxKind.InterfaceBlock Then
                Return True
            End If
 
            Dim flags = member.GetModifierFlags()
 
            If (flags And ModifierFlags.NotOverridable) <> 0 Then
                Return False
            End If
 
            If (flags And ModifierFlags.MustOverride) <> 0 Then
                Return True
            End If
 
            If (flags And ModifierFlags.Overridable) <> 0 Then
                Return True
            End If
 
            If (flags And ModifierFlags.Overrides) <> 0 Then
                Return True
            End If
 
            Return False
        End Function
 
        Public Overrides Function SetCanOverride(memberNode As SyntaxNode, value As Boolean) As SyntaxNode
            Dim overrideKind = If(value, EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual, EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNone)
 
            Return SetOverrideKind(memberNode, overrideKind)
        End Function
 
        Public Overrides Function GetClassKind(typeNode As SyntaxNode, typeSymbol As INamedTypeSymbol) As EnvDTE80.vsCMClassKind
            Debug.Assert(TypeOf typeNode Is ClassBlockSyntax OrElse
                         TypeOf typeNode Is ModuleBlockSyntax)
 
            Dim typeBlock = DirectCast(typeNode, TypeBlockSyntax)
            If TypeOf typeBlock Is ModuleBlockSyntax Then
                Return EnvDTE80.vsCMClassKind.vsCMClassKindModule
            End If
 
            Dim flags = typeBlock.GetModifierFlags()
 
            If (flags And ModifierFlags.Partial) <> 0 Then
                Return EnvDTE80.vsCMClassKind.vsCMClassKindPartialClass
            End If
 
            If typeSymbol.DeclaringSyntaxReferences.Length > 1 Then
                Return EnvDTE80.vsCMClassKind.vsCMClassKindPartialClass
            End If
 
            Return EnvDTE80.vsCMClassKind.vsCMClassKindMainClass
        End Function
 
        Private Shared Function IsValidClassKind(kind As EnvDTE80.vsCMClassKind) As Boolean
            Return kind = EnvDTE80.vsCMClassKind.vsCMClassKindMainClass OrElse
                   kind = EnvDTE80.vsCMClassKind.vsCMClassKindPartialClass
        End Function
 
        Public Overrides Function SetClassKind(typeNode As SyntaxNode, kind As EnvDTE80.vsCMClassKind) As SyntaxNode
            Debug.Assert(TypeOf typeNode Is ClassBlockSyntax OrElse
                         TypeOf typeNode Is ModuleBlockSyntax)
 
            Dim typeBlock = DirectCast(typeNode, StatementSyntax)
            If TypeOf typeBlock Is ModuleBlockSyntax Then
                If kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNone Then
                    Return typeBlock
                End If
 
                Throw Exceptions.ThrowENotImpl()
            End If
 
            If Not IsValidClassKind(kind) Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim flags = typeBlock.GetModifierFlags()
            flags = flags And Not ModifierFlags.Partial
 
            If kind = EnvDTE80.vsCMClassKind.vsCMClassKindPartialClass Then
                flags = flags Or ModifierFlags.Partial
            End If
 
            Return typeBlock.UpdateModifiers(flags)
        End Function
 
        Private Shared Function CollectComments(triviaList As IList(Of SyntaxTrivia)) As IList(Of SyntaxTrivia)
            Dim commentList = New List(Of SyntaxTrivia)
            Dim firstCommentFound = False
 
            For i = triviaList.Count - 1 To 0 Step -1
                Dim trivia = triviaList(i)
                Dim nextTrivia = If(i > 0, triviaList(i - 1), Nothing)
 
                If trivia.Kind = SyntaxKind.CommentTrivia Then
                    firstCommentFound = True
                    commentList.Add(trivia)
                ElseIf Not firstCommentFound AndAlso trivia.IsWhitespaceOrEndOfLine() Then
                    Continue For
                ElseIf firstCommentFound AndAlso trivia.Kind = SyntaxKind.EndOfLineTrivia AndAlso nextTrivia.Kind = SyntaxKind.CommentTrivia Then
                    Continue For
                Else
                    Exit For
                End If
            Next
 
            commentList.Reverse()
 
            Return commentList
        End Function
 
        Public Overrides Function GetComment(node As SyntaxNode) As String
            Debug.Assert(TypeOf node Is StatementSyntax)
 
            Dim member = DirectCast(node, StatementSyntax)
 
            Dim firstToken = member.GetFirstToken()
            Dim triviaList = firstToken.LeadingTrivia
            Dim commentList = CollectComments(firstToken.LeadingTrivia.ToArray())
 
            If commentList.Count = 0 Then
                Return String.Empty
            End If
 
            Dim textBuilder = New StringBuilder()
            For Each trivia In commentList
                Debug.Assert(trivia.ToString().StartsWith("'", StringComparison.Ordinal))
                Dim commentText = trivia.ToString().Substring(1)
 
                textBuilder.AppendLine(commentText)
            Next
 
            Return textBuilder.ToString().TrimEnd()
        End Function
 
        Public Overrides Function SetComment(node As SyntaxNode, value As String) As SyntaxNode
            Debug.Assert(TypeOf node Is StatementSyntax)
 
            Dim member = DirectCast(node, StatementSyntax)
            Dim text = member.SyntaxTree.GetText(CancellationToken.None)
            Dim newLine = GetNewLineCharacter(text)
 
            Dim commentText = String.Empty
 
            If value IsNot Nothing Then
                Dim builder = New StringBuilder()
 
                For Each line In value.Split({vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
                    builder.Append("' ")
                    builder.Append(line)
                    builder.Append(newLine)
                Next
 
                commentText = builder.ToString()
            End If
 
            Dim newTriviaList = SyntaxFactory.ParseLeadingTrivia(commentText)
            Dim leadingTriviaList = member.GetLeadingTrivia().ToList()
 
            Dim commentList = CollectComments(leadingTriviaList)
            If commentList.Count > 0 Then
                ' In this case, we're going to replace the existing comment.
                Dim firstIndex = leadingTriviaList.FindIndex(Function(t) t = commentList(0))
                Dim lastIndex = leadingTriviaList.FindIndex(Function(t) t = commentList(commentList.Count - 1))
                Dim count = lastIndex - firstIndex + 1
 
                leadingTriviaList.RemoveRange(firstIndex, count)
 
                ' Note: single line comments have a trailing new-line but that won't be
                ' returned by CollectComments. So, we may need to remove an additional new line below.
                If firstIndex < leadingTriviaList.Count AndAlso
                   leadingTriviaList(firstIndex).Kind = SyntaxKind.EndOfLineTrivia Then
 
                    leadingTriviaList.RemoveAt(firstIndex)
                End If
 
                For Each triviaElement In newTriviaList.Reverse()
                    leadingTriviaList.Insert(firstIndex, triviaElement)
                Next
            Else
                ' Otherwise, just add the comment to the end of the leading trivia.
                leadingTriviaList.AddRange(newTriviaList)
            End If
 
            Return member.WithLeadingTrivia(leadingTriviaList)
        End Function
 
        Public Overrides Function GetConstKind(variableNode As SyntaxNode) As EnvDTE80.vsCMConstKind
            If TypeOf variableNode Is EnumMemberDeclarationSyntax Then
                Return EnvDTE80.vsCMConstKind.vsCMConstKindConst
            End If
 
            Dim member = TryCast(GetNodeWithModifiers(variableNode), StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
 
            If (flags And ModifierFlags.Const) <> 0 Then
                Return EnvDTE80.vsCMConstKind.vsCMConstKindConst
            End If
 
            If (flags And ModifierFlags.ReadOnly) <> 0 Then
                Return EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly
            End If
 
            Return EnvDTE80.vsCMConstKind.vsCMConstKindNone
        End Function
 
        Private Shared Function IsValidConstKind(kind As EnvDTE80.vsCMConstKind) As Boolean
            Return kind = EnvDTE80.vsCMConstKind.vsCMConstKindConst OrElse
                   kind = EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly OrElse
                   kind = EnvDTE80.vsCMConstKind.vsCMConstKindNone
        End Function
 
        Public Overrides Function SetConstKind(variableNode As SyntaxNode, kind As EnvDTE80.vsCMConstKind) As SyntaxNode
            If TypeOf variableNode Is EnumMemberDeclarationSyntax Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            If Not IsValidConstKind(kind) Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim member = TryCast(GetNodeWithModifiers(variableNode), StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
            flags = flags And Not (ModifierFlags.Const Or ModifierFlags.ReadOnly Or ModifierFlags.Dim)
 
            If kind = EnvDTE80.vsCMConstKind.vsCMConstKindConst Then
                flags = flags Or ModifierFlags.Const
            ElseIf kind = EnvDTE80.vsCMConstKind.vsCMConstKindReadOnly Then
                flags = flags Or ModifierFlags.ReadOnly
            End If
 
            If flags = 0 Then
                flags = flags Or ModifierFlags.Dim
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Public Overrides Function GetDataTypeKind(typeNode As SyntaxNode, symbol As INamedTypeSymbol) As EnvDTE80.vsCMDataTypeKind
            Debug.Assert(TypeOf typeNode Is ClassBlockSyntax OrElse
                         TypeOf typeNode Is InterfaceBlockSyntax OrElse
                         TypeOf typeNode Is ModuleBlockSyntax OrElse
                         TypeOf typeNode Is StructureBlockSyntax)
 
            Dim typeBlock = DirectCast(typeNode, TypeBlockSyntax)
            If TypeOf typeBlock Is ModuleBlockSyntax Then
                Return EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindModule
            End If
 
            Dim flags = typeBlock.GetModifierFlags()
            If (flags And ModifierFlags.Partial) <> 0 Then
                Return EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindPartial
            End If
 
            If symbol.DeclaringSyntaxReferences.Length > 1 Then
                Return EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindPartial
            End If
 
            Return EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindMain
        End Function
 
        Private Shared Function IsValidDataTypeKind(kind As EnvDTE80.vsCMDataTypeKind, allowModule As Boolean) As Boolean
            Return kind = EnvDTE80.vsCMClassKind.vsCMClassKindMainClass OrElse
                   kind = EnvDTE80.vsCMClassKind.vsCMClassKindPartialClass OrElse
                   (allowModule AndAlso kind = EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindModule)
        End Function
 
        Public Overrides Function SetDataTypeKind(typeNode As SyntaxNode, kind As EnvDTE80.vsCMDataTypeKind) As SyntaxNode
            Debug.Assert(TypeOf typeNode Is ClassBlockSyntax OrElse
                         TypeOf typeNode Is InterfaceBlockSyntax OrElse
                         TypeOf typeNode Is ModuleBlockSyntax OrElse
                         TypeOf typeNode Is StructureBlockSyntax)
 
            Dim typeBlock = DirectCast(typeNode, TypeBlockSyntax)
            If TypeOf typeBlock Is InterfaceBlockSyntax Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim allowModule = TypeOf typeBlock Is ClassBlockSyntax OrElse
                              TypeOf typeBlock Is ModuleBlockSyntax
 
            If Not IsValidDataTypeKind(kind, allowModule) Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = typeBlock.GetModifierFlags()
            flags = flags And Not ModifierFlags.Partial
 
            If kind = EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindPartial Then
                flags = flags Or ModifierFlags.Partial
            End If
 
            ' VB supports changing a Module to a Class and vice versa.
            If TypeOf typeBlock Is ModuleBlockSyntax Then
                If kind = EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindMain OrElse
                   kind = EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindPartial Then
 
                    Dim moduleBlock = DirectCast(typeBlock, ModuleBlockSyntax)
 
                    typeBlock = SyntaxFactory.ClassBlock(
                        classStatement:=SyntaxFactory.ClassStatement(
                            attributeLists:=moduleBlock.ModuleStatement.AttributeLists,
                            modifiers:=moduleBlock.ModuleStatement.Modifiers,
                            classKeyword:=SyntaxFactory.Token(moduleBlock.ModuleStatement.ModuleKeyword.LeadingTrivia, SyntaxKind.ClassKeyword, moduleBlock.ModuleStatement.ModuleKeyword.TrailingTrivia),
                            identifier:=moduleBlock.ModuleStatement.Identifier,
                            typeParameterList:=moduleBlock.ModuleStatement.TypeParameterList),
                        [inherits]:=moduleBlock.Inherits,
                        [implements]:=moduleBlock.Implements,
                        members:=moduleBlock.Members,
                        endClassStatement:=SyntaxFactory.EndClassStatement(
                            endKeyword:=moduleBlock.EndModuleStatement.EndKeyword,
                            blockKeyword:=SyntaxFactory.Token(moduleBlock.EndModuleStatement.BlockKeyword.LeadingTrivia, SyntaxKind.ClassKeyword, moduleBlock.EndModuleStatement.BlockKeyword.TrailingTrivia)))
                End If
            ElseIf TypeOf typeBlock Is ClassBlockSyntax Then
                If kind = EnvDTE80.vsCMDataTypeKind.vsCMDataTypeKindModule Then
 
                    flags = flags And Not ModifierFlags.Shared
                    Dim classBlock = DirectCast(typeBlock, ClassBlockSyntax)
 
                    typeBlock = SyntaxFactory.ModuleBlock(
                        moduleStatement:=SyntaxFactory.ModuleStatement(
                            attributeLists:=classBlock.ClassStatement.AttributeLists,
                            modifiers:=classBlock.ClassStatement.Modifiers,
                            moduleKeyword:=SyntaxFactory.Token(classBlock.ClassStatement.ClassKeyword.LeadingTrivia, SyntaxKind.ModuleKeyword, classBlock.ClassStatement.ClassKeyword.TrailingTrivia),
                            identifier:=classBlock.ClassStatement.Identifier,
                            typeParameterList:=classBlock.ClassStatement.TypeParameterList),
                        [inherits]:=Nothing,
                        [implements]:=Nothing,
                        members:=classBlock.Members,
                        endModuleStatement:=SyntaxFactory.EndModuleStatement(
                            endKeyword:=classBlock.EndClassStatement.EndKeyword,
                            blockKeyword:=SyntaxFactory.Token(classBlock.EndClassStatement.BlockKeyword.LeadingTrivia, SyntaxKind.ModuleKeyword, classBlock.EndClassStatement.BlockKeyword.TrailingTrivia)))
                End If
            End If
 
            Return typeBlock.UpdateModifiers(flags)
        End Function
 
        Private Shared Function GetDocCommentNode(memberDeclaration As StatementSyntax) As DocumentationCommentTriviaSyntax
            Dim docCommentTrivia = memberDeclaration _
                .GetLeadingTrivia() _
                .Reverse() _
                .FirstOrDefault(Function(t) t.Kind = SyntaxKind.DocumentationCommentTrivia)
 
            If docCommentTrivia.Kind <> SyntaxKind.DocumentationCommentTrivia Then
                Return Nothing
            End If
 
            Return DirectCast(docCommentTrivia.GetStructure(), DocumentationCommentTriviaSyntax)
        End Function
 
        Public Overrides Function GetDocComment(node As SyntaxNode) As String
            Debug.Assert(TypeOf node Is StatementSyntax)
 
            Dim member = DirectCast(node, StatementSyntax)
            Dim documentationComment = GetDocCommentNode(member)
            If documentationComment Is Nothing Then
                Return String.Empty
            End If
 
            Dim text = member.SyntaxTree.GetText(CancellationToken.None)
            Dim newLine = GetNewLineCharacter(text)
 
            Dim lines = documentationComment.ToString().Split({newLine}, StringSplitOptions.None)
 
            ' trim off leading whitespace and exterior trivia.
            Dim lengthToStrip = lines(0).GetLeadingWhitespace().Length
            Dim linesCount = lines.Length
 
            For i = 1 To lines.Length - 1
                Dim line = lines(i).TrimStart()
                If line.StartsWith("'''", StringComparison.Ordinal) Then
                    lines(i) = line.Substring(3)
                End If
            Next
 
            Return lines.Join(newLine).TrimEnd()
        End Function
 
        Public Overrides Function SetDocComment(node As SyntaxNode, value As String) As SyntaxNode
            Debug.Assert(TypeOf node Is StatementSyntax)
 
            Dim member = DirectCast(node, StatementSyntax)
            Dim triviaList = CType(Nothing, SyntaxTriviaList)
 
            If value IsNot Nothing Then
                Dim text = member.SyntaxTree.GetText(CancellationToken.None)
                Dim newLine = GetNewLineCharacter(text)
                Dim builder = New StringBuilder()
 
                For Each line In value.Split({vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
                    builder.Append("''' ")
                    builder.Append(line)
                    builder.Append(newLine)
                Next
 
                triviaList = SyntaxFactory.ParseLeadingTrivia(builder.ToString())
            End If
 
            Dim leadingTriviaList = member.GetLeadingTrivia().ToList()
            Dim documentationComment = GetDocCommentNode(member)
 
            If documentationComment IsNot Nothing Then
                ' In this case, we're going to replace the existing XML doc comment.
                Dim index = leadingTriviaList.FindIndex(Function(t) t = documentationComment.ParentTrivia)
                leadingTriviaList.RemoveAt(index)
 
                For Each triviaElement In triviaList.Reverse()
                    leadingTriviaList.Insert(index, triviaElement)
                Next
            Else
                ' Otherwise, just add the XML doc comment to the end of the leading trivia.
                leadingTriviaList.AddRange(triviaList)
            End If
 
            Return member.WithLeadingTrivia(leadingTriviaList)
        End Function
 
        Public Overrides Function GetFunctionKind(symbol As IMethodSymbol) As EnvDTE.vsCMFunction
            If symbol.IsOverride AndAlso symbol.Name = "Finalize" Then
                Return EnvDTE.vsCMFunction.vsCMFunctionDestructor
            End If
 
            Select Case symbol.MethodKind
                Case MethodKind.Ordinary,
                     MethodKind.DeclareMethod
                    Return If(symbol.ReturnsVoid, EnvDTE.vsCMFunction.vsCMFunctionSub, EnvDTE.vsCMFunction.vsCMFunctionFunction)
 
                Case MethodKind.Constructor,
                     MethodKind.StaticConstructor
                    Return EnvDTE.vsCMFunction.vsCMFunctionConstructor
 
                Case MethodKind.UserDefinedOperator
                    Return EnvDTE.vsCMFunction.vsCMFunctionOperator
 
                Case MethodKind.PropertyGet
                    Return EnvDTE.vsCMFunction.vsCMFunctionPropertyGet
                Case MethodKind.PropertySet
                    Return EnvDTE.vsCMFunction.vsCMFunctionPropertySet
 
                Case MethodKind.EventAdd
                    Return CType(EnvDTE80.vsCMFunction2.vsCMFunctionAddHandler, EnvDTE.vsCMFunction)
                Case MethodKind.EventRemove
                    Return CType(EnvDTE80.vsCMFunction2.vsCMFunctionRemoveHandler, EnvDTE.vsCMFunction)
                Case MethodKind.EventRaise
                    Return CType(EnvDTE80.vsCMFunction2.vsCMFunctionRaiseEvent, EnvDTE.vsCMFunction)
            End Select
 
            Throw Exceptions.ThrowEUnexpected()
        End Function
 
        Public Overrides Function GetInheritanceKind(typeNode As SyntaxNode, typeSymbol As INamedTypeSymbol) As EnvDTE80.vsCMInheritanceKind
            Dim result As EnvDTE80.vsCMInheritanceKind = 0
 
            If typeSymbol.IsSealed Then
                result = result Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindSealed
            ElseIf typeSymbol.IsAbstract Then
                result = result Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindAbstract
            End If
 
            ' Old VB code model had a special case to check other parts for Shadows, so we'll do that here..
            Dim statements = typeSymbol.DeclaringSyntaxReferences _
                .Select(Function(r) TryCast(r.GetSyntax(), StatementSyntax)) _
                .Where(Function(s) s IsNot Nothing)
 
            For Each statement In statements
                Dim modifiers = SyntaxFactory.TokenList(statement.GetModifiers())
 
                If modifiers.Any(SyntaxKind.ShadowsKeyword) Then
                    result = result Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew
                    Exit For
                End If
            Next
 
            Return result
        End Function
 
        Private Shared Function IsValidInheritanceKind(kind As EnvDTE80.vsCMInheritanceKind) As Boolean
            Return kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindAbstract OrElse
                   kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNone OrElse
                   kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindSealed OrElse
                   kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew OrElse
                   kind = (EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindAbstract) OrElse
                   kind = (EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindSealed)
        End Function
 
        Public Overrides Function SetInheritanceKind(typeNode As SyntaxNode, kind As EnvDTE80.vsCMInheritanceKind) As SyntaxNode
            Debug.Assert(TypeOf typeNode Is ClassBlockSyntax OrElse
                         TypeOf typeNode Is ModuleBlockSyntax)
 
            If TypeOf typeNode Is ModuleBlockSyntax Then
                If kind = EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNone Then
                    Return typeNode
                End If
 
                Throw Exceptions.ThrowENotImpl()
            End If
 
            If Not IsValidInheritanceKind(kind) Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim member = TryCast(typeNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
            flags = flags And Not (ModifierFlags.MustInherit Or ModifierFlags.NotInheritable Or ModifierFlags.Shadows)
 
            If kind <> EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNone Then
                If (kind And EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindAbstract) <> 0 Then
                    flags = flags Or ModifierFlags.MustInherit
                ElseIf (kind And EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindSealed) <> 0 Then
                    flags = flags Or ModifierFlags.NotInheritable
                End If
 
                If (kind And EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew) <> 0 Then
                    flags = flags Or ModifierFlags.Shadows
                End If
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Public Overrides Function GetMustImplement(memberNode As SyntaxNode) As Boolean
            Debug.Assert(TypeOf memberNode Is StatementSyntax)
 
            Dim member = TryCast(memberNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If member.Parent.Kind = SyntaxKind.InterfaceBlock Then
                Return True
            End If
 
            Dim flags = member.GetModifierFlags()
 
            Return (flags And ModifierFlags.MustOverride) <> 0
        End Function
 
        Public Overrides Function SetMustImplement(memberNode As SyntaxNode, value As Boolean) As SyntaxNode
            Dim overrideKind = If(value, EnvDTE80.vsCMOverrideKind.vsCMOverrideKindAbstract, EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNone)
 
            Return SetOverrideKind(memberNode, overrideKind)
        End Function
 
        Public Overrides Function GetOverrideKind(memberNode As SyntaxNode) As EnvDTE80.vsCMOverrideKind
            Debug.Assert(TypeOf memberNode Is DeclarationStatementSyntax)
 
            Dim member = TryCast(memberNode, DeclarationStatementSyntax)
            If member IsNot Nothing Then
                Dim modifiers = SyntaxFactory.TokenList(member.GetModifiers())
                Dim result As EnvDTE80.vsCMOverrideKind = 0
 
                If modifiers.Any(SyntaxKind.ShadowsKeyword) Then
                    result = result Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNew
                End If
 
                If modifiers.Any(SyntaxKind.OverridesKeyword) Then
                    result = result Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindOverride
                End If
 
                If modifiers.Any(SyntaxKind.MustOverrideKeyword) Or member.IsParentKind(SyntaxKind.InterfaceBlock) Then
                    result = result Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindAbstract
                End If
 
                If modifiers.Any(SyntaxKind.OverridableKeyword) Then
                    result = result Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual
                ElseIf modifiers.Any(SyntaxKind.NotOverridableKeyword) Then
                    result = result Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindSealed
                End If
 
                Return result
            End If
 
            Throw New InvalidOperationException
        End Function
 
        Private Shared Function IsValidOverrideKind(kind As EnvDTE80.vsCMOverrideKind) As Boolean
            Return kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindSealed OrElse
                   kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNew OrElse
                   kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindOverride OrElse
                   kind = (EnvDTE80.vsCMOverrideKind.vsCMOverrideKindOverride Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindSealed) OrElse
                   kind = (EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual Or EnvDTE80.vsCMInheritanceKind.vsCMInheritanceKindNew) OrElse
                   kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindAbstract OrElse
                   kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual OrElse
                   kind = EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNone
        End Function
 
        Public Overrides Function SetOverrideKind(memberNode As SyntaxNode, kind As EnvDTE80.vsCMOverrideKind) As SyntaxNode
            Dim member = TryCast(memberNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If TypeOf memberNode.Parent Is ModuleBlockSyntax OrElse
               TypeOf memberNode.Parent Is InterfaceBlockSyntax OrElse
               TypeOf memberNode.Parent Is PropertyBlockSyntax OrElse
               TypeOf memberNode.Parent Is PropertyStatementSyntax Then
 
                Throw Exceptions.ThrowENotImpl()
            End If
 
            If Not IsValidOverrideKind(kind) Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim flags = member.GetModifierFlags()
            flags = flags And Not (ModifierFlags.NotOverridable Or ModifierFlags.Shadows Or ModifierFlags.Overrides Or ModifierFlags.MustOverride Or ModifierFlags.Overridable)
 
            Select Case kind
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindSealed
                    flags = flags Or ModifierFlags.NotOverridable
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNew
                    flags = flags Or ModifierFlags.Shadows
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindOverride
                    flags = flags Or ModifierFlags.Overrides
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindAbstract
                    flags = flags Or ModifierFlags.MustOverride
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual
                    flags = flags Or ModifierFlags.Overridable
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindOverride Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindSealed
                    flags = flags Or ModifierFlags.NotOverridable Or ModifierFlags.Overrides
                Case EnvDTE80.vsCMOverrideKind.vsCMOverrideKindVirtual Or EnvDTE80.vsCMOverrideKind.vsCMOverrideKindNew
                    flags = flags Or ModifierFlags.Overridable Or ModifierFlags.Shadows
            End Select
 
            Dim resultMember = member.UpdateModifiers(flags)
 
            If (flags And ModifierFlags.MustOverride) <> 0 Then
                If TypeOf resultMember Is MethodBlockBaseSyntax Then
                    resultMember = DirectCast(resultMember, MethodBlockBaseSyntax).BlockStatement
                ElseIf TypeOf resultMember Is PropertyBlockSyntax Then
                    resultMember = DirectCast(resultMember, PropertyBlockSyntax).PropertyStatement
                End If
            Else
                If TypeOf resultMember Is MethodStatementSyntax Then
                    If resultMember.Kind = SyntaxKind.FunctionStatement Then
                        resultMember = SyntaxFactory.FunctionBlock(
                            subOrFunctionStatement:=DirectCast(resultMember, MethodStatementSyntax),
                            statements:=Nothing,
                            endSubOrFunctionStatement:=SyntaxFactory.EndFunctionStatement())
                    ElseIf resultMember.Kind = SyntaxKind.SubStatement Then
                        resultMember = SyntaxFactory.SubBlock(
                            subOrFunctionStatement:=DirectCast(resultMember, MethodStatementSyntax),
                            statements:=Nothing,
                            endSubOrFunctionStatement:=SyntaxFactory.EndSubStatement())
                    End If
                ElseIf TypeOf resultMember Is PropertyStatementSyntax Then
                    Dim propertyStatement = DirectCast(resultMember, PropertyStatementSyntax)
 
                    Dim parameterName = "value"
                    If propertyStatement.Identifier.GetTypeCharacter() <> TypeCharacter.None Then
                        parameterName &= propertyStatement.Identifier.GetTypeCharacter().GetTypeCharacterString()
                    End If
 
                    Dim returnType = propertyStatement.GetReturnType()
                    Dim asClauseText = If(returnType IsNot Nothing,
                                          " As " & returnType.ToString(),
                                          String.Empty)
 
                    resultMember = SyntaxFactory.PropertyBlock(
                        propertyStatement:=propertyStatement,
                        accessors:=SyntaxFactory.List(Of AccessorBlockSyntax)({
                            SyntaxFactory.GetAccessorBlock(
                                accessorStatement:=SyntaxFactory.GetAccessorStatement(),
                                statements:=Nothing,
                                endAccessorStatement:=SyntaxFactory.EndGetStatement()),
                            SyntaxFactory.SetAccessorBlock(
                                accessorStatement:=SyntaxFactory.SetAccessorStatement(
                                    attributeLists:=Nothing,
                                    modifiers:=Nothing,
                                    parameterList:=SyntaxFactory.ParseParameterList("(" & parameterName & asClauseText & ")")),
                                statements:=Nothing,
                                endAccessorStatement:=SyntaxFactory.EndSetStatement())
                            }))
                End If
            End If
 
            Return resultMember
        End Function
 
        Public Overrides Function GetIsAbstract(memberNode As SyntaxNode, symbol As ISymbol) As Boolean
            Return symbol.IsAbstract
        End Function
 
        Public Overrides Function SetIsAbstract(memberNode As SyntaxNode, value As Boolean) As SyntaxNode
            If TypeOf memberNode Is StructureBlockSyntax OrElse
               TypeOf memberNode Is ModuleBlockSyntax Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim member = TryCast(memberNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
 
            If value Then
                If TypeOf memberNode Is TypeBlockSyntax Then
                    flags = flags Or ModifierFlags.MustInherit
                Else
                    flags = flags Or ModifierFlags.MustOverride
                End If
            Else
                If TypeOf memberNode Is TypeBlockSyntax Then
                    flags = flags And Not ModifierFlags.MustInherit
                Else
                    flags = flags And Not ModifierFlags.MustOverride
                End If
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Public Overrides Function GetIsConstant(variableNode As SyntaxNode) As Boolean
            If TypeOf variableNode Is EnumMemberDeclarationSyntax Then
                Return True
            End If
 
            Dim member = TryCast(GetNodeWithModifiers(variableNode), StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim flags = member.GetModifierFlags()
 
            ' VB legacy code model returns True for both Const and ReadOnly fields
            Return (flags And (ModifierFlags.Const Or ModifierFlags.ReadOnly)) <> 0
        End Function
 
        Public Overrides Function SetIsConstant(variableNode As SyntaxNode, value As Boolean) As SyntaxNode
            Dim constKind = If(value, EnvDTE80.vsCMConstKind.vsCMConstKindConst, EnvDTE80.vsCMConstKind.vsCMConstKindNone)
 
            Return SetConstKind(variableNode, constKind)
        End Function
 
        Public Overrides Function GetIsDefault(propertyNode As SyntaxNode) As Boolean
            Debug.Assert(TypeOf propertyNode Is PropertyBlockSyntax OrElse
                         TypeOf propertyNode Is PropertyStatementSyntax)
 
            If TypeOf propertyNode Is PropertyStatementSyntax Then
                Return False
            End If
 
            Dim propertyBlock = TryCast(propertyNode, PropertyBlockSyntax)
            If propertyBlock Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Return propertyBlock.PropertyStatement.Modifiers.Any(SyntaxKind.DefaultKeyword)
        End Function
 
        Public Overrides Function SetIsDefault(propertyNode As SyntaxNode, value As Boolean) As SyntaxNode
            Debug.Assert(TypeOf propertyNode Is PropertyBlockSyntax OrElse
                         TypeOf propertyNode Is PropertyStatementSyntax)
 
            Dim member = DirectCast(propertyNode, StatementSyntax)
 
            Dim flags = member.GetModifierFlags()
            flags = flags And Not ModifierFlags.Default
 
            If value Then
                flags = flags Or ModifierFlags.Default
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Public Overrides Function GetIsGeneric(node As SyntaxNode) As Boolean
            Debug.Assert(TypeOf node Is StatementSyntax)
 
            Return DirectCast(node, StatementSyntax).GetArity() > 0
        End Function
 
        Public Overrides Function GetIsPropertyStyleEvent(eventNode As SyntaxNode) As Boolean
            Debug.Assert(TypeOf eventNode Is EventStatementSyntax OrElse
                         TypeOf eventNode Is EventBlockSyntax)
 
            Return TypeOf eventNode Is EventBlockSyntax
        End Function
 
        Public Overrides Function GetIsShared(memberNode As SyntaxNode, symbol As ISymbol) As Boolean
            Return _
                (symbol.Kind = SymbolKind.NamedType AndAlso DirectCast(symbol, INamedTypeSymbol).TypeKind = TypeKind.Module) OrElse
                symbol.IsStatic
        End Function
 
        Public Overrides Function SetIsShared(memberNode As SyntaxNode, value As Boolean) As SyntaxNode
            If TypeOf memberNode Is TypeBlockSyntax Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim member = TryCast(memberNode, StatementSyntax)
            If member Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim parentType = TryCast(member.Parent, DeclarationStatementSyntax)
            If parentType Is Nothing Then
                Throw Exceptions.ThrowEFail()
            End If
 
            If TypeOf parentType Is ModuleBlockSyntax OrElse
               TypeOf parentType Is InterfaceBlockSyntax OrElse
               TypeOf parentType Is EnumBlockSyntax Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim flags = member.GetModifierFlags() And Not ModifierFlags.Dim
 
            If value Then
                flags = flags Or ModifierFlags.Shared
            Else
                flags = flags And Not ModifierFlags.Shared
            End If
 
            If flags = 0 AndAlso member.IsKind(SyntaxKind.FieldDeclaration) Then
                flags = flags Or ModifierFlags.Dim
            End If
 
            Return member.UpdateModifiers(flags)
        End Function
 
        Public Overrides Function GetReadWrite(memberNode As SyntaxNode) As EnvDTE80.vsCMPropertyKind
            Debug.Assert(TypeOf memberNode Is PropertyBlockSyntax OrElse
                         TypeOf memberNode Is PropertyStatementSyntax)
 
            Dim propertyStatement = TryCast(memberNode, PropertyStatementSyntax)
 
            If propertyStatement Is Nothing Then
                Dim propertyBlock = TryCast(memberNode, PropertyBlockSyntax)
                If propertyBlock IsNot Nothing Then
                    propertyStatement = propertyBlock.PropertyStatement
                End If
            End If
 
            If propertyStatement IsNot Nothing Then
                If propertyStatement.Modifiers.Any(SyntaxKind.WriteOnlyKeyword) Then
                    Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindWriteOnly
                ElseIf propertyStatement.Modifiers.Any(SyntaxKind.ReadOnlyKeyword) Then
                    Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadOnly
                Else
                    Return EnvDTE80.vsCMPropertyKind.vsCMPropertyKindReadWrite
                End If
            End If
 
            Throw Exceptions.ThrowEUnexpected()
        End Function
 
        Private Shared Function SetDelegateType(delegateStatement As DelegateStatementSyntax, typeSymbol As ITypeSymbol) As DelegateStatementSyntax
            ' Remove the leading and trailing trivia and save it for reattachment later.
            Dim leadingTrivia = delegateStatement.GetLeadingTrivia()
            Dim trailingTrivia = delegateStatement.GetTrailingTrivia()
            delegateStatement = delegateStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            If typeSymbol Is Nothing Then
                ' If no type is specified (e.g. CodeElement.Type = Nothing), we just convert to a Sub
                ' if it isn't one already.
                If delegateStatement.IsKind(SyntaxKind.DelegateFunctionStatement) Then
                    delegateStatement = SyntaxFactory.DelegateSubStatement(
                        attributeLists:=delegateStatement.AttributeLists,
                        modifiers:=delegateStatement.Modifiers,
                        identifier:=delegateStatement.Identifier,
                        typeParameterList:=delegateStatement.TypeParameterList,
                        parameterList:=delegateStatement.ParameterList,
                        asClause:=Nothing)
                End If
            Else
                Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
                Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
                ' If this is a Sub, convert to a Function
                If delegateStatement.IsKind(SyntaxKind.DelegateSubStatement) Then
                    delegateStatement = SyntaxFactory.DelegateFunctionStatement(
                        attributeLists:=delegateStatement.AttributeLists,
                        modifiers:=delegateStatement.Modifiers,
                        identifier:=delegateStatement.Identifier,
                        typeParameterList:=delegateStatement.TypeParameterList,
                        parameterList:=delegateStatement.ParameterList,
                        asClause:=delegateStatement.AsClause)
                End If
 
                If delegateStatement.AsClause IsNot Nothing Then
                    Debug.Assert(TypeOf delegateStatement.AsClause Is SimpleAsClauseSyntax)
 
                    Dim oldType = DirectCast(delegateStatement.AsClause, SimpleAsClauseSyntax).Type
                    delegateStatement = delegateStatement.ReplaceNode(oldType, newType)
                Else
                    delegateStatement = delegateStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
                End If
            End If
 
            Return delegateStatement _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetEventType(eventStatement As EventStatementSyntax, typeSymbol As ITypeSymbol) As EventStatementSyntax
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
            ' Remove the leading and trailing trivia and save it for reattachment later.
            Dim leadingTrivia = eventStatement.GetLeadingTrivia()
            Dim trailingTrivia = eventStatement.GetTrailingTrivia()
            eventStatement = eventStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            ' If the event has a parameter list, we need to remove it.
            If eventStatement.ParameterList IsNot Nothing Then
                eventStatement = eventStatement.WithParameterList(Nothing)
            End If
 
            If eventStatement.AsClause IsNot Nothing Then
                Debug.Assert(TypeOf eventStatement.AsClause Is SimpleAsClauseSyntax)
 
                Dim oldType = DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type
                eventStatement = eventStatement.ReplaceNode(oldType, newType)
            Else
                eventStatement = eventStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
            End If
 
            Return eventStatement _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetEventType(eventBlock As EventBlockSyntax, typeSymbol As ITypeSymbol) As EventBlockSyntax
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            ' Update the event statement
            Dim eventStatement = eventBlock.EventStatement
            Dim leadingTrivia = eventStatement.GetLeadingTrivia()
            Dim trailingTrivia = eventStatement.GetTrailingTrivia()
            eventStatement = eventStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            If eventStatement.AsClause IsNot Nothing Then
                Debug.Assert(TypeOf eventStatement.AsClause Is SimpleAsClauseSyntax)
 
                Dim oldType = DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type
                eventStatement = eventStatement.ReplaceNode(oldType, newType)
            Else
                eventStatement = eventStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
            End If
 
            eventStatement = eventStatement _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
            eventBlock = eventBlock.WithEventStatement(eventStatement)
 
            For i = 0 To eventBlock.Accessors.Count - 1
                Dim accessorBlock = eventBlock.Accessors(i)
                Dim newAccessorBlock = accessorBlock
 
                If accessorBlock.Kind = SyntaxKind.AddHandlerAccessorBlock OrElse
                   accessorBlock.Kind = SyntaxKind.RemoveHandlerAccessorBlock Then
 
                    ' Update the first parameter of the AddHandler or RemoveHandler statements
                    Dim firstParameter = accessorBlock.BlockStatement.ParameterList.Parameters.FirstOrDefault()
                    If firstParameter IsNot Nothing Then
                        Dim newFirstParameter As ParameterSyntax
                        If firstParameter.AsClause IsNot Nothing Then
                            Debug.Assert(TypeOf firstParameter.AsClause Is SimpleAsClauseSyntax)
 
                            Dim oldType = DirectCast(firstParameter.AsClause, SimpleAsClauseSyntax).Type
                            newFirstParameter = firstParameter.ReplaceNode(oldType, newType)
                        Else
                            newFirstParameter = firstParameter.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
                        End If
 
                        newFirstParameter = newFirstParameter _
                            .WithLeadingTrivia(firstParameter.GetLeadingTrivia()) _
                            .WithTrailingTrivia(firstParameter.GetTrailingTrivia())
 
                        newAccessorBlock = accessorBlock.ReplaceNode(firstParameter, newFirstParameter)
                    End If
                ElseIf accessorBlock.Kind = SyntaxKind.RaiseEventAccessorBlock Then
                    ' For RaiseEvent, we replace the whole signature with the delegate's invoke method
 
                    Dim namedTypeSymbol = TryCast(typeSymbol, INamedTypeSymbol)
                    If namedTypeSymbol IsNot Nothing Then
                        Dim invokeMethod = namedTypeSymbol.DelegateInvokeMethod
                        If invokeMethod IsNot Nothing Then
                            Dim parameterStrings = invokeMethod.Parameters.Select(Function(p) p.ToDisplayString(s_raiseEventSignatureFormat))
                            Dim parameterListString = "("c & String.Join(", ", parameterStrings) & ")"c
                            Dim newParameterList = SyntaxFactory.ParseParameterList(parameterListString)
 
                            newParameterList = newParameterList.WithTrailingTrivia(accessorBlock.BlockStatement.ParameterList.GetTrailingTrivia())
                            newAccessorBlock = accessorBlock.ReplaceNode(accessorBlock.BlockStatement.ParameterList, newParameterList)
                        End If
                    End If
                End If
 
                If accessorBlock IsNot newAccessorBlock Then
                    eventBlock = eventBlock.ReplaceNode(accessorBlock, newAccessorBlock)
                End If
            Next
 
            Return eventBlock
        End Function
 
        Private Shared Function SetMethodType(declareStatement As DeclareStatementSyntax, typeSymbol As ITypeSymbol) As DeclareStatementSyntax
            ' Remove the leading and trailing trivia and save it for reattachment later.
            Dim leadingTrivia = declareStatement.GetLeadingTrivia()
            Dim trailingTrivia = declareStatement.GetTrailingTrivia()
            declareStatement = declareStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            If typeSymbol Is Nothing Then
                ' If no type is specified (e.g. CodeElement.Type = Nothing), we just convert to a Sub
                ' if it isn't one already.
                If declareStatement.IsKind(SyntaxKind.DeclareFunctionStatement) Then
                    declareStatement = SyntaxFactory.DeclareSubStatement(
                        attributeLists:=declareStatement.AttributeLists,
                        modifiers:=declareStatement.Modifiers,
                        declareKeyword:=declareStatement.DeclareKeyword,
                        charsetKeyword:=declareStatement.CharsetKeyword,
                        subOrFunctionKeyword:=SyntaxFactory.Token(SyntaxKind.SubKeyword),
                        identifier:=declareStatement.Identifier,
                        libKeyword:=declareStatement.LibKeyword,
                        libraryName:=declareStatement.LibraryName,
                        aliasKeyword:=declareStatement.AliasKeyword,
                        aliasName:=declareStatement.AliasName,
                        parameterList:=declareStatement.ParameterList,
                        asClause:=Nothing)
                End If
            Else
                Dim newType = SyntaxFactory.ParseTypeName(typeSymbol.ToDisplayString(s_setTypeFormat))
 
                declareStatement = SyntaxFactory.DeclareFunctionStatement(
                    attributeLists:=declareStatement.AttributeLists,
                    modifiers:=declareStatement.Modifiers,
                    declareKeyword:=declareStatement.DeclareKeyword,
                    charsetKeyword:=declareStatement.CharsetKeyword,
                    subOrFunctionKeyword:=SyntaxFactory.Token(SyntaxKind.FunctionKeyword),
                    identifier:=declareStatement.Identifier,
                    libKeyword:=declareStatement.LibKeyword,
                    libraryName:=declareStatement.LibraryName,
                    aliasKeyword:=declareStatement.AliasKeyword,
                    aliasName:=declareStatement.AliasName,
                    parameterList:=declareStatement.ParameterList,
                    asClause:=declareStatement.AsClause)
 
                If declareStatement.AsClause IsNot Nothing Then
                    Debug.Assert(TypeOf declareStatement.AsClause Is SimpleAsClauseSyntax)
 
                    Dim oldType = DirectCast(declareStatement.AsClause, SimpleAsClauseSyntax).Type
                    declareStatement = declareStatement.ReplaceNode(oldType, newType)
                Else
                    declareStatement = declareStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
                End If
            End If
 
            Return declareStatement.WithLeadingTrivia(leadingTrivia).WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetMethodType(methodStatement As MethodStatementSyntax, typeSymbol As ITypeSymbol) As MethodStatementSyntax
            ' Remove the leading and trailing trivia and save it for reattachment later.
            Dim leadingTrivia = methodStatement.GetLeadingTrivia()
            Dim trailingTrivia = methodStatement.GetTrailingTrivia()
            methodStatement = methodStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            If typeSymbol Is Nothing Then
                ' If no type is specified (e.g. CodeElement.Type = Nothing), we just convert to a Sub
                ' if it isn't one already.
                If methodStatement.IsKind(SyntaxKind.FunctionStatement) Then
                    methodStatement = SyntaxFactory.SubStatement(
                        attributeLists:=methodStatement.AttributeLists,
                        modifiers:=methodStatement.Modifiers,
                        identifier:=methodStatement.Identifier,
                        typeParameterList:=methodStatement.TypeParameterList,
                        parameterList:=methodStatement.ParameterList,
                        asClause:=Nothing,
                        handlesClause:=methodStatement.HandlesClause,
                        implementsClause:=methodStatement.ImplementsClause)
                End If
            Else
                Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
                Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
                ' If this is a Sub, convert to a Function
                If methodStatement.IsKind(SyntaxKind.SubStatement) Then
                    methodStatement = SyntaxFactory.FunctionStatement(
                        attributeLists:=methodStatement.AttributeLists,
                        modifiers:=methodStatement.Modifiers,
                        identifier:=methodStatement.Identifier,
                        typeParameterList:=methodStatement.TypeParameterList,
                        parameterList:=methodStatement.ParameterList,
                        asClause:=methodStatement.AsClause,
                        handlesClause:=methodStatement.HandlesClause,
                        implementsClause:=methodStatement.ImplementsClause)
                End If
 
                If methodStatement.AsClause IsNot Nothing Then
                    Debug.Assert(TypeOf methodStatement.AsClause Is SimpleAsClauseSyntax)
 
                    Dim oldType = DirectCast(methodStatement.AsClause, SimpleAsClauseSyntax).Type
                    methodStatement = methodStatement.ReplaceNode(oldType, newType)
                Else
                    methodStatement = methodStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
                End If
            End If
 
            Return methodStatement _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetMethodType(methodBlock As MethodBlockSyntax, typeSymbol As ITypeSymbol) As MethodBlockSyntax
            ' Remove the leading and trailing trivia and save it for reattachment later.
            Dim leadingTrivia = methodBlock.GetLeadingTrivia()
            Dim trailingTrivia = methodBlock.GetTrailingTrivia()
            methodBlock = methodBlock _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim methodStatement = SetMethodType(DirectCast(methodBlock.BlockStatement, MethodStatementSyntax), typeSymbol)
            Dim endMethodStatement = methodBlock.EndBlockStatement
 
            If endMethodStatement IsNot Nothing AndAlso Not endMethodStatement.IsMissing Then
                ' Note that we don't have to remove/replace the trailing trivia for the end block statement
                ' because we're already doing that for the whole block.
                If endMethodStatement.IsKind(SyntaxKind.EndSubStatement) AndAlso typeSymbol IsNot Nothing Then
                    endMethodStatement = SyntaxFactory.EndFunctionStatement()
                ElseIf endMethodStatement.IsKind(SyntaxKind.EndFunctionStatement) AndAlso typeSymbol Is Nothing Then
                    endMethodStatement = SyntaxFactory.EndSubStatement()
                End If
            End If
 
            methodBlock = methodBlock.Update(If(methodStatement.Kind = SyntaxKind.SubStatement, SyntaxKind.SubBlock, SyntaxKind.FunctionBlock),
                                             methodStatement, methodBlock.Statements, endMethodStatement)
 
            Return methodBlock _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetParameterType(parameter As ParameterSyntax, typeSymbol As ITypeSymbol) As ParameterSyntax
            If typeSymbol Is Nothing Then
                Return parameter
            End If
 
            ' Remove the leading and trailing trivia and save it for reattachment later.\
            Dim leadingTrivia = parameter.GetLeadingTrivia()
            Dim trailingTrivia = parameter.GetTrailingTrivia()
            parameter = parameter _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            If parameter.AsClause IsNot Nothing Then
                Debug.Assert(TypeOf parameter.AsClause Is SimpleAsClauseSyntax)
 
                Dim oldType = DirectCast(parameter.AsClause, SimpleAsClauseSyntax).Type
                parameter = parameter.ReplaceNode(oldType, newType)
            Else
                parameter = parameter.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
            End If
 
            Return parameter _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetPropertyType(propertyStatement As PropertyStatementSyntax, typeSymbol As ITypeSymbol) As PropertyStatementSyntax
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            ' Remove the leading and trailing trivia and save it for reattachment later.\
            Dim leadingTrivia = propertyStatement.GetLeadingTrivia()
            Dim trailingTrivia = propertyStatement.GetTrailingTrivia()
            propertyStatement = propertyStatement _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            If propertyStatement.AsClause IsNot Nothing Then
                Dim oldType = propertyStatement.AsClause.Type()
                If oldType IsNot Nothing Then
                    propertyStatement = propertyStatement.ReplaceNode(oldType, newType)
                End If
            Else
                propertyStatement = propertyStatement.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
            End If
 
            Return propertyStatement _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetPropertyType(propertyBlock As PropertyBlockSyntax, typeSymbol As ITypeSymbol) As PropertyBlockSyntax
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            ' Remove the leading and trailing trivia and save it for reattachment later.\
            Dim leadingTrivia = propertyBlock.GetLeadingTrivia()
            Dim trailingTrivia = propertyBlock.GetTrailingTrivia()
            propertyBlock = propertyBlock _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim propertyStatement = SetPropertyType(propertyBlock.PropertyStatement, typeSymbol)
            propertyBlock = propertyBlock.WithPropertyStatement(propertyStatement)
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            For i = 0 To propertyBlock.Accessors.Count - 1
                Dim accessorBlock = propertyBlock.Accessors(i)
                Dim newAccessorBlock = accessorBlock
 
                If accessorBlock.Kind = SyntaxKind.SetAccessorBlock Then
                    ' Update the first parameter of the SetAccessor statement
                    Dim firstParameter = accessorBlock.BlockStatement.ParameterList.Parameters.FirstOrDefault()
                    If firstParameter IsNot Nothing Then
                        Dim newFirstParameter As ParameterSyntax
                        If firstParameter.AsClause IsNot Nothing Then
                            Debug.Assert(TypeOf firstParameter.AsClause Is SimpleAsClauseSyntax)
 
                            Dim oldType = DirectCast(firstParameter.AsClause, SimpleAsClauseSyntax).Type
                            newFirstParameter = firstParameter.ReplaceNode(oldType, newType)
                        Else
                            newFirstParameter = firstParameter.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
                        End If
 
                        newFirstParameter = newFirstParameter _
                            .WithLeadingTrivia(firstParameter.GetLeadingTrivia()) _
                            .WithTrailingTrivia(firstParameter.GetTrailingTrivia())
 
                        newAccessorBlock = accessorBlock.ReplaceNode(firstParameter, newFirstParameter)
                    End If
                End If
 
                If accessorBlock IsNot newAccessorBlock Then
                    propertyBlock = propertyBlock.ReplaceNode(accessorBlock, newAccessorBlock)
                End If
            Next
 
            Return propertyBlock _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Private Shared Function SetVariableType(variableDeclarator As VariableDeclaratorSyntax, typeSymbol As ITypeSymbol) As VariableDeclaratorSyntax
            If typeSymbol Is Nothing Then
                Throw Exceptions.ThrowEInvalidArg()
            End If
 
            ' Remove the leading and trailing trivia and save it for reattachment later.\
            Dim leadingTrivia = variableDeclarator.GetLeadingTrivia()
            Dim trailingTrivia = variableDeclarator.GetTrailingTrivia()
            variableDeclarator = variableDeclarator _
                .WithLeadingTrivia(SyntaxTriviaList.Empty) _
                .WithTrailingTrivia(SyntaxTriviaList.Empty)
 
            Dim typeName = typeSymbol.ToDisplayString(s_setTypeFormat)
            Dim newType = SyntaxFactory.ParseTypeName(typeName)
 
            If variableDeclarator.AsClause IsNot Nothing Then
                Dim oldType = variableDeclarator.AsClause.Type()
                If oldType IsNot Nothing Then
                    variableDeclarator = variableDeclarator.ReplaceNode(oldType, newType)
                End If
            Else
                variableDeclarator = variableDeclarator.WithAsClause(SyntaxFactory.SimpleAsClause(newType))
            End If
 
            Return variableDeclarator _
                .WithLeadingTrivia(leadingTrivia) _
                .WithTrailingTrivia(trailingTrivia)
        End Function
 
        Public Overrides Function SetType(node As SyntaxNode, typeSymbol As ITypeSymbol) As SyntaxNode
            Debug.Assert(TypeOf node Is DelegateStatementSyntax OrElse
                         TypeOf node Is EventStatementSyntax OrElse
                         TypeOf node Is EventBlockSyntax OrElse
                         TypeOf node Is DeclareStatementSyntax OrElse
                         TypeOf node Is MethodStatementSyntax OrElse
                         TypeOf node Is MethodBlockBaseSyntax OrElse
                         TypeOf node Is ParameterSyntax OrElse
                         TypeOf node Is PropertyStatementSyntax OrElse
                         TypeOf node Is PropertyBlockSyntax OrElse
                         TypeOf node Is VariableDeclaratorSyntax)
 
            If TypeOf node Is DelegateStatementSyntax Then
                Return SetDelegateType(DirectCast(node, DelegateStatementSyntax), typeSymbol)
            End If
 
            If TypeOf node Is EventStatementSyntax Then
                Return SetEventType(DirectCast(node, EventStatementSyntax), typeSymbol)
            End If
 
            If TypeOf node Is EventBlockSyntax Then
                Return SetEventType(DirectCast(node, EventBlockSyntax), typeSymbol)
            End If
 
            If TypeOf node Is DeclareStatementSyntax Then
                Return SetMethodType(DirectCast(node, DeclareStatementSyntax), typeSymbol)
            End If
 
            If TypeOf node Is MethodStatementSyntax Then
                Return SetMethodType(DirectCast(node, MethodStatementSyntax), typeSymbol)
            End If
 
            If TypeOf node Is MethodBlockSyntax Then
                Return SetMethodType(DirectCast(node, MethodBlockSyntax), typeSymbol)
            End If
 
            If TypeOf node Is ConstructorBlockSyntax Then
                Return node
            End If
 
            If TypeOf node Is OperatorBlockSyntax Then
                Return node
            End If
 
            If TypeOf node Is ParameterSyntax Then
                Return SetParameterType(DirectCast(node, ParameterSyntax), typeSymbol)
            End If
 
            If TypeOf node Is PropertyStatementSyntax Then
                Return SetPropertyType(DirectCast(node, PropertyStatementSyntax), typeSymbol)
            End If
 
            If TypeOf node Is PropertyBlockSyntax Then
                Return SetPropertyType(DirectCast(node, PropertyBlockSyntax), typeSymbol)
            End If
 
            If TypeOf node Is VariableDeclaratorSyntax Then
                Return SetVariableType(DirectCast(node, VariableDeclaratorSyntax), typeSymbol)
            End If
 
            Throw New NotImplementedException()
        End Function
 
        Public Overrides Function GetFullyQualifiedName(name As String, position As Integer, semanticModel As SemanticModel) As String
            Dim typeName = SyntaxFactory.ParseTypeName(name)
            If TypeOf typeName Is PredefinedTypeSyntax Then
                Dim predefinedType As PredefinedType
                If SyntaxFactsService.TryGetPredefinedType(DirectCast(typeName, PredefinedTypeSyntax).Keyword, predefinedType) Then
                    Dim specialType = predefinedType.ToSpecialType()
                    Return semanticModel.Compilation.GetSpecialType(specialType).GetEscapedFullName()
                End If
            Else
                Dim symbols = semanticModel.LookupNamespacesAndTypes(position, name:=name)
                If symbols.Length > 0 Then
                    Return symbols(0).GetEscapedFullName()
                End If
            End If
 
            Return name
        End Function
 
        Public Overrides Function GetInitExpression(node As SyntaxNode) As String
            Dim initializer As ExpressionSyntax = Nothing
 
            Select Case node.Kind
                Case SyntaxKind.Parameter
                    Dim parameter = DirectCast(node, ParameterSyntax)
                    If parameter.Default IsNot Nothing Then
                        initializer = parameter.Default.Value
                    End If
 
                Case SyntaxKind.ModifiedIdentifier
                    Dim modifiedIdentifier = DirectCast(node, ModifiedIdentifierSyntax)
                    Dim variableDeclarator = DirectCast(modifiedIdentifier.Parent, VariableDeclaratorSyntax)
                    initializer = variableDeclarator.GetInitializer()
 
                Case SyntaxKind.EnumMemberDeclaration
                    Dim enumMemberDeclaration = DirectCast(node, EnumMemberDeclarationSyntax)
                    If enumMemberDeclaration.Initializer IsNot Nothing Then
                        initializer = enumMemberDeclaration.Initializer.Value
                    End If
            End Select
 
            Return If(initializer IsNot Nothing,
                      initializer.ToString(),
                      Nothing)
        End Function
 
        Public Overrides Function AddInitExpression(node As SyntaxNode, value As String) As SyntaxNode
            Select Case node.Kind
                Case SyntaxKind.Parameter
                    Dim parameter = DirectCast(node, ParameterSyntax)
 
                    Dim parameterKind = GetParameterKind(parameter)
                    If Not (parameterKind And EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional) <> 0 Then
                        Throw Exceptions.ThrowEInvalidArg
                    End If
 
                    If String.IsNullOrWhiteSpace(value) Then
                        ' Remove the Optional modifier
                        parameterKind = parameterKind And Not EnvDTE80.vsCMParameterKind.vsCMParameterKindOptional
                        parameter = DirectCast(SetParameterKind(parameter, parameterKind), ParameterSyntax)
 
                        If parameter.Default IsNot Nothing Then
                            parameter = parameter.RemoveNode(parameter.Default, SyntaxRemoveOptions.KeepNoTrivia)
                        End If
 
                        Return parameter
                    End If
 
                    Dim expression = SyntaxFactory.ParseExpression(value)
 
                    Dim equalsValueClause = If(parameter.Default IsNot Nothing AndAlso Not parameter.Default.IsMissing,
                                               parameter.Default.WithValue(expression),
                                               SyntaxFactory.EqualsValue(expression))
 
                    Return parameter.WithDefault(equalsValueClause)
 
                Case SyntaxKind.VariableDeclarator
                    Dim variableDeclarator = DirectCast(node, VariableDeclaratorSyntax)
 
                    If String.IsNullOrWhiteSpace(value) Then
                        If variableDeclarator.Initializer IsNot Nothing Then
                            variableDeclarator = variableDeclarator.RemoveNode(variableDeclarator.Initializer, SyntaxRemoveOptions.KeepExteriorTrivia)
                        End If
 
                        Return variableDeclarator
                    End If
 
                    Dim trailingTrivia = variableDeclarator.GetTrailingTrivia()
                    variableDeclarator = variableDeclarator.WithTrailingTrivia(SyntaxTriviaList.Empty)
 
                    Dim expression = SyntaxFactory.ParseExpression(value)
 
                    Dim equalsValueClause = If(variableDeclarator.Initializer IsNot Nothing AndAlso Not variableDeclarator.Initializer.IsMissing,
                                               variableDeclarator.Initializer.WithValue(expression),
                                               SyntaxFactory.EqualsValue(expression)).WithTrailingTrivia(trailingTrivia)
 
                    Return variableDeclarator.WithInitializer(equalsValueClause)
 
                Case SyntaxKind.EnumMemberDeclaration
                    Dim enumMemberDeclaration = DirectCast(node, EnumMemberDeclarationSyntax)
 
                    If String.IsNullOrWhiteSpace(value) Then
                        If enumMemberDeclaration.Initializer IsNot Nothing Then
                            enumMemberDeclaration = enumMemberDeclaration.RemoveNode(enumMemberDeclaration.Initializer, SyntaxRemoveOptions.KeepExteriorTrivia)
                        End If
 
                        Return enumMemberDeclaration
                    End If
 
                    Dim trailingTrivia = enumMemberDeclaration.GetTrailingTrivia()
                    enumMemberDeclaration = enumMemberDeclaration.WithTrailingTrivia(SyntaxTriviaList.Empty)
 
                    Dim expression = SyntaxFactory.ParseExpression(value)
 
                    Dim equalsValueClause = If(enumMemberDeclaration.Initializer IsNot Nothing AndAlso Not enumMemberDeclaration.Initializer.IsMissing,
                                               enumMemberDeclaration.Initializer.WithValue(expression),
                                               SyntaxFactory.EqualsValue(expression)).WithTrailingTrivia(trailingTrivia)
 
                    Return enumMemberDeclaration.WithInitializer(equalsValueClause)
 
                Case Else
                    Throw Exceptions.ThrowEFail()
            End Select
        End Function
 
        Public Overrides Function GetDestination(containerNode As SyntaxNode) As CodeGenerationDestination
            Return VisualBasicCodeGenerationHelpers.GetDestination(containerNode)
        End Function
 
        Protected Overrides Function GetDefaultAccessibility(targetSymbolKind As SymbolKind, destination As CodeGenerationDestination) As Accessibility
            If destination = CodeGenerationDestination.StructType Then
                Return Accessibility.Public
            End If
 
            Select Case targetSymbolKind
                Case SymbolKind.Field
                    Return Accessibility.Private
                Case SymbolKind.Method,
                     SymbolKind.Property,
                     SymbolKind.Event,
                     SymbolKind.NamedType
                    Return Accessibility.Public
                Case Else
                    Debug.Fail("Invalid symbol kind: " & targetSymbolKind)
                    Throw Exceptions.ThrowEFail()
            End Select
        End Function
 
        Public Overrides Function GetTypeSymbolFromFullName(fullName As String, compilation As Compilation) As ITypeSymbol
            Dim typeSymbol As ITypeSymbol = compilation.GetTypeByMetadataName(fullName)
 
            If typeSymbol Is Nothing Then
                Dim parsedTypeName = SyntaxFactory.ParseTypeName(fullName)
 
                ' Check to see if the name we parsed has any skipped text. If it does, don't bother trying to
                ' speculatively bind it because we'll likely just get the wrong thing since we found a bunch
                ' of non-sensical tokens.
 
                ' NOTE: There appears to be a VB parser issue where "ContainsSkippedText" does not return true
                ' even when there is clearly skipped token trivia present. We work around this by for a particularly
                ' common case by checking whether the trailing trivia contains any skipped token trivia.
                ' https://github.com/dotnet/roslyn/issues/7182 has been filed for the parser issue.
 
                If parsedTypeName.ContainsSkippedText OrElse
                   parsedTypeName.GetTrailingTrivia().Any(SyntaxKind.SkippedTokensTrivia) Then
 
                    Return Nothing
                End If
 
                ' If we couldn't get the name, we just grab the first tree in the compilation to
                ' speculatively bind at position zero. However, if there *aren't* any trees, we fork the
                ' compilation with an empty tree for the purposes of speculative binding.
                '
                ' I'm a bad person.
                Dim tree = compilation.SyntaxTrees.FirstOrDefault()
                If tree Is Nothing Then
                    tree = s_emptyTree
                    compilation = compilation.AddSyntaxTrees(tree)
                End If
 
                Dim semanticModel = compilation.GetSemanticModel(tree)
                typeSymbol = semanticModel.GetSpeculativeTypeInfo(0, parsedTypeName, SpeculativeBindingOption.BindAsTypeOrNamespace).Type
            End If
 
            If typeSymbol Is Nothing Then
                Debug.Fail("Could not find type: " & fullName)
                Throw New ArgumentException()
            End If
 
            Return typeSymbol
        End Function
 
        Protected Overrides Function GetTypeSymbolFromPartialName(partialName As String, semanticModel As SemanticModel, position As Integer) As ITypeSymbol
            Dim parsedTypeName = SyntaxFactory.ParseTypeName(partialName)
 
            Return semanticModel.GetSpeculativeTypeInfo(position, parsedTypeName, SpeculativeBindingOption.BindAsTypeOrNamespace).Type
        End Function
 
        Public Overrides Function CreateReturnDefaultValueStatement(type As ITypeSymbol) As SyntaxNode
            Return SyntaxFactory.ReturnStatement(
                SyntaxFactory.NothingLiteralExpression(
                    SyntaxFactory.Token(SyntaxKind.NothingKeyword)))
        End Function
 
        Protected Overrides Function IsCodeModelNode(node As SyntaxNode) As Boolean
            Select Case CType(node.Kind, SyntaxKind)
                Case SyntaxKind.ClassBlock,
                     SyntaxKind.ConstructorBlock,
                     SyntaxKind.DeclareFunctionStatement,
                     SyntaxKind.DeclareSubStatement,
                     SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement,
                     SyntaxKind.EnumBlock,
                     SyntaxKind.EnumMemberDeclaration,
                     SyntaxKind.EventBlock,
                     SyntaxKind.EventStatement,
                     SyntaxKind.FieldDeclaration,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.InterfaceBlock,
                     SyntaxKind.ModuleBlock,
                     SyntaxKind.NamespaceBlock,
                     SyntaxKind.OperatorBlock,
                     SyntaxKind.PropertyBlock,
                     SyntaxKind.StructureBlock,
                     SyntaxKind.SubBlock,
                     SyntaxKind.SimpleImportsClause
                    Return True
 
                Case Else
                    Return False
            End Select
        End Function
 
        Protected Overrides Function GetFieldFromVariableNode(variableNode As SyntaxNode) As SyntaxNode
            Return If(variableNode.Kind = SyntaxKind.ModifiedIdentifier,
                      variableNode.FirstAncestorOrSelf(Of FieldDeclarationSyntax)(),
                      variableNode)
        End Function
 
        Protected Overrides Function GetVariableFromFieldNode(fieldNode As SyntaxNode) As SyntaxNode
            ' Work around that the fact that VB code model really deals with fields as modified identifiers
            Return If(TypeOf fieldNode Is FieldDeclarationSyntax,
                      DirectCast(fieldNode, FieldDeclarationSyntax).Declarators.Single().Names.Single(),
                      fieldNode)
        End Function
 
        Protected Overrides Function GetAttributeFromAttributeDeclarationNode(node As SyntaxNode) As SyntaxNode
            Return If(TypeOf node Is AttributeListSyntax,
                      DirectCast(node, AttributeListSyntax).Attributes.First,
                      node)
        End Function
 
        Protected Overrides Function GetSpanToFormat(root As SyntaxNode, span As TextSpan) As TextSpan
            Dim startToken = GetTokenWithoutAnnotation(root.FindToken(span.Start).GetPreviousToken(), Function(t) t.GetPreviousToken())
            Dim endToken = GetTokenWithoutAnnotation(root.FindToken(span.End), Function(t) t.GetNextToken())
 
            Return GetEncompassingSpan(root, startToken, endToken)
        End Function
 
        Protected Overrides Function InsertMemberNodeIntoContainer(index As Integer, member As SyntaxNode, container As SyntaxNode) As SyntaxNode
            Dim declarationStatement = DirectCast(member, DeclarationStatementSyntax)
 
            If TypeOf container Is CompilationUnitSyntax Then
                Dim compilationUnit = DirectCast(container, CompilationUnitSyntax)
 
                Return compilationUnit.WithMembers(compilationUnit.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is NamespaceBlockSyntax Then
                Dim namespaceBlock = DirectCast(container, NamespaceBlockSyntax)
 
                Return namespaceBlock.WithMembers(namespaceBlock.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is ClassBlockSyntax Then
                Dim classBlock = DirectCast(container, ClassBlockSyntax)
 
                Return classBlock.WithMembers(classBlock.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is InterfaceBlockSyntax Then
                Dim interfaceBlock = DirectCast(container, InterfaceBlockSyntax)
 
                Return interfaceBlock.WithMembers(interfaceBlock.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is StructureBlockSyntax Then
                Dim structureBlock = DirectCast(container, StructureBlockSyntax)
 
                Return structureBlock.WithMembers(structureBlock.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is ModuleBlockSyntax Then
                Dim moduleBlock = DirectCast(container, ModuleBlockSyntax)
 
                Return moduleBlock.WithMembers(moduleBlock.Members.Insert(index, declarationStatement))
            ElseIf TypeOf container Is EnumBlockSyntax Then
                Dim enumBlock = DirectCast(container, EnumBlockSyntax)
 
                Return enumBlock.WithMembers(enumBlock.Members.Insert(index, declarationStatement))
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Protected Overrides Function InsertAttributeArgumentIntoContainer(index As Integer, attributeArgument As SyntaxNode, container As SyntaxNode) As SyntaxNode
            If TypeOf container Is AttributeSyntax Then
                Dim attribute = DirectCast(container, AttributeSyntax)
                Dim argumentList = attribute.ArgumentList
 
                Dim newArgumentList As ArgumentListSyntax
 
                If argumentList Is Nothing Then
                    newArgumentList = SyntaxFactory.ArgumentList(
                                        SyntaxFactory.SingletonSeparatedList(
                                            DirectCast(attributeArgument, ArgumentSyntax)))
                Else
                    Dim newArguments = argumentList.Arguments.Insert(index, DirectCast(attributeArgument, ArgumentSyntax))
                    newArgumentList = argumentList.WithArguments(newArguments)
                End If
 
                Return attribute.WithArgumentList(newArgumentList)
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Private Shared Function InsertAttributeListInto(attributes As SyntaxList(Of AttributesStatementSyntax), index As Integer, attribute As AttributesStatementSyntax) As SyntaxList(Of AttributesStatementSyntax)
            ' we need to explicitly add end of line trivia here since both of them (with or without) are valid but parsed differently
            If index = 0 Then
                Return attributes.Insert(index, attribute)
            End If
 
            Dim previousAttribute = attributes(index - 1)
            If previousAttribute.GetTrailingTrivia().Any(Function(t) t.Kind = SyntaxKind.EndOfLineTrivia) Then
                Return attributes.Insert(index, attribute)
            End If
 
            attributes = attributes.Replace(previousAttribute, previousAttribute.WithAppendedTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed))
            Return attributes.Insert(index, attribute)
        End Function
 
        Protected Overrides Function InsertAttributeListIntoContainer(index As Integer, list As SyntaxNode, container As SyntaxNode) As SyntaxNode
            ' If the attribute is being inserted at the first index and the container is not the compilation unit, copy leading trivia
            ' to the attribute that is being inserted.
            If index = 0 AndAlso TypeOf container IsNot CompilationUnitSyntax Then
                Dim firstToken = container.GetFirstToken()
                If firstToken.HasLeadingTrivia Then
                    Dim trivia = firstToken.LeadingTrivia
 
                    container = container.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(SyntaxTriviaList.Empty))
                    list = list.WithLeadingTrivia(trivia)
                End If
            End If
 
            ' If the attribute to be inserted does not have a trailing line break, add one (unless this is a parameter).
            If TypeOf container IsNot ParameterSyntax AndAlso
               (Not list.HasTrailingTrivia OrElse Not list.GetTrailingTrivia().Any(SyntaxKind.EndOfLineTrivia)) Then
 
                list = list.WithAppendedTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)
            End If
 
            Dim attributeList = DirectCast(list, AttributeListSyntax)
 
            If TypeOf container Is CompilationUnitSyntax Then
                Dim compilationUnit = DirectCast(container, CompilationUnitSyntax)
                Dim attributesStatement = SyntaxFactory.AttributesStatement(SyntaxFactory.SingletonList(attributeList))
                Dim attributeStatements = InsertAttributeListInto(compilationUnit.Attributes, index, attributesStatement)
                Return compilationUnit.WithAttributes(attributeStatements)
            ElseIf TypeOf container Is ModuleBlockSyntax Then
                Dim moduleBlock = DirectCast(container, ModuleBlockSyntax)
                Dim attributeLists = moduleBlock.ModuleStatement.AttributeLists.Insert(index, attributeList)
                Return moduleBlock.WithBlockStatement(moduleBlock.ModuleStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is StructureBlockSyntax Then
                Dim structureBlock = DirectCast(container, StructureBlockSyntax)
                Dim attributeLists = structureBlock.StructureStatement.AttributeLists.Insert(index, attributeList)
                Return structureBlock.WithStructureStatement(structureBlock.StructureStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is InterfaceBlockSyntax Then
                Dim interfaceBlock = DirectCast(container, InterfaceBlockSyntax)
                Dim attributeLists = interfaceBlock.InterfaceStatement.AttributeLists.Insert(index, attributeList)
                Return interfaceBlock.WithInterfaceStatement(interfaceBlock.InterfaceStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is ClassBlockSyntax Then
                Dim classBlock = DirectCast(container, ClassBlockSyntax)
                Dim attributeLists = classBlock.ClassStatement.AttributeLists.Insert(index, attributeList)
                Dim begin = classBlock.ClassStatement.WithAttributeLists(attributeLists)
                Return classBlock.WithClassStatement(begin)
            ElseIf TypeOf container Is EnumBlockSyntax Then
                Dim enumBlock = DirectCast(container, EnumBlockSyntax)
                Dim attributeLists = enumBlock.EnumStatement.AttributeLists.Insert(index, attributeList)
                Return enumBlock.WithEnumStatement(enumBlock.EnumStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is EnumMemberDeclarationSyntax Then
                Dim enumMember = DirectCast(container, EnumMemberDeclarationSyntax)
                Dim attributeLists = enumMember.AttributeLists.Insert(index, attributeList)
                Return enumMember.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is DelegateStatementSyntax Then
                Dim delegateStatement = DirectCast(container, DelegateStatementSyntax)
                Dim attributeLists = delegateStatement.AttributeLists.Insert(index, attributeList)
                Return delegateStatement.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is DeclareStatementSyntax Then
                Dim declareStatement = DirectCast(container, DeclareStatementSyntax)
                Dim attributeLists = declareStatement.AttributeLists.Insert(index, attributeList)
                Return declareStatement.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is MethodStatementSyntax Then
                Dim methodStatement = DirectCast(container, MethodStatementSyntax)
                Dim attributeLists = methodStatement.AttributeLists.Insert(index, attributeList)
                Return methodStatement.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is MethodBlockBaseSyntax Then
                Dim method = DirectCast(container, MethodBlockBaseSyntax)
                If TypeOf method.BlockStatement Is SubNewStatementSyntax Then
                    Dim constructor = DirectCast(method.BlockStatement, SubNewStatementSyntax)
                    Dim attributeLists = constructor.AttributeLists.Insert(index, attributeList)
                    Return DirectCast(method, ConstructorBlockSyntax).WithBlockStatement(constructor.WithAttributeLists(attributeLists))
                ElseIf TypeOf method.BlockStatement Is OperatorStatementSyntax Then
                    Dim operatorStatement = DirectCast(method.BlockStatement, OperatorStatementSyntax)
                    Dim attributeLists = operatorStatement.AttributeLists.Insert(index, attributeList)
                    Return DirectCast(method, OperatorBlockSyntax).WithBlockStatement(operatorStatement.WithAttributeLists(attributeLists))
                ElseIf TypeOf method.BlockStatement Is MethodStatementSyntax Then
                    Dim methodStatement = DirectCast(method.BlockStatement, MethodStatementSyntax)
                    Dim attributeLists = methodStatement.AttributeLists.Insert(index, attributeList)
                    Return DirectCast(method, MethodBlockSyntax).WithBlockStatement(methodStatement.WithAttributeLists(attributeLists))
                End If
            ElseIf TypeOf container Is PropertyStatementSyntax Then
                Dim propertyStatement = DirectCast(container, PropertyStatementSyntax)
                Dim attributeLists = propertyStatement.AttributeLists.Insert(index, attributeList)
                Return propertyStatement.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is PropertyBlockSyntax Then
                Dim propertyBlock = DirectCast(container, PropertyBlockSyntax)
                Dim attributeLists = propertyBlock.PropertyStatement.AttributeLists.Insert(index, attributeList)
                Return propertyBlock.WithPropertyStatement(propertyBlock.PropertyStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is EventStatementSyntax Then
                Dim eventStatement = DirectCast(container, EventStatementSyntax)
                Dim attributeLists = eventStatement.AttributeLists.Insert(index, attributeList)
                Return eventStatement.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is EventBlockSyntax Then
                Dim eventBlock = DirectCast(container, EventBlockSyntax)
                Dim attributeLists = eventBlock.EventStatement.AttributeLists.Insert(index, attributeList)
                Return eventBlock.WithEventStatement(eventBlock.EventStatement.WithAttributeLists(attributeLists))
            ElseIf TypeOf container Is FieldDeclarationSyntax Then
                Dim field = DirectCast(container, FieldDeclarationSyntax)
                Dim attributeLists = field.AttributeLists.Insert(index, attributeList)
                Return field.WithAttributeLists(attributeLists)
            ElseIf TypeOf container Is ParameterSyntax Then
                Dim parameter = DirectCast(container, ParameterSyntax)
                Dim attributeLists = parameter.AttributeLists.Insert(index, attributeList)
                Return parameter.WithAttributeLists(attributeLists)
            End If
 
            Throw Exceptions.ThrowEUnexpected()
        End Function
 
        Protected Overrides Function InsertImportIntoContainer(index As Integer, importNode As SyntaxNode, container As SyntaxNode) As SyntaxNode
            If TypeOf container IsNot CompilationUnitSyntax Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim compilationUnit = DirectCast(container, CompilationUnitSyntax)
            Dim importsStatement = DirectCast(importNode, ImportsStatementSyntax)
 
            Dim lastToken = importsStatement.GetLastToken()
            If lastToken.Kind <> SyntaxKind.EndOfLineTrivia Then
                importsStatement = importsStatement.ReplaceToken(lastToken, lastToken.WithAppendedTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed))
            End If
 
            Dim importsList = compilationUnit.Imports.Insert(index, importsStatement)
            Return compilationUnit.WithImports(importsList)
        End Function
 
        Private Shared Function InsertParameterIntoParameterList(index As Integer, parameter As ParameterSyntax, list As ParameterListSyntax) As ParameterListSyntax
            If list Is Nothing Then
                Return SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList(parameter)) _
                    .WithAdditionalAnnotations(Formatter.Annotation)
            End If
 
            Dim parameters = list.Parameters.Insert(index, parameter)
            Return list.WithParameters(parameters)
        End Function
 
        Protected Overrides Function InsertParameterIntoContainer(index As Integer, parameter As SyntaxNode, container As SyntaxNode) As SyntaxNode
            Dim parameterNode = DirectCast(parameter, ParameterSyntax)
 
            If TypeOf container Is MethodBaseSyntax Then
                Dim methodStatement = DirectCast(container, MethodBaseSyntax)
                Dim parameterList = InsertParameterIntoParameterList(index, parameterNode, methodStatement.ParameterList)
                Return methodStatement.WithParameterList(parameterList)
            ElseIf TypeOf container Is MethodBlockBaseSyntax Then
                Dim methodBlock = DirectCast(container, MethodBlockBaseSyntax)
                Dim methodStatement = methodBlock.BlockStatement
                Dim parameterList = InsertParameterIntoParameterList(index, parameterNode, methodStatement.ParameterList)
                methodStatement = methodStatement.WithParameterList(parameterList)
 
                Select Case methodBlock.Kind
                    Case SyntaxKind.SubBlock, SyntaxKind.FunctionBlock
                        Return DirectCast(methodBlock, MethodBlockSyntax).WithBlockStatement(DirectCast(methodStatement, MethodStatementSyntax))
                    Case SyntaxKind.ConstructorBlock
                        Return DirectCast(methodBlock, ConstructorBlockSyntax).WithBlockStatement(DirectCast(methodStatement, SubNewStatementSyntax))
                    Case SyntaxKind.OperatorBlock
                        Return DirectCast(methodBlock, OperatorBlockSyntax).WithBlockStatement(DirectCast(methodStatement, OperatorStatementSyntax))
                    Case Else
                        Return DirectCast(methodBlock, AccessorBlockSyntax).WithBlockStatement(DirectCast(methodStatement, AccessorStatementSyntax))
                End Select
            ElseIf TypeOf container Is PropertyBlockSyntax Then
                Dim propertyBlock = DirectCast(container, PropertyBlockSyntax)
                Dim propertyStatement = propertyBlock.PropertyStatement
                Dim parameterList = InsertParameterIntoParameterList(index, parameterNode, propertyStatement.ParameterList)
                propertyStatement = propertyStatement.WithParameterList(parameterList)
                Return propertyBlock.WithPropertyStatement(propertyStatement)
            End If
 
            Throw Exceptions.ThrowEUnexpected()
        End Function
 
        Public Overrides Function IsNamespace(node As SyntaxNode) As Boolean
            Return TypeOf node Is NamespaceBlockSyntax
        End Function
 
        Public Overrides Function IsType(node As SyntaxNode) As Boolean
            Return TypeOf node Is TypeBlockSyntax OrElse
                   TypeOf node Is EnumBlockSyntax
        End Function
 
        Public Overrides Function GetMethodXml(node As SyntaxNode, semanticModel As SemanticModel) As String
            Dim methodBlock = TryCast(node, MethodBlockBaseSyntax)
            If methodBlock Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Return MethodXmlBuilder.Generate(methodBlock, semanticModel)
        End Function
 
        Private Shared Function GetMethodStatement(method As SyntaxNode) As MethodStatementSyntax
            Dim methodBlock = TryCast(method, MethodBlockBaseSyntax)
            If methodBlock Is Nothing Then
                Return Nothing
            End If
 
            Return TryCast(methodBlock.BlockStatement, MethodStatementSyntax)
        End Function
 
        Private Overloads Shared Function GetHandledEventNames(methodStatement As MethodStatementSyntax) As IList(Of String)
            If methodStatement Is Nothing OrElse
               methodStatement.HandlesClause Is Nothing OrElse
               methodStatement.HandlesClause.Events.Count = 0 Then
                Return SpecializedCollections.EmptyList(Of String)()
            End If
 
            Dim eventCount = methodStatement.HandlesClause.Events.Count
            Dim result(eventCount - 1) As String
            For i = 0 To eventCount - 1
                Dim handlesItem = methodStatement.HandlesClause.Events(i)
                result(i) = handlesItem.EventContainer.ToString() & "."c & handlesItem.EventMember.ToString()
            Next
 
            Return result
        End Function
 
        Private Shared Function EscapeIfNotMeMyBaseOrMyClass(identifier As String) As String
            Select Case SyntaxFacts.GetKeywordKind(identifier)
                Case SyntaxKind.MeKeyword,
                     SyntaxKind.MyBaseKeyword,
                     SyntaxKind.MyClassKeyword,
                     SyntaxKind.None
 
                    Return identifier
 
                Case Else
                    Return "["c & identifier & "]"c
            End Select
        End Function
 
        Private Shared Function MakeHandledEventName(parentName As String, eventName As String) As String
            If eventName.Length >= parentName.Length Then
                If CaseInsensitiveComparison.Equals(eventName.Substring(0, parentName.Length), parentName) Then
                    Return "MyBase" & eventName.Substring(parentName.Length)
                End If
            End If
 
            ' If eventName starts with an unescaped keyword other than Me, MyBase or MyClass, we need to escape it.
            If Not eventName.StartsWith("[", StringComparison.Ordinal) Then
                Dim dotIndex = eventName.IndexOf("."c)
                If dotIndex >= 0 Then
                    Return EscapeIfNotMeMyBaseOrMyClass(eventName.Substring(0, dotIndex)) & eventName.Substring(dotIndex)
                Else
                    EscapeIfNotMeMyBaseOrMyClass(eventName)
                End If
            End If
 
            Return eventName
        End Function
 
        Public Overrides Function AddHandlesClause(document As Document, eventName As String, method As SyntaxNode, cancellationToken As CancellationToken) As Document
            Dim methodStatement = GetMethodStatement(method)
 
            Dim parentTypeBlock = TryCast(method.Parent, TypeBlockSyntax)
            If parentTypeBlock Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim parentName = parentTypeBlock.BlockStatement.Identifier.ToString()
            Dim newEventName = MakeHandledEventName(parentName, eventName)
 
            Dim position As Integer
            Dim textToInsert As String
            If methodStatement.HandlesClause Is Nothing Then
                position = methodStatement.ParameterList.CloseParenToken.Span.End
                textToInsert = " Handles " & newEventName
            Else
                position = methodStatement.HandlesClause.Span.End
                textToInsert = ", " & newEventName
            End If
 
            Dim text = document.GetTextSynchronously(cancellationToken)
 
            text = text.Replace(position, 0, textToInsert)
 
            Return document.WithText(text)
        End Function
 
        Public Overrides Function RemoveHandlesClause(document As Document, eventName As String, method As SyntaxNode, cancellationToken As CancellationToken) As Document
            Dim methodStatement = GetMethodStatement(method)
 
            Dim parentTypeBlock = TryCast(method.Parent, TypeBlockSyntax)
            If parentTypeBlock Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim parentName = parentTypeBlock.BlockStatement.Identifier.ToString()
            Dim newEventName = MakeHandledEventName(parentName, eventName)
 
            If methodStatement.HandlesClause Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim indexOfDot = newEventName.IndexOf("."c)
            If indexOfDot = -1 Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim containerName = newEventName.Substring(0, indexOfDot)
            Dim memberName = newEventName.Substring(indexOfDot + 1)
 
            Dim clauseItemToRemove As HandlesClauseItemSyntax = Nothing
            For Each handlesClauseItem In methodStatement.HandlesClause.Events
                If handlesClauseItem.EventContainer.ToString() = containerName AndAlso
                    handlesClauseItem.EventMember.ToString() = memberName Then
 
                    clauseItemToRemove = handlesClauseItem
                    Exit For
                End If
            Next
 
            If clauseItemToRemove Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            Dim text = document.GetTextSynchronously(cancellationToken)
 
            If methodStatement.HandlesClause.Events.Count = 1 Then
                ' Easy case, delete the whole clause
                text = text.Replace(methodStatement.HandlesClause.Span, String.Empty)
            Else
                ' Harder case, remove it from the list.  If it's the first one, remove the following
                ' comma, else remove the preceding comma.
                Dim index = methodStatement.HandlesClause.Events.IndexOf(clauseItemToRemove)
                If index = 0 Then
                    text = text.Replace(TextSpan.FromBounds(clauseItemToRemove.SpanStart, methodStatement.HandlesClause.Events.GetSeparator(0).Span.End), String.Empty)
                Else
                    text = text.Replace(TextSpan.FromBounds(methodStatement.HandlesClause.Events.GetSeparator(index - 1).SpanStart, clauseItemToRemove.Span.End), String.Empty)
                End If
            End If
 
            Return document.WithText(text)
        End Function
 
        Public Overloads Overrides Function GetHandledEventNames(method As SyntaxNode, semanticModel As SemanticModel) As IList(Of String)
            Dim methodStatement = GetMethodStatement(method)
 
            Return GetHandledEventNames(methodStatement)
        End Function
 
        Public Overrides Function HandlesEvent(eventName As String, method As SyntaxNode, semanticModel As SemanticModel) As Boolean
            Dim methodStatement = GetMethodStatement(method)
            Dim handledEventNames = GetHandledEventNames(methodStatement)
 
            For Each handledEventName In handledEventNames
                If CaseInsensitiveComparison.Equals(eventName, handledEventName) Then
                    Return True
                End If
            Next
 
            Return False
        End Function
 
        Public Overrides Function GetFunctionExtenderNames() As String()
            Return {ExtenderNames.VBPartialMethodExtender}
        End Function
 
        Public Overrides Function GetFunctionExtender(name As String, node As SyntaxNode, symbol As ISymbol) As Object
            If Not TypeOf node Is MethodBlockBaseSyntax AndAlso
               Not TypeOf node Is MethodStatementSyntax AndAlso
               Not TypeOf symbol Is IMethodSymbol Then
 
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            If StringComparer.OrdinalIgnoreCase.Equals(name, ExtenderNames.VBPartialMethodExtender) Then
                Dim methodSymbol = DirectCast(symbol, IMethodSymbol)
                Dim isPartial = methodSymbol.PartialDefinitionPart IsNot Nothing OrElse methodSymbol.PartialImplementationPart IsNot Nothing
                Dim isDeclaration = If(isPartial,
                                       methodSymbol.PartialDefinitionPart Is Nothing,
                                       False)
 
                Return PartialMethodExtender.Create(isDeclaration, isPartial)
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Public Overrides Function GetPropertyExtenderNames() As String()
            Return {ExtenderNames.VBAutoPropertyExtender}
        End Function
 
        Public Overrides Function GetPropertyExtender(name As String, node As SyntaxNode, symbol As ISymbol) As Object
            If Not TypeOf node Is PropertyBlockSyntax AndAlso
               Not TypeOf node Is PropertyStatementSyntax AndAlso
               Not TypeOf symbol Is IPropertySymbol Then
 
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            If StringComparer.OrdinalIgnoreCase.Equals(name, ExtenderNames.VBAutoPropertyExtender) Then
                Dim isAutoImplemented = TypeOf node Is PropertyStatementSyntax AndAlso
                                        Not TypeOf node.Parent Is InterfaceBlockSyntax
 
                Return AutoPropertyExtender.Create(isAutoImplemented)
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Public Overrides Function GetExternalTypeExtenderNames() As String()
            Return {ExtenderNames.ExternalLocation}
        End Function
 
        Public Overrides Function GetExternalTypeExtender(name As String, externalLocation As String) As Object
            Debug.Assert(externalLocation IsNot Nothing)
 
            If StringComparer.OrdinalIgnoreCase.Equals(name, ExtenderNames.ExternalLocation) Then
                Return CodeTypeLocationExtender.Create(externalLocation)
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Public Overrides Function GetTypeExtenderNames() As String()
            Return {ExtenderNames.VBGenericExtender}
        End Function
 
        Public Overrides Function GetTypeExtender(name As String, codeType As AbstractCodeType) As Object
            If codeType Is Nothing Then
                Throw Exceptions.ThrowEUnexpected()
            End If
 
            If StringComparer.OrdinalIgnoreCase.Equals(name, ExtenderNames.VBGenericExtender) Then
                Return GenericExtender.Create(codeType)
            End If
 
            Throw Exceptions.ThrowEFail()
        End Function
 
        Protected Overrides Function AddBlankLineToMethodBody(node As SyntaxNode, newNode As SyntaxNode) As Boolean
            Return TypeOf node Is SyntaxNode AndAlso
                   node.IsKind(SyntaxKind.SubStatement, SyntaxKind.FunctionStatement) AndAlso
                   TypeOf newNode Is SyntaxNode AndAlso
                   newNode.IsKind(SyntaxKind.SubBlock, SyntaxKind.FunctionBlock)
        End Function
 
        Public Overrides Function IsValidBaseType(node As SyntaxNode, typeSymbol As ITypeSymbol) As Boolean
            If node.IsKind(SyntaxKind.ClassBlock) Then
                Return typeSymbol.TypeKind = TypeKind.Class
            ElseIf node.IsKind(SyntaxKind.InterfaceBlock) Then
                Return typeSymbol.TypeKind = TypeKind.Interface
            End If
 
            Return False
        End Function
 
        Public Overrides Function AddBase(node As SyntaxNode, typeSymbol As ITypeSymbol, semanticModel As SemanticModel, position As Integer?) As SyntaxNode
            If Not node.IsKind(SyntaxKind.ClassBlock, SyntaxKind.InterfaceBlock) Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim typeBlock = DirectCast(node, TypeBlockSyntax)
            Dim baseCount = typeBlock.Inherits.Count
 
            If typeBlock.IsKind(SyntaxKind.ClassBlock) AndAlso baseCount > 0 Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim typeBlockPosition = typeBlock.SpanStart
 
            Dim inheritsStatement =
                SyntaxFactory.InheritsStatement(
                    SyntaxFactory.ParseTypeName(
                        typeSymbol.ToMinimalDisplayString(semanticModel, typeBlockPosition)))
 
            inheritsStatement = inheritsStatement.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)
 
            Dim inheritsStatements = typeBlock.Inherits.Insert(0, inheritsStatement)
 
            Return typeBlock.WithInherits(inheritsStatements)
        End Function
 
        Public Overrides Function RemoveBase(node As SyntaxNode, typeSymbol As ITypeSymbol, semanticModel As SemanticModel) As SyntaxNode
            If Not node.IsKind(SyntaxKind.ClassBlock, SyntaxKind.InterfaceBlock) Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim typeBlock = DirectCast(node, TypeBlockSyntax)
            If typeBlock.Inherits.Count = 0 Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim inheritsStatements = typeBlock.Inherits
 
            For Each inheritsStatement In inheritsStatements
                For Each inheritsType In inheritsStatement.Types
                    Dim typeInfo = semanticModel.GetTypeInfo(inheritsType, CancellationToken.None)
                    If typeInfo.Type IsNot Nothing AndAlso
                       typeInfo.Type.Equals(typeSymbol) Then
                        If inheritsStatement.Types.Count = 1 Then
                            inheritsStatements = inheritsStatements.Remove(inheritsStatement)
                        Else
                            Dim newInheritsStatement = inheritsStatement.RemoveNode(inheritsType, SyntaxRemoveOptions.KeepEndOfLine)
                            inheritsStatements = inheritsStatements.Replace(inheritsStatement, newInheritsStatement)
                        End If
 
                        Exit For
                    End If
                Next
            Next
 
            Return typeBlock.WithInherits(inheritsStatements)
        End Function
 
        Public Overrides Function IsValidInterfaceType(node As SyntaxNode, typeSymbol As ITypeSymbol) As Boolean
            If node.IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then
                Return typeSymbol.TypeKind = TypeKind.Interface
            End If
 
            Return False
        End Function
 
        Public Overrides Function AddImplementedInterface(node As SyntaxNode, typeSymbol As ITypeSymbol, semanticModel As SemanticModel, position As Integer?) As SyntaxNode
            If Not node.IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim typeBlock = DirectCast(node, TypeBlockSyntax)
            Dim baseCount = typeBlock.Implements.Count
 
            Dim insertionIndex As Integer
            If position IsNot Nothing Then
                insertionIndex = position.Value
                If insertionIndex > baseCount Then
                    Throw Exceptions.ThrowEInvalidArg()
                End If
            Else
                insertionIndex = baseCount
            End If
 
            Dim typeBlockPosition = typeBlock.SpanStart
 
            Dim implementsStatement =
                SyntaxFactory.ImplementsStatement(
                    SyntaxFactory.ParseTypeName(
                        typeSymbol.ToMinimalDisplayString(semanticModel, typeBlockPosition)))
 
            implementsStatement = implementsStatement.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)
 
            Dim implementsStatements = typeBlock.Implements.Insert(insertionIndex, implementsStatement)
 
            Return typeBlock.WithImplements(implementsStatements)
        End Function
 
        Public Overrides Function RemoveImplementedInterface(node As SyntaxNode, typeSymbol As ITypeSymbol, semanticModel As SemanticModel) As SyntaxNode
            If Not node.IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then
                Throw Exceptions.ThrowENotImpl()
            End If
 
            Dim typeBlock = DirectCast(node, TypeBlockSyntax)
            If typeBlock.Implements.Count = 0 Then
                Throw Exceptions.ThrowEFail()
            End If
 
            Dim implementsStatements = typeBlock.Implements
 
            For Each implementsStatement In implementsStatements
                For Each inheritsType In implementsStatement.Types
                    Dim typeInfo = semanticModel.GetTypeInfo(inheritsType, CancellationToken.None)
                    If typeInfo.Type IsNot Nothing AndAlso
                       typeInfo.Type.Equals(typeSymbol) Then
                        If implementsStatement.Types.Count = 1 Then
                            implementsStatements = implementsStatements.Remove(implementsStatement)
                        Else
                            Dim newImplementsStatement = implementsStatement.RemoveNode(inheritsType, SyntaxRemoveOptions.KeepEndOfLine)
                            implementsStatements = implementsStatements.Replace(implementsStatement, newImplementsStatement)
                        End If
 
                        Exit For
                    End If
                Next
            Next
 
            Return typeBlock.WithImplements(implementsStatements)
        End Function
 
        Public Overrides Sub AttachFormatTrackingToBuffer(buffer As ITextBuffer)
            _commitBufferManagerFactory.CreateForBuffer(buffer).AddReferencingView()
        End Sub
 
        Public Overrides Sub DetachFormatTrackingToBuffer(buffer As ITextBuffer)
            _commitBufferManagerFactory.CreateForBuffer(buffer).RemoveReferencingView()
        End Sub
 
        Public Overrides Sub EnsureBufferFormatted(buffer As ITextBuffer)
            _commitBufferManagerFactory.CreateForBuffer(buffer).CommitDirty(isExplicitFormat:=False, cancellationToken:=Nothing)
        End Sub
 
    End Class
End Namespace