File: Syntax\SyntaxFacts.vb
Web Access
Project: src\src\roslyn\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.

Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
' NOTE: The other partial class definition is generated by a tool.
' Because VB doesn't support Partial Module definitions the actual SyntaxFacts implementations are in this class
' but the SyntaxFacts extension methods are thin wrappers around this class exposed in separate Modules.

Namespace Microsoft.CodeAnalysis.VisualBasic

    Partial Public NotInheritable Class SyntaxFacts

        ''' <summary>
        ''' Determine if the token instance represents a syntax trivia such as comment, whitespace, etc...
        ''' </summary>
        Public Shared Function IsTrivia(this As SyntaxKind) As Boolean
            Return IsSyntaxTrivia(this)
        End Function

        ''' <summary>
        ''' Get all reserved and contextual keywords
        ''' </summary>
        Public Shared Function GetKeywordKinds() As IEnumerable(Of SyntaxKind)
            Return GetReservedKeywordKinds.Concat(GetContextualKeywordKinds)
        End Function

        ''' <summary>
        ''' Helper to check whether the token is a predefined type
        ''' </summary>
        ''' <returns>True if it is a predefined type</returns>
        Public Shared Function IsPredefinedType(kind As SyntaxKind) As Boolean
            Return IsPredefinedTypeKeyword(kind)
        End Function

        ''' <summary>
        ''' Helper to check whether the token is a predefined type OR Variant keyword
        ''' </summary>
        ''' <returns>True if it is a predefined type OR Variant keyword</returns>
        Friend Shared Function IsPredefinedTypeOrVariant(kind As SyntaxKind) As Boolean
            Return IsPredefinedTypeKeyword(kind) OrElse kind = SyntaxKind.VariantKeyword
        End Function

        ''' <summary>
        ''' Returns true if the node is the object of an invocation expression
        ''' </summary>
        Public Shared Function IsInvoked(node As ExpressionSyntax) As Boolean
            node = SyntaxFactory.GetStandaloneExpression(node)
            Dim inv = TryCast(node.Parent, InvocationExpressionSyntax)
            Return inv IsNot Nothing AndAlso inv.Expression Is node
        End Function

        ''' <summary>
        ''' Returns true if the node is the operand of an AddressOf expression
        ''' </summary>
        Public Shared Function IsAddressOfOperand(node As ExpressionSyntax) As Boolean
            Dim parent = node.Parent
            Return parent IsNot Nothing AndAlso parent.Kind = SyntaxKind.AddressOfExpression
        End Function

        ''' <summary>
        ''' Returns true if the node is the operand of an AddressOf expression, or the object
        ''' of an invocation. This is used for special binding rules around the return value variable 
        ''' inside Functions and Property Get accessors.
        ''' </summary>
        Public Shared Function IsInvocationOrAddressOfOperand(node As ExpressionSyntax) As Boolean
            Return IsInvoked(node) OrElse IsAddressOfOperand(node)
        End Function

        ' Determines whether a particular node is in a context where it must bind to a type.
        Public Shared Function IsInTypeOnlyContext(node As ExpressionSyntax) As Boolean

            'Typeof does a null check and will result in returning false if nothing is passed rather than throwing an exception
            If Not (TypeOf node Is TypeSyntax) Then
                Return False ' Only nodes deriving from TypeSyntax could possible be in type context.
            End If

            Dim parent As VisualBasicSyntaxNode = node.Parent
            If parent IsNot Nothing Then
                Select Case parent.Kind
                    Case SyntaxKind.SimpleAsClause, SyntaxKind.AsNewClause
                        Return DirectCast(parent, AsClauseSyntax).Type Is node
                    Case SyntaxKind.GetTypeExpression
                        Return DirectCast(parent, GetTypeExpressionSyntax).Type Is node
                    Case SyntaxKind.TypeOfIsExpression, SyntaxKind.TypeOfIsNotExpression
                        Return DirectCast(parent, TypeOfExpressionSyntax).Type Is node
                    Case SyntaxKind.CTypeExpression, SyntaxKind.DirectCastExpression, SyntaxKind.TryCastExpression
                        Return DirectCast(parent, CastExpressionSyntax).Type Is node
                    Case SyntaxKind.TypeArgumentList
                        Return True  ' all non-token children are types
                    Case SyntaxKind.InheritsStatement, SyntaxKind.ImplementsStatement
                        Return True  ' all non-token children are types
                    Case SyntaxKind.TypeConstraint
                        Return True ' all non-token children are types
                    Case SyntaxKind.CrefSignaturePart
                        Return True ' all non-token children are types
                    Case SyntaxKind.Attribute
                        Return DirectCast(parent, AttributeSyntax).Name Is node
                    Case SyntaxKind.ObjectCreationExpression
                        Return DirectCast(parent, ObjectCreationExpressionSyntax).Type Is node
                    Case SyntaxKind.ArrayCreationExpression
                        Return DirectCast(parent, ArrayCreationExpressionSyntax).Type Is node
                    Case SyntaxKind.ArrayType
                        Return DirectCast(parent, ArrayTypeSyntax).ElementType Is node
                    Case SyntaxKind.NullableType
                        Return DirectCast(parent, NullableTypeSyntax).ElementType Is node
                    Case SyntaxKind.QualifiedName
                        Dim parentQualName = DirectCast(parent, QualifiedNameSyntax)
                        If parentQualName.Parent IsNot Nothing AndAlso parentQualName.Parent.Kind = SyntaxKind.ImplementsClause Then
                            Return parentQualName.Left Is node
                        Else
                            Return parentQualName.Right Is node
                        End If
                    Case SyntaxKind.TypedTupleElement
                        Return DirectCast(parent, TypedTupleElementSyntax).Type Is node
                End Select
            End If

            Return False
        End Function

        ' Is this node in a place where it bind to an implemented member.
        Friend Shared Function IsImplementedMember(node As SyntaxNode) As Boolean
            Debug.Assert(node IsNot Nothing)

            Dim parent = node.Parent
            Return parent IsNot Nothing AndAlso parent.IsKind(SyntaxKind.ImplementsClause)
        End Function

        ' Is this node in a place where it bind to a handled event.
        Friend Shared Function IsHandlesEvent(node As SyntaxNode) As Boolean
            Debug.Assert(node IsNot Nothing)

            Dim parent = node.Parent
            Return parent IsNot Nothing AndAlso
                parent.IsKind(SyntaxKind.HandlesClauseItem) AndAlso
                TypeOf node Is IdentifierNameSyntax
        End Function

        ' Is this node in a place where it bind to a handled event's container.
        Friend Shared Function IsHandlesContainer(node As SyntaxNode) As Boolean
            Debug.Assert(node IsNot Nothing)

            Return TypeOf node Is WithEventsEventContainerSyntax
        End Function

        ' Is this node in a place where it bind to a handled event's container.
        Friend Shared Function IsHandlesProperty(node As SyntaxNode) As Boolean
            Debug.Assert(node IsNot Nothing)

            Dim parent = node.Parent
            Return parent IsNot Nothing AndAlso
                parent.IsKind(SyntaxKind.WithEventsPropertyEventContainer) AndAlso
                TypeOf node Is IdentifierNameSyntax
        End Function

        ' Is this node in a place where is must bind to either a namespace or a type.
        Public Shared Function IsInNamespaceOrTypeContext(node As SyntaxNode) As Boolean
            If node IsNot Nothing Then
                If TypeOf node IsNot TypeSyntax Then
                    Return False ' Only nodes deriving from TypeSyntax could possible be in type or namespace context.
                End If

                Dim parent = node.Parent
                If parent IsNot Nothing Then
                    Select Case parent.Kind()
                        Case SyntaxKind.SimpleImportsClause
                            Return DirectCast(parent, SimpleImportsClauseSyntax).Name Is node
                        Case SyntaxKind.NamespaceStatement
                            Return DirectCast(parent, NamespaceStatementSyntax).Name Is node
                        Case SyntaxKind.QualifiedName
                            Dim parentQualName = DirectCast(parent, QualifiedNameSyntax)
                            If Not (parentQualName.Parent IsNot Nothing AndAlso parentQualName.Parent.Kind = SyntaxKind.ImplementsClause) Then
                                Return DirectCast(parent, QualifiedNameSyntax).Left Is node
                            End If
                    End Select
                End If

                Dim expressionNode = TryCast(node, ExpressionSyntax)
                If expressionNode IsNot Nothing Then
                    Return IsInTypeOnlyContext(expressionNode)
                End If
            End If

            Return False
        End Function

        ''' <summary>
        ''' Determines if position is before or within the span of a node, or in the trailing trivia of a node 
        ''' up to, but not including, a newline or colon trivia (which mark the end of a statement.)
        ''' </summary>
        Private Shared Function InOrBeforeSpanOrEffectiveTrailingOfNode(node As SyntaxNode, position As Integer) As Boolean
            Return position < node.SpanStart OrElse InSpanOrEffectiveTrailingOfNode(node, position)
        End Function

        ''' <summary>
        ''' Determines if position is within the span of a node, or in the trailing trivia of a node 
        ''' up to, but not including, a newline or colon trivia (which mark the end of a statement.)
        ''' </summary>
        Friend Shared Function InSpanOrEffectiveTrailingOfNode(node As SyntaxNode, position As Integer) As Boolean
            Dim span = node.Span
            If span.Contains(position) Then
                Return True
            ElseIf position >= span.End AndAlso position < node.FullSpan.End Then
                ' Position is in the trailing trivia of node. Check for newline or :.
                Dim trailingTrivia As SyntaxTriviaList = node.GetTrailingTrivia()
                For Each trivia In trailingTrivia
                    If trivia.Kind = SyntaxKind.EndOfLineTrivia OrElse trivia.Kind = SyntaxKind.ColonTrivia Then
                        Exit For
                    End If
                    If trivia.FullSpan.Contains(position) Then
                        Return True
                    End If
                Next

                ' The effective trailing trivia didn't contain the position
                Return False
            End If

            Return False
        End Function

        ' Determines if possibleBlock is a block statement and position is in the interior.
        ' If so, then return true.
        Friend Shared Function InBlockInterior(possibleBlock As SyntaxNode, position As Integer) As Boolean
            Dim body As SyntaxList(Of StatementSyntax) = Nothing
            Return InBlockInterior(possibleBlock, position, body)
        End Function

        ''' <summary>
        ''' Determines if possibleLambda is a lambda expression and position is in the interior.
        ''' </summary>
        Friend Shared Function InLambdaInterior(
            possibleLambda As SyntaxNode,
            position As Integer
        ) As Boolean

            Dim afterBegin As Boolean
            Dim beforeEnd As Boolean

            Select Case possibleLambda.Kind()
                Case SyntaxKind.SingleLineFunctionLambdaExpression,
                     SyntaxKind.SingleLineSubLambdaExpression

                    Dim singleLineLambda = DirectCast(possibleLambda, SingleLineLambdaExpressionSyntax)
                    Dim parameterList As ParameterListSyntax = singleLineLambda.SubOrFunctionHeader.ParameterList

                    If parameterList Is Nothing OrElse parameterList.CloseParenToken.IsMissing Then
                        afterBegin = (position >= singleLineLambda.SubOrFunctionHeader.Span.End)
                    Else
                        afterBegin = (position >= parameterList.CloseParenToken.SpanStart)
                    End If

                    beforeEnd = (position <= singleLineLambda.Body.Span.End)

                Case SyntaxKind.MultiLineFunctionLambdaExpression,
                     SyntaxKind.MultiLineSubLambdaExpression

                    Dim multiLineLambda = DirectCast(possibleLambda, MultiLineLambdaExpressionSyntax)
                    Dim parameterList As ParameterListSyntax = multiLineLambda.SubOrFunctionHeader.ParameterList

                    If parameterList Is Nothing OrElse parameterList.CloseParenToken.IsMissing Then
                        afterBegin = (position >= multiLineLambda.SubOrFunctionHeader.Span.End)
                    Else
                        afterBegin = (position >= parameterList.CloseParenToken.SpanStart)
                    End If

                    beforeEnd = (position < multiLineLambda.EndSubOrFunctionStatement.SpanStart)

                Case Else
                    Return False
            End Select

            Return afterBegin AndAlso beforeEnd
        End Function

        ' Determines if possibleBlock is a block statement and position is in the interior.
        ' If so, then return true and the body.
        Friend Shared Function InBlockInterior(possibleBlock As SyntaxNode,
                                        position As Integer,
                                        ByRef body As SyntaxList(Of StatementSyntax)) As Boolean
            Dim beginStatement As StatementSyntax = Nothing
            Dim endStatement As StatementSyntax = Nothing
            Dim beginTerminator As SyntaxToken = Nothing

            If IsBlockStatement(possibleBlock, beginStatement, beginTerminator, body, endStatement) Then
                Dim afterBegin As Boolean = True
                Dim beforeEnd As Boolean = True

                If beginTerminator.Kind <> SyntaxKind.None AndAlso beginTerminator.Width > 0 Then
                    afterBegin = position >= beginTerminator.SpanStart
                Else
                    afterBegin = Not InOrBeforeSpanOrEffectiveTrailingOfNode(beginStatement, position)
                End If

                If endStatement Is Nothing Then
                    Select Case possibleBlock.Kind
                        Case SyntaxKind.SingleLineIfStatement, SyntaxKind.SingleLineElseClause
                            ' No expected end statement. These are "single" line blocks, check based on last statement in block instead.
                            If body.Count > 0 Then
                                Dim lastStatement = body(body.Count - 1)
                                beforeEnd = InOrBeforeSpanOrEffectiveTrailingOfNode(lastStatement, position)
                            End If

                        Case Else
                            ' No expected end statement. These are multi-line blocks, check based on a token that follows the block instead.
                            Dim followingToken As SyntaxToken = possibleBlock.GetLastToken(includeZeroWidth:=True).GetNextToken()

                            If followingToken <> Nothing Then
                                ' These blocks are always followed by a construct that terminates them. Let's treat it similar to the endStatement.
                                beforeEnd = position < followingToken.SpanStart
                            End If
                    End Select

                ElseIf endStatement.Width > 0 Then
                    beforeEnd = InOrBeforeSpanOrEffectiveTrailingOfNode(endStatement, position)
                End If

                Return afterBegin AndAlso beforeEnd
            End If

            Return False
        End Function

        ' Returns is possibleBlock is a block statement. If so, return the begin, body, and end statement. Note that
        ' many blocks (IfPart, TryPart, CaseBlock, etc. ) do not have immediate end statements. Also a few blocks don't
        ' have bodies that are SeparatedSyntaxList(Of StatementSyntax).
        '
        ' Only for single-line If And Else, also return the token that ends that "begin" part (Then or Else tokens).
        Friend Shared Function IsBlockStatement(possibleBlock As SyntaxNode,
                                         ByRef beginStatement As StatementSyntax,
                                         ByRef beginTerminator As SyntaxToken,
                                         ByRef body As SyntaxList(Of StatementSyntax),
                                         ByRef endStatement As StatementSyntax) As Boolean
            beginTerminator = Nothing

            Select Case possibleBlock.Kind()
                Case SyntaxKind.NamespaceBlock
                    Dim nsBlock = DirectCast(possibleBlock, NamespaceBlockSyntax)
                    beginStatement = nsBlock.NamespaceStatement
                    body = nsBlock.Members
                    endStatement = nsBlock.EndNamespaceStatement
                    Return True

                Case SyntaxKind.ModuleBlock, SyntaxKind.StructureBlock, SyntaxKind.InterfaceBlock, SyntaxKind.ClassBlock
                    Dim typeBlock = DirectCast(possibleBlock, TypeBlockSyntax)
                    beginStatement = typeBlock.BlockStatement
                    body = typeBlock.Members
                    endStatement = typeBlock.EndBlockStatement
                    Return True

                Case SyntaxKind.EnumBlock
                    Dim enumBlock = DirectCast(possibleBlock, EnumBlockSyntax)
                    beginStatement = enumBlock.EnumStatement
                    body = enumBlock.Members
                    endStatement = enumBlock.EndEnumStatement
                    Return True

                Case SyntaxKind.SubBlock, SyntaxKind.FunctionBlock, SyntaxKind.ConstructorBlock,
                     SyntaxKind.OperatorBlock, SyntaxKind.GetAccessorBlock, SyntaxKind.SetAccessorBlock,
                     SyntaxKind.AddHandlerAccessorBlock, SyntaxKind.RemoveHandlerAccessorBlock, SyntaxKind.RaiseEventAccessorBlock
                    Dim methodBlock = DirectCast(possibleBlock, MethodBlockBaseSyntax)
                    beginStatement = methodBlock.BlockStatement
                    body = methodBlock.Statements
                    endStatement = methodBlock.EndBlockStatement
                    Return True

                Case SyntaxKind.PropertyBlock
                    Dim propertyBlock = DirectCast(possibleBlock, PropertyBlockSyntax)
                    beginStatement = propertyBlock.PropertyStatement
                    body = Nothing ' doesn't have a body per se
                    endStatement = propertyBlock.EndPropertyStatement
                    Return True

                Case SyntaxKind.EventBlock
                    Dim eventBlock = DirectCast(possibleBlock, EventBlockSyntax)
                    beginStatement = eventBlock.EventStatement
                    body = Nothing ' doesn't have a body per se
                    endStatement = eventBlock.EndEventStatement
                    Return True

                Case SyntaxKind.WhileBlock
                    Dim whileBlock = DirectCast(possibleBlock, WhileBlockSyntax)
                    beginStatement = whileBlock.WhileStatement
                    body = whileBlock.Statements
                    endStatement = whileBlock.EndWhileStatement
                    Return True

                Case SyntaxKind.ForBlock, SyntaxKind.ForEachBlock
                    Dim forBlock = DirectCast(possibleBlock, ForOrForEachBlockSyntax)
                    beginStatement = forBlock.ForOrForEachStatement
                    body = forBlock.Statements
                    endStatement = forBlock.NextStatement
                    Return True

                Case SyntaxKind.SimpleDoLoopBlock,
                     SyntaxKind.DoWhileLoopBlock,
                     SyntaxKind.DoUntilLoopBlock,
                     SyntaxKind.DoLoopWhileBlock,
                     SyntaxKind.DoLoopUntilBlock

                    Dim doBlock = DirectCast(possibleBlock, DoLoopBlockSyntax)
                    beginStatement = doBlock.DoStatement
                    body = doBlock.Statements
                    endStatement = doBlock.LoopStatement
                    Return True

                Case SyntaxKind.UsingBlock
                    Dim usingBlock = DirectCast(possibleBlock, UsingBlockSyntax)
                    beginStatement = usingBlock.UsingStatement
                    body = usingBlock.Statements
                    endStatement = usingBlock.EndUsingStatement
                    Return True

                Case SyntaxKind.SyncLockBlock
                    Dim syncBlock = DirectCast(possibleBlock, SyncLockBlockSyntax)
                    beginStatement = syncBlock.SyncLockStatement
                    body = syncBlock.Statements
                    endStatement = syncBlock.EndSyncLockStatement
                    Return True

                Case SyntaxKind.WithBlock
                    Dim withBlock = DirectCast(possibleBlock, WithBlockSyntax)
                    beginStatement = withBlock.WithStatement
                    body = withBlock.Statements
                    endStatement = withBlock.EndWithStatement
                    Return True

                Case SyntaxKind.SelectBlock
                    Dim selectBlock = DirectCast(possibleBlock, SelectBlockSyntax)
                    beginStatement = selectBlock.SelectStatement
                    body = Nothing ' doesn't fit 
                    endStatement = selectBlock.EndSelectStatement
                    Return True

                Case SyntaxKind.CaseBlock, SyntaxKind.CaseElseBlock
                    Dim caseBlock = DirectCast(possibleBlock, CaseBlockSyntax)
                    beginStatement = caseBlock.CaseStatement
                    body = caseBlock.Statements
                    endStatement = Nothing ' doesn't fit
                    Return True

                Case SyntaxKind.SingleLineIfStatement
                    Dim ifStatement = DirectCast(possibleBlock, SingleLineIfStatementSyntax)
                    beginStatement = Nothing ' doesn't fit
                    beginTerminator = ifStatement.ThenKeyword
                    body = ifStatement.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case SyntaxKind.SingleLineElseClause
                    Dim elseClause = DirectCast(possibleBlock, SingleLineElseClauseSyntax)
                    beginStatement = Nothing ' doesn't fit
                    beginTerminator = elseClause.ElseKeyword
                    body = elseClause.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case SyntaxKind.MultiLineIfBlock
                    Dim ifBlock = DirectCast(possibleBlock, MultiLineIfBlockSyntax)
                    beginStatement = ifBlock.IfStatement
                    body = ifBlock.Statements
                    endStatement = ifBlock.EndIfStatement
                    Return True

                Case SyntaxKind.ElseIfBlock
                    Dim elseIfBlock = DirectCast(possibleBlock, ElseIfBlockSyntax)
                    beginStatement = elseIfBlock.ElseIfStatement
                    body = elseIfBlock.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case SyntaxKind.ElseBlock
                    Dim elseBlock = DirectCast(possibleBlock, ElseBlockSyntax)
                    beginStatement = elseBlock.ElseStatement
                    body = elseBlock.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case SyntaxKind.TryBlock
                    Dim tryBlock = DirectCast(possibleBlock, TryBlockSyntax)
                    beginStatement = tryBlock.TryStatement
                    body = tryBlock.Statements
                    endStatement = tryBlock.EndTryStatement
                    Return True

                Case SyntaxKind.CatchBlock
                    Dim catchBlock = DirectCast(possibleBlock, CatchBlockSyntax)
                    beginStatement = catchBlock.CatchStatement
                    body = catchBlock.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case SyntaxKind.FinallyBlock
                    Dim finallyBlock = DirectCast(possibleBlock, FinallyBlockSyntax)
                    beginStatement = finallyBlock.FinallyStatement
                    body = finallyBlock.Statements
                    endStatement = Nothing ' doesn't have an end.
                    Return True

                Case Else
                    Return False
            End Select
        End Function

        ''' <summary>
        ''' If "node" is a block statement return the Begin statement  of "node", otherwise return "node".
        ''' </summary>
        Friend Shared Function BeginOfBlockStatementIfAny(node As SyntaxNode) As SyntaxNode
            Dim beginStatement As StatementSyntax = Nothing
            Dim body As SyntaxList(Of StatementSyntax) = Nothing
            Dim endStatement As StatementSyntax = Nothing
            Dim beginTerminator As SyntaxToken = Nothing

            If IsBlockStatement(node, beginStatement, beginTerminator, body, endStatement) Then
                If beginStatement IsNot Nothing Then
                    Return beginStatement
                End If
            End If

            Return node
        End Function

        Public Shared Function GetText(accessibility As Accessibility) As String
            Select Case accessibility

                Case Accessibility.Friend
                    Return GetText(SyntaxKind.FriendKeyword)

                Case Accessibility.NotApplicable
                    Return String.Empty

                Case Accessibility.Private
                    Return GetText(SyntaxKind.PrivateKeyword)

                Case Accessibility.Protected
                    Return GetText(SyntaxKind.ProtectedKeyword)

                Case Accessibility.ProtectedAndFriend
                    Return GetText(SyntaxKind.PrivateKeyword) + " " + GetText(SyntaxKind.ProtectedKeyword)

                Case Accessibility.ProtectedOrFriend
                    Return GetText(SyntaxKind.ProtectedKeyword) + " " + GetText(SyntaxKind.FriendKeyword)

                Case Accessibility.Public
                    Return GetText(SyntaxKind.PublicKeyword)

                Case Else
                    Debug.Assert(False, String.Format("Unknown accessibility '{0}'", accessibility))
                    Return Nothing
            End Select
        End Function

        Public Shared Function IsAnyToken(kind As SyntaxKind) As Boolean
            Return kind >= SyntaxKind.AddHandlerKeyword AndAlso kind <= SyntaxKind.CharacterLiteralToken
        End Function

        Public Shared Function GetUnaryExpression(token As SyntaxKind) As SyntaxKind
            Select Case token

                Case SyntaxKind.PlusToken
                    Return SyntaxKind.UnaryPlusExpression

                Case SyntaxKind.MinusToken
                    Return SyntaxKind.UnaryMinusExpression

                Case SyntaxKind.NotKeyword
                    Return SyntaxKind.NotExpression

                Case SyntaxKind.AddressOfKeyword
                    Return SyntaxKind.AddressOfExpression

                Case Else
                    Return SyntaxKind.None
            End Select
        End Function

        Public Shared Function IsPreprocessorPunctuation(kind As SyntaxKind) As Boolean
            Return kind = SyntaxKind.HashToken
        End Function

        Public Shared Function IsLanguagePunctuation(kind As SyntaxKind) As Boolean
            Return IsPunctuation(kind) AndAlso Not IsPreprocessorPunctuation(kind)
        End Function

        Public Shared Function IsName(kind As SyntaxKind) As Boolean
            Return kind = SyntaxKind.IdentifierName OrElse
                    kind = SyntaxKind.GenericName OrElse
                    kind = SyntaxKind.QualifiedName OrElse
                    kind = SyntaxKind.GlobalName
        End Function

        Public Shared Function IsNamespaceMemberDeclaration(kind As SyntaxKind) As Boolean
            Return kind = SyntaxKind.ClassStatement OrElse kind = SyntaxKind.InterfaceStatement OrElse
                    kind = SyntaxKind.StructureStatement OrElse kind = SyntaxKind.EnumStatement OrElse
                    kind = SyntaxKind.ModuleStatement OrElse kind = SyntaxKind.NamespaceStatement OrElse
                    kind = SyntaxKind.DelegateFunctionStatement OrElse kind = SyntaxKind.DelegateSubStatement
        End Function

        Public Shared Function IsPunctuationOrKeyword(kind As SyntaxKind) As Boolean
            Select Case kind
                Case SyntaxKind.AddHandlerKeyword To SyntaxKind.EndOfXmlToken,
                     SyntaxKind.NameOfKeyword,
                     SyntaxKind.DollarSignDoubleQuoteToken,
                     SyntaxKind.EndOfInterpolatedStringToken
                    Return True

                Case Else
                    Return False
            End Select
        End Function

        Public Shared Function VarianceKindFromToken(token As SyntaxToken) As VarianceKind
            Select Case token.Kind
                Case SyntaxKind.OutKeyword
                    Return VarianceKind.Out

                Case SyntaxKind.InKeyword
                    Return VarianceKind.In

                Case Else
                    Return VarianceKind.None
            End Select
        End Function

        ''' <summary>
        ''' Checks if the SyntaxNode is an attribute name. To be an attribute name, the syntax
        ''' must be parented by an Attribute and the node itself must be equal to the Attribute.Name
        ''' property.
        ''' </summary>
        Public Shared Function IsAttributeName(node As SyntaxNode) As Boolean

            Dim nextNode As SyntaxNode = node

            Do While nextNode IsNot Nothing

                Select Case nextNode.Kind()

                    Case SyntaxKind.IdentifierName, SyntaxKind.QualifiedName
                        nextNode = nextNode.Parent

                    Case SyntaxKind.Attribute
                        Dim attribute = DirectCast(nextNode, AttributeSyntax)

                        If attribute.Name Is node Then
                            Return True
                        End If

                        Dim name As QualifiedNameSyntax = TryCast(attribute.Name, QualifiedNameSyntax)
                        Return name IsNot Nothing AndAlso name.Right Is node

                    Case Else
                        Return False

                End Select

            Loop

            Return False
        End Function

        ''' <summary>
        ''' Is the node the name of a named argument of an invocation or object creation expression, 
        ''' but not an attribute.
        ''' </summary>        
        Public Shared Function IsNamedArgumentName(node As SyntaxNode) As Boolean
            If node.Kind <> SyntaxKind.IdentifierName Then
                Return False
            End If

            Dim parent1 = TryCast(node.Parent, NameColonEqualsSyntax)
            If parent1 Is Nothing Then
                Return False
            End If

            Dim parent2 = parent1.Parent.Parent
            If parent2 Is Nothing OrElse Not parent2.IsKind(SyntaxKind.ArgumentList) Then
                Return False
            End If

            Dim parent3 = parent2.Parent
            If parent3 Is Nothing Then
                Return False
            End If

            Select Case parent3.Kind
                Case SyntaxKind.InvocationExpression,
                     SyntaxKind.ObjectCreationExpression,
                     SyntaxKind.RaiseEventStatement

                    Return True
                Case Else
                    Return False
            End Select
        End Function

        ''' <summary>
        ''' Return keyword or punctuation text based on SyntaxKind
        ''' </summary>
        Public Shared Function GetBlockName(kind As SyntaxKind) As String
            Select Case kind
                Case SyntaxKind.CaseBlock
                    Return "Case"

                Case SyntaxKind.SimpleDoLoopBlock,
                     SyntaxKind.DoWhileLoopBlock,
                     SyntaxKind.DoUntilLoopBlock,
                     SyntaxKind.DoLoopWhileBlock,
                     SyntaxKind.DoLoopUntilBlock
                    Return "Do Loop"

                Case SyntaxKind.WhileBlock
                    Return "While"

                Case SyntaxKind.WithBlock
                    Return "With"

                Case SyntaxKind.SyncLockBlock
                    Return "SyncLock"

                Case SyntaxKind.UsingBlock
                    Return "Using"

                Case SyntaxKind.ForBlock
                    Return "For"

                Case SyntaxKind.ForEachBlock
                    Return "For Each"

                Case SyntaxKind.SelectBlock
                    Return "Select"

                Case SyntaxKind.MultiLineIfBlock
                    Return "If"

                Case SyntaxKind.ElseIfBlock
                    Return "Else If"

                Case SyntaxKind.ElseBlock
                    Return "Else"

                Case SyntaxKind.TryBlock
                    Return "Try"

                Case SyntaxKind.CatchBlock
                    Return "Catch"

                Case SyntaxKind.FinallyBlock
                    Return "Finally"

                Case Else
                    Throw New ArgumentOutOfRangeException(NameOf(kind))
            End Select
        End Function

        ''' <summary>
        ''' Indicates whether a newline may validly follow the specified SyntaxToken without requiring an explicit line continuation sequence ' _' or terminating the containing statement.
        ''' </summary>
        ''' <param name="token">The token to test. This token must be parented by a SyntaxNode.</param>
        ''' <returns>True if implicit line continuation is allowed after token.</returns>
        ''' <remarks>
        ''' <para>Refer to "Statements in Visual Basic", 2010 version, http://msdn.microsoft.com/en-us/library/865x40k4(v=vs.100).aspx 
        ''' for examples.</para>
        ''' <para>Implicit line continuation may be used in Visual Basic: </para>
        ''' <list>
        '''   <item>After a comma (,).</item>
        '''   <item>After a less-than sign (&lt;) or before a greater-than sign (&gt;) when you specify an attribute.</item>
        '''   <item>After an open parenthesis (() or before a closing parenthesis ()).</item>
        '''   <item>After an open curly brace ({) or before a closing curly brace (}).</item>
        '''   <item>After an open embedded expression (&lt;%=) or before the close of an embedded expression (%&gt;) within an XML literal.</item>
        '''   <item>
        '''     <para>Before and after query operators (Aggregate, Distinct, From, Group By, Group Join, Join, Let, 
        ''' Order By, Select, Skip, Skip While, Take, Take While, Where, In, Into, On, Ascending, and Descending).</para>
        '''     <para>You cannot break a line between the keywords of query operators that are made up of multiple keywords 
        ''' (Order By, Group Join, Take While, and Skip While).</para>
        '''   </item>
        '''   <item>After the concatenation operator (&amp;).</item>
        '''   <item>After assignment operators (=, &amp;=, :=, +=, -=, *=, /=, \=, ^=, &lt;&lt;=, &gt;&gt;=).</item>
        '''   <item>After binary operators (+, -, /, *, Mod, &lt;&gt;, &lt;, &gt;, &lt;=, &gt;=, ^, &gt;&gt;, &lt;&lt;, And, AndAlso, Or, OrElse, Like, Xor) within an expression.</item>
        '''   <item>After the Is and IsNot operators.</item>
        '''   <item>After a less-than sign (&lt;) or before a greater-than sign (&gt;) when you specify an attribute.</item>
        '''   <item>
        '''     <para>Also after a greater-than sign (&gt;) when you specify an attribute.</para>
        '''     <para>However, you must include a line-continuation character (_) when you specify assembly-level or module-level attributes.</para>
        '''   </item>
        '''   <item>
        '''     <para>After a member qualifier character (.) and before the member name.</para>
        '''     <para>However, you must include a line-continuation character (_) following a member qualifier character when you are using the With statement or 
        ''' supplying values in the initialization list for a type.</para>
        '''   </item>
        '''   <item>
        '''     <para>After an XML axis property qualifier (. or ...).</para> 
        '''     <para>However, you must include a line-continuation character (_) when you specify a member qualifier when you are using the With keyword.</para>
        '''   </item>
        '''   <item>After the From keyword in a collection initializer.</item>
        '''   <item>After the With keyword in a member initializer.</item>
        '''   <item>After the In keyword in a For Each statement.</item>
        ''' </list>
        ''' </remarks>
        Public Shared Function AllowsTrailingImplicitLineContinuation(token As SyntaxToken) As Boolean

            If token.Parent Is Nothing Then Throw New ArgumentException("'token' must be parented by a SyntaxNode.")

            Dim kind = token.Kind
            Dim parentKind = token.Parent.Kind

            ' This list taken from: "Statements in Visual Basic", 2010 version, http://msdn.microsoft.com/en-us/library/865x40k4(v=vs.100).aspx

            ' After a comma (,).
            If kind = SyntaxKind.CommaToken Then Return True

            ' Disallowed after unary minus and plus.
            If kind = SyntaxKind.MinusToken OrElse kind = SyntaxKind.PlusToken Then
                Return TypeOf token.Parent Is BinaryExpressionSyntax
            End If

            ' Disallowed after xml namespace imports
            If kind = SyntaxKind.GreaterThanToken AndAlso parentKind = SyntaxKind.XmlNamespaceImportsClause Then
                Return False
            End If

            ' After the concatenation operator (&).
            ' After assignment operators (=, &=, :=, +=, -=, *=, /=, \=, ^=, <<=, >>=).
            ' After binary operators (+, -, /, *, Mod, <>, <, >, <=, >=, ^, >>, <<, And, AndAlso, Or, OrElse, Like, Xor) within an expression.
            ' After the Is and IsNot operators.
            ' These cases are also covered by the binary operator check.
            ' After a less-than sign (<) or before a greater-than sign (>) when you specify an attribute. 
            ' Also after a greater-than sign (>) when you specify an attribute. 
            ' NOTE: No idea what this means:
            ' However, you must include a line-continuation character (_) when you specify assembly-level or module-level attributes.
            If IsBinaryExpressionOperatorToken(kind) OrElse IsAssignmentStatementOperatorToken(kind) Then Return True

            Select Case kind

                Case SyntaxKind.ColonEqualsToken

                    Return True

                ' After an open parenthesis (() or before a closing parenthesis ()).
                ' After an open embedded expression (<%=) or before the close of an embedded expression (%>) within an XML literal.
                Case SyntaxKind.OpenParenToken,
                     SyntaxKind.LessThanPercentEqualsToken,
                     SyntaxKind.PercentGreaterThanToken

                    Return True

                ' After an open curly brace ({) or before a closing curly brace (})
                ' However, a line-continuation character is required following the open curly brace of a string interpolation.
                Case SyntaxKind.OpenBraceToken

                    If parentKind = SyntaxKind.Interpolation Then
                        Return False
                    End If

                    Return True

                ' After a member qualifier character (.) and before the member name. 
                ' However, you must include a line-continuation character (_) following a member qualifier character when you are using the With statement or 
                ' supplying values in the initialization list for a type.
                Case SyntaxKind.DotToken

                    ' bug # 12903
                    ' when dot is directly under named field initializer, (_) is needed between "." and member name
                    If parentKind = SyntaxKind.NamedFieldInitializer Then
                        Return False
                    ElseIf parentKind = SyntaxKind.SimpleMemberAccessExpression Then
                        Return CType(token.Parent, MemberAccessExpressionSyntax).Expression IsNot Nothing OrElse
                               token.Parent.Parent.Kind = SyntaxKind.NamedFieldInitializer

                        ' After an XML axis property qualifier (. or .@ or ...). 
                        ' However, you must include a line-continuation character (_) when you specify a member qualifier when you are using the With keyword.
                        ' BUG: Dev11 doesn't allow after the @ token

                    ElseIf parentKind = SyntaxKind.XmlElementAccessExpression OrElse
                           parentKind = SyntaxKind.XmlAttributeAccessExpression OrElse
                           parentKind = SyntaxKind.XmlDescendantAccessExpression Then

                        ' Dev 10/11 do not allow a "." on a line after a ".", 
                        ' This is an error
                        '       a = <x/>.
                        '           ..<x>
                        '
                        ' while this is allowed
                        '       a = <x/>.
                        '           @<x>
                        ' Note, this restriction may not be necessary. See comment in ParseQualifiedExpr line 830. 

                        If CType(token.Parent, XmlMemberAccessExpressionSyntax).Base IsNot Nothing Then
                            Return token.GetNextToken.Kind <> SyntaxKind.DotToken
                        Else
                            Return False
                        End If
                    Else
                        Return True

                    End If

                ' After the With keyword in a member initializer.
                Case SyntaxKind.WithKeyword

                    Return parentKind = SyntaxKind.ObjectMemberInitializer

                ' Before and after query operators (Aggregate, Distinct, From, Group By, Group Join, Join, Let, 
                ' Order By, Select, Skip, Skip While, Take, Take While, Where, In, Into, On, Ascending, and Descending). 
                ' After the From keyword in a collection initializer.
                Case SyntaxKind.AggregateKeyword,
                     SyntaxKind.ByKeyword,
                     SyntaxKind.EqualsKeyword,
                     SyntaxKind.FromKeyword,
                     SyntaxKind.IntoKeyword,
                     SyntaxKind.JoinKeyword,
                     SyntaxKind.WhereKeyword

                    Return True

                ' This is new in Roslyn.
                Case SyntaxKind.GetXmlNamespaceKeyword,
                        SyntaxKind.OfKeyword

                    Return True

                ' You cannot break a line between the keywords of query operators that are made up of multiple keywords 
                ' (Order By, Group Join, Take While, and Skip While).
                Case SyntaxKind.GroupKeyword
                    Return parentKind <> SyntaxKind.GroupJoinClause

                ' You cannot break a line between the keywords of query operators that are made up of multiple keywords 
                ' (Order By, Group Join, Take While, and Skip While).
                Case SyntaxKind.SkipKeyword

                    Return parentKind <> SyntaxKind.SkipWhileClause

                ' You cannot break a line between the keywords of query operators that are made up of multiple keywords 
                ' (Order By, Group Join, Take While, and Skip While).
                Case SyntaxKind.TakeKeyword

                    Return parentKind <> SyntaxKind.TakeWhileClause

                ' After the In keyword in a For Each statement.
                Case SyntaxKind.InKeyword

                    Return parentKind = SyntaxKind.CollectionRangeVariable OrElse
                           parentKind = SyntaxKind.ForEachStatement

                ' Keywords that may appear outside of query clauses
                Case SyntaxKind.OnKeyword,
                     SyntaxKind.LetKeyword,
                     SyntaxKind.SelectKeyword,
                     SyntaxKind.WhileKeyword

                    Return TypeOf token.Parent Is QueryClauseSyntax

                ' XML Literals
                Case SyntaxKind.BeginCDataToken,
                     SyntaxKind.DoubleQuoteToken,
                     SyntaxKind.LessThanExclamationMinusMinusToken,
                     SyntaxKind.LessThanQuestionToken,
                     SyntaxKind.XmlKeyword,
                     SyntaxKind.XmlNameToken,
                     SyntaxKind.XmlTextLiteralToken

                    Return True

                Case SyntaxKind.EndCDataToken,
                     SyntaxKind.MinusMinusGreaterThanToken,
                     SyntaxKind.QuestionGreaterThanToken,
                     SyntaxKind.SlashGreaterThanToken

                    ' An implicit line continuation is allowed only if the token is not the end of
                    ' the xml literal. Walk up the parent chain and see if there is a parent node
                    ' whose end extends beyond this token.
                    Dim p As XmlNodeSyntax = Nothing
                    Dim n = TryCast(token.Parent.Parent, XmlNodeSyntax)
                    While n IsNot Nothing
                        p = n
                        If p.EndPosition > token.EndPosition Then
                            Return True
                        End If
                        n = TryCast(n.Parent, XmlNodeSyntax)
                    End While
                    Return False

                Case SyntaxKind.ColonToken

                    Return parentKind = SyntaxKind.XmlPrefix

                Case Else

                    Return False

            End Select

        End Function

        ''' <summary>
        ''' Indicates whether a newline may validly precede the specified SyntaxToken without requiring an explicit line continuation sequence ' _' or terminating the containing statement.
        ''' </summary>
        ''' <param name="token">The token to test. This token must be parented by a SyntaxNode.</param>
        ''' <returns>True if implicit line continuation is allowed after token.</returns>
        ''' <remarks>
        ''' <para>Refer to "Statements in Visual Basic", 2010 version, http://msdn.microsoft.com/en-us/library/865x40k4(v=vs.100).aspx 
        ''' for examples.</para>
        ''' <para>Implicit line continuation may be used in Visual Basic: </para>
        ''' <list>
        '''   <item>After a comma (,).</item>
        '''   <item>After a less-than sign (&lt;) or before a greater-than sign (&gt;) when you specify an attribute.</item>
        '''   <item>After an open parenthesis (() or before a closing parenthesis ()).</item>
        '''   <item>After an open curly brace ({) or before a closing curly brace (}).</item>
        '''   <item>After an open embedded expression (&lt;%=) or before the close of an embedded expression (%&gt;) within an XML literal.</item>
        '''   <item>
        '''     <para>Before and after query operators (Aggregate, Distinct, From, Group By, Group Join, Join, Let, 
        ''' Order By, Select, Skip, Skip While, Take, Take While, Where, In, Into, On, Ascending, and Descending).</para>
        '''     <para>You cannot break a line between the keywords of query operators that are made up of multiple keywords 
        ''' (Order By, Group Join, Take While, and Skip While).</para>
        '''   </item>
        '''   <item>After the concatenation operator (&amp;).</item>
        '''   <item>After assignment operators (=, &amp;=, :=, +=, -=, *=, /=, \=, ^=, &lt;&lt;=, &gt;&gt;=).</item>
        '''   <item>After binary operators (+, -, /, *, Mod, &lt;&gt;, &lt;, &gt;, &lt;=, &gt;=, ^, &gt;&gt;, &lt;&lt;, And, AndAlso, Or, OrElse, Like, Xor) within an expression.</item>
        '''   <item>After the Is and IsNot operators.</item>
        '''   <item>After a less-than sign (&lt;) or before a greater-than sign (&gt;) when you specify an attribute.</item>
        '''   <item>
        '''     <para>Also after a greater-than sign (&gt;) when you specify an attribute.</para>
        '''     <para>However, you must include a line-continuation character (_) when you specify assembly-level or module-level attributes.</para>
        '''   </item>
        '''   <item>
        '''     <para>After a member qualifier character (.) and before the member name.</para>
        '''     <para>However, you must include a line-continuation character (_) following a member qualifier character when you are using the With statement or 
        ''' supplying values in the initialization list for a type.</para>
        '''   </item>
        '''   <item>
        '''     <para>After an XML axis property qualifier (. or ...).</para> 
        '''     <para>However, you must include a line-continuation character (_) when you specify a member qualifier when you are using the With keyword.</para>
        '''   </item>
        '''   <item>After the From keyword in a collection initializer.</item>
        '''   <item>After the With keyword in a member initializer.</item>
        '''   <item>After the In keyword in a For Each statement.</item>
        ''' </list>
        ''' </remarks>
        Public Shared Function AllowsLeadingImplicitLineContinuation(token As SyntaxToken) As Boolean

            If token.Parent Is Nothing Then Throw New ArgumentException("'token' must be parented by a SyntaxNode.")

            Dim kind = token.Kind
            Dim parentKind = token.Parent.Kind

            ' This list taken from: "Statements in Visual Basic", 2010 version, http://msdn.microsoft.com/en-us/library/865x40k4(v=vs.100).aspx

            Select Case kind

                ' After a less-than sign (<) or before a greater-than sign (>) when you specify an attribute. 
                Case SyntaxKind.GreaterThanToken,
                     SyntaxKind.LessThanToken

                    Return parentKind = SyntaxKind.AttributeList

                ' After an open parenthesis (() or before a closing parenthesis ()).
                ' After an open embedded expression (<%=) or before the close of an embedded expression (%>) within an XML literal.
                Case SyntaxKind.CloseParenToken,
                     SyntaxKind.PercentGreaterThanToken

                    Return True

                ' After an open curly brace ({) or before a closing curly brace (})
                ' However, a line-continuation character is required before the closing curly brace of a string interpolation.
                Case SyntaxKind.CloseBraceToken

                    If parentKind = SyntaxKind.Interpolation Then
                        Return False
                    End If

                    Return True

                ' Before and after query operators (Aggregate, Distinct, From, Group By, Group Join, Join, Let, 
                ' Order By, Select, Skip, Skip While, Take, Take While, Where, In, Into, On, Ascending, and Descending). 
                Case SyntaxKind.AscendingKeyword,
                     SyntaxKind.DescendingKeyword,
                     SyntaxKind.DistinctKeyword,
                     SyntaxKind.GroupKeyword,
                     SyntaxKind.IntoKeyword,
                     SyntaxKind.OrderKeyword,
                     SyntaxKind.SkipKeyword,
                     SyntaxKind.TakeKeyword,
                     SyntaxKind.WhereKeyword

                    Return True

                ' You cannot break a line between the keywords of query operators that are made up of multiple keywords 
                ' (Order By, Group Join, Take While, and Skip While).
                Case SyntaxKind.JoinKeyword

                    Return parentKind <> SyntaxKind.GroupJoinClause

                ' Keywords that may appear outside of query clauses
                Case SyntaxKind.InKeyword,
                     SyntaxKind.LetKeyword,
                     SyntaxKind.OnKeyword,
                     SyntaxKind.SelectKeyword

                    Return TypeOf token.Parent Is QueryClauseSyntax

                Case SyntaxKind.AggregateKeyword,
                     SyntaxKind.FromKeyword

                    ' Allow a leading line continuation only if this is a QueryClause and it is not the first clause
                    ' in a query expression.

                    Dim p As VisualBasicSyntaxNode = TryCast(token.Parent, QueryClauseSyntax)
                    If p Is Nothing Then
                        Return False
                    End If

                    p = p.Parent
                    While p IsNot Nothing
                        If TypeOf p Is QueryExpressionSyntax Then
                            If p.GetLocation.SourceSpan.Start < token.SpanStart Then
                                Return True
                            Else
                                Return False
                            End If
                        End If
                        p = p.Parent
                    End While

                    Return False

                Case Else

                    Return False

            End Select
        End Function

        Public Shared Function GetOperatorKind(operatorMetadataName As String) As SyntaxKind
            Dim opInfo = OverloadResolution.GetOperatorInfo(operatorMetadataName)

            Return If(opInfo.ParamCount = 0, SyntaxKind.None, OverloadResolution.GetOperatorTokenKind(opInfo))
        End Function

        Public Shared Function IsAccessibilityModifier(kind As SyntaxKind) As Boolean
            Select Case kind
                Case SyntaxKind.PrivateKeyword,
                     SyntaxKind.ProtectedKeyword,
                     SyntaxKind.FriendKeyword,
                     SyntaxKind.PublicKeyword
                    Return True
                Case Else
                    Return False
            End Select
        End Function

        Friend Shared Function IsTerminator(kind As SyntaxKind) As Boolean
            Return kind = SyntaxKind.StatementTerminatorToken OrElse
                kind = SyntaxKind.ColonToken OrElse
                kind = SyntaxKind.EndOfFileToken
        End Function

        Friend Shared Function IsWithinPreprocessorConditionalExpression(node As SyntaxNode) As Boolean
            Debug.Assert(node IsNot Nothing)
            Dim parent = node.Parent

            While parent IsNot Nothing
                Select Case parent.Kind()
                    Case SyntaxKind.IfDirectiveTrivia, SyntaxKind.ElseIfDirectiveTrivia
                        Return DirectCast(parent, IfDirectiveTriviaSyntax).Condition Is node
                    Case SyntaxKind.ConstDirectiveTrivia
                        Return DirectCast(parent, ConstDirectiveTriviaSyntax).Value Is node
                    Case Else
                        node = parent
                        parent = node.Parent
                End Select
            End While

            Return False
        End Function

        ''' <summary>
        ''' Checks whether the element name is reserved.
        '''
        ''' For example:
        ''' "Item3" is reserved.
        ''' "Rest", "ToString" and other members of System.ValueTuple are reserved.
        ''' Names that are not reserved return False.
        ''' </summary>
        Public Shared Function IsReservedTupleElementName(elementName As String) As Boolean
            Return TupleTypeSymbol.IsElementNameReserved(elementName) <> -1
        End Function
    End Class
End Namespace