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