VisualBasicSyntaxFactsService.vb 83.7 KB
Newer Older
1
' Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2

3
Imports System.Collections.Immutable
4
Imports System.Composition
B
brettv 已提交
5
Imports System.Text
P
Pilchie 已提交
6 7
Imports System.Threading
Imports Microsoft.CodeAnalysis
8
Imports Microsoft.CodeAnalysis.Collections
B
brettv 已提交
9
Imports Microsoft.CodeAnalysis.FindSymbols
10
Imports Microsoft.CodeAnalysis.Host
11
Imports Microsoft.CodeAnalysis.Host.Mef
P
Pilchie 已提交
12 13
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Text
14
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
P
Pilchie 已提交
15 16 17 18 19
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts

Namespace Microsoft.CodeAnalysis.VisualBasic

20
    <ExportLanguageServiceFactory(GetType(ISyntaxFactsService), LanguageNames.VisualBasic), [Shared]>
A
AdamSpeight2008 已提交
21
    Friend Class VisualBasicSyntaxFactsServiceFactory
22
        Implements ILanguageServiceFactory
23

24
        Public Function CreateLanguageService(languageServices As HostLanguageServices) As ILanguageService Implements ILanguageServiceFactory.CreateLanguageService
C
CyrusNajmabadi 已提交
25
            Return VisualBasicSyntaxFactsService.Instance
26
        End Function
27
    End Class
28

29 30 31
    Friend Class VisualBasicSyntaxFactsService
        Inherits AbstractSyntaxFactsService
        Implements ISyntaxFactsService
P
Pilchie 已提交
32

C
CyrusNajmabadi 已提交
33 34 35 36 37
        Public Shared ReadOnly Property Instance As New VisualBasicSyntaxFactsService

        Private Sub New()
        End Sub

38 39 40 41 42 43
        Public ReadOnly Property IsCaseSensitive As Boolean Implements ISyntaxFactsService.IsCaseSensitive
            Get
                Return False
            End Get
        End Property

44 45 46
        Public Function SupportsIndexingInitializer(options As ParseOptions) As Boolean Implements ISyntaxFactsService.SupportsIndexingInitializer
            Return False
        End Function
47

48 49 50
        Public Function IsAwaitKeyword(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsAwaitKeyword
            Return token.Kind = SyntaxKind.AwaitKeyword
        End Function
P
Pilchie 已提交
51

52 53 54
        Public Function IsIdentifier(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsIdentifier
            Return token.Kind = SyntaxKind.IdentifierToken
        End Function
P
Pilchie 已提交
55

56 57 58
        Public Function IsGlobalNamespaceKeyword(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsGlobalNamespaceKeyword
            Return token.Kind = SyntaxKind.GlobalKeyword
        End Function
P
Pilchie 已提交
59

60 61 62
        Public Function IsVerbatimIdentifier(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsVerbatimIdentifier
            Return False
        End Function
P
Pilchie 已提交
63

64 65
        Public Function IsOperator(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsOperator
            Return (IsUnaryExpressionOperatorToken(CType(token.Kind, SyntaxKind)) AndAlso (TypeOf token.Parent Is UnaryExpressionSyntax OrElse TypeOf token.Parent Is OperatorStatementSyntax)) OrElse
66
                   (IsBinaryExpressionOperatorToken(CType(token.Kind, SyntaxKind)) AndAlso (TypeOf token.Parent Is BinaryExpressionSyntax OrElse TypeOf token.Parent Is OperatorStatementSyntax))
67 68 69 70 71
        End Function

        Public Function IsContextualKeyword(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsContextualKeyword
            Return token.IsContextualKeyword()
        End Function
P
Pilchie 已提交
72

73 74 75
        Public Function IsKeyword(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsKeyword
            Return token.IsKeyword()
        End Function
76

77 78 79
        Public Function IsPreprocessorKeyword(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsPreprocessorKeyword
            Return token.IsPreprocessorKeyword()
        End Function
80

81 82 83
        Public Function IsHashToken(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsHashToken
            Return token.Kind = SyntaxKind.HashToken
        End Function
P
Pilchie 已提交
84

85
        Public Function TryGetCorrespondingOpenBrace(token As SyntaxToken, ByRef openBrace As SyntaxToken) As Boolean Implements ISyntaxFactsService.TryGetCorrespondingOpenBrace
P
Pilchie 已提交
86

87 88 89 90 91
            If token.Kind = SyntaxKind.CloseBraceToken Then
                Dim tuples = token.Parent.GetBraces()
                openBrace = tuples.Item1
                Return openBrace.Kind = SyntaxKind.OpenBraceToken
            End If
P
Pilchie 已提交
92

93 94
            Return False
        End Function
P
Pilchie 已提交
95

96 97 98
        Public Function IsInInactiveRegion(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFactsService.IsInInactiveRegion
            Dim vbTree = TryCast(syntaxTree, SyntaxTree)
            If vbTree Is Nothing Then
99
                Return False
100
            End If
P
Pilchie 已提交
101

102 103
            Return vbTree.IsInInactiveRegion(position, cancellationToken)
        End Function
104

105 106 107 108 109
        Public Function IsInNonUserCode(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFactsService.IsInNonUserCode
            Dim vbTree = TryCast(syntaxTree, SyntaxTree)
            If vbTree Is Nothing Then
                Return False
            End If
P
Pilchie 已提交
110

111 112
            Return vbTree.IsInNonUserCode(position, cancellationToken)
        End Function
P
Pilchie 已提交
113

114 115 116 117 118
        Public Function IsEntirelyWithinStringOrCharOrNumericLiteral(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean Implements ISyntaxFactsService.IsEntirelyWithinStringOrCharOrNumericLiteral
            Dim vbTree = TryCast(syntaxTree, SyntaxTree)
            If vbTree Is Nothing Then
                Return False
            End If
P
Pilchie 已提交
119

120 121
            Return vbTree.IsEntirelyWithinStringOrCharOrNumericLiteral(position, cancellationToken)
        End Function
P
Pilchie 已提交
122

123 124 125
        Public Function IsDirective(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDirective
            Return TypeOf node Is DirectiveTriviaSyntax
        End Function
P
Pilchie 已提交
126

127 128 129 130 131
        Public Function TryGetExternalSourceInfo(node As SyntaxNode, ByRef info As ExternalSourceInfo) As Boolean Implements ISyntaxFactsService.TryGetExternalSourceInfo
            Select Case node.Kind
                Case SyntaxKind.ExternalSourceDirectiveTrivia
                    info = New ExternalSourceInfo(CInt(DirectCast(node, ExternalSourceDirectiveTriviaSyntax).LineStart.Value), False)
                    Return True
P
Pilchie 已提交
132

133 134 135 136
                Case SyntaxKind.EndExternalSourceDirectiveTrivia
                    info = New ExternalSourceInfo(Nothing, True)
                    Return True
            End Select
P
Pilchie 已提交
137

138 139
            Return False
        End Function
140

141 142
        Public Function IsObjectCreationExpressionType(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsObjectCreationExpressionType
            Return node.IsParentKind(SyntaxKind.ObjectCreationExpression) AndAlso
143
                DirectCast(node.Parent, ObjectCreationExpressionSyntax).Type Is node
144
        End Function
145

146 147
        Public Function IsAttributeName(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsAttributeName
            Return node.IsParentKind(SyntaxKind.Attribute) AndAlso
148
                DirectCast(node.Parent, AttributeSyntax).Name Is node
149 150 151 152 153 154
        End Function

        Public Function IsRightSideOfQualifiedName(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsRightSideOfQualifiedName
            Dim vbNode = TryCast(node, SimpleNameSyntax)
            Return vbNode IsNot Nothing AndAlso vbNode.IsRightSideOfQualifiedName()
        End Function
155

156
        Public Function IsNameOfMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsNameOfMemberAccessExpression
157 158 159
            Dim vbNode = TryCast(node, SimpleNameSyntax)
            Return vbNode IsNot Nothing AndAlso vbNode.IsMemberAccessExpressionName()
        End Function
160

161 162 163
        Public Function IsConditionalMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsConditionalMemberAccessExpression
            Return TypeOf node Is ConditionalAccessExpressionSyntax
        End Function
164

165 166 167
        Public Function IsInvocationExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInvocationExpression
            Return TypeOf node Is InvocationExpressionSyntax
        End Function
168

169 170 171
        Public Function IsAnonymousFunction(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsAnonymousFunction
            Return TypeOf node Is LambdaExpressionSyntax
        End Function
P
Pilchie 已提交
172

173 174 175
        Public Function IsGenericName(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsGenericName
            Return TypeOf node Is GenericNameSyntax
        End Function
P
Pilchie 已提交
176

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
        Public Function IsNamedParameter(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsNamedParameter
            Return node.CheckParent(Of SimpleArgumentSyntax)(Function(p) p.IsNamed AndAlso p.NameColonEquals.Name Is node)
        End Function

        Public Function IsSkippedTokensTrivia(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSkippedTokensTrivia
            Return TypeOf node Is SkippedTokensTriviaSyntax
        End Function

        Public Function HasIncompleteParentMember(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.HasIncompleteParentMember
            Return node.IsParentKind(SyntaxKind.IncompleteMember)
        End Function

        Public Function GetIdentifierOfGenericName(genericName As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetIdentifierOfGenericName
            Dim vbGenericName = TryCast(genericName, GenericNameSyntax)
            Return If(vbGenericName IsNot Nothing, vbGenericName.Identifier, Nothing)
        End Function
P
Pilchie 已提交
193

194 195
        Public Function IsUsingDirectiveName(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsUsingDirectiveName
            Return node.IsParentKind(SyntaxKind.SimpleImportsClause) AndAlso
196
                   DirectCast(node.Parent, SimpleImportsClauseSyntax).Name Is node
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
        End Function

        Public Function IsForEachStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsForEachStatement
            Return TypeOf node Is ForEachStatementSyntax
        End Function

        Public Function IsLockStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLockStatement
            Return TypeOf node Is SyncLockStatementSyntax
        End Function

        Public Function IsUsingStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsUsingStatement
            Return TypeOf node Is UsingStatementSyntax
        End Function

        Public Function IsThisConstructorInitializer(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsThisConstructorInitializer
            If TypeOf token.Parent Is IdentifierNameSyntax AndAlso token.HasMatchingText(SyntaxKind.NewKeyword) Then
                Dim memberAccess = TryCast(token.Parent.Parent, MemberAccessExpressionSyntax)
                Return memberAccess.IsThisConstructorInitializer()
            End If

            Return False
        End Function

        Public Function IsBaseConstructorInitializer(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsBaseConstructorInitializer
            If TypeOf token.Parent Is IdentifierNameSyntax AndAlso token.HasMatchingText(SyntaxKind.NewKeyword) Then
                Dim memberAccess = TryCast(token.Parent.Parent, MemberAccessExpressionSyntax)
                Return memberAccess.IsBaseConstructorInitializer()
            End If

            Return False
        End Function

        Public Function IsQueryExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsQueryExpression
            Return TypeOf node Is QueryExpressionSyntax
        End Function

        Public Function IsPredefinedType(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsPredefinedType
            Dim actualType As PredefinedType = PredefinedType.None
            Return TryGetPredefinedType(token, actualType) AndAlso actualType <> PredefinedType.None
        End Function

        Public Function IsPredefinedType(token As SyntaxToken, type As PredefinedType) As Boolean Implements ISyntaxFactsService.IsPredefinedType
            Dim actualType As PredefinedType = PredefinedType.None
            Return TryGetPredefinedType(token, actualType) AndAlso actualType = type
        End Function

        Public Function TryGetPredefinedType(token As SyntaxToken, ByRef type As PredefinedType) As Boolean Implements ISyntaxFactsService.TryGetPredefinedType
            type = GetPredefinedType(token)
            Return type <> PredefinedType.None
        End Function

        Private Function GetPredefinedType(token As SyntaxToken) As PredefinedType
            Select Case token.Kind
                Case SyntaxKind.BooleanKeyword
                    Return PredefinedType.Boolean
                Case SyntaxKind.ByteKeyword
                    Return PredefinedType.Byte
                Case SyntaxKind.SByteKeyword
                    Return PredefinedType.SByte
                Case SyntaxKind.IntegerKeyword
                    Return PredefinedType.Int32
                Case SyntaxKind.UIntegerKeyword
                    Return PredefinedType.UInt32
                Case SyntaxKind.ShortKeyword
                    Return PredefinedType.Int16
                Case SyntaxKind.UShortKeyword
                    Return PredefinedType.UInt16
                Case SyntaxKind.LongKeyword
                    Return PredefinedType.Int64
                Case SyntaxKind.ULongKeyword
                    Return PredefinedType.UInt64
                Case SyntaxKind.SingleKeyword
                    Return PredefinedType.Single
                Case SyntaxKind.DoubleKeyword
                    Return PredefinedType.Double
                Case SyntaxKind.DecimalKeyword
                    Return PredefinedType.Decimal
                Case SyntaxKind.StringKeyword
                    Return PredefinedType.String
                Case SyntaxKind.CharKeyword
                    Return PredefinedType.Char
                Case SyntaxKind.ObjectKeyword
                    Return PredefinedType.Object
                Case SyntaxKind.DateKeyword
                    Return PredefinedType.DateTime
                Case Else
                    Return PredefinedType.None
            End Select
        End Function

        Public Function IsPredefinedOperator(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsPredefinedOperator
            Dim actualOp As PredefinedOperator = PredefinedOperator.None
            Return TryGetPredefinedOperator(token, actualOp) AndAlso actualOp <> PredefinedOperator.None
        End Function

        Public Function IsPredefinedOperator(token As SyntaxToken, op As PredefinedOperator) As Boolean Implements ISyntaxFactsService.IsPredefinedOperator
            Dim actualOp As PredefinedOperator = PredefinedOperator.None
            Return TryGetPredefinedOperator(token, actualOp) AndAlso actualOp = op
        End Function

        Public Function TryGetPredefinedOperator(token As SyntaxToken, ByRef op As PredefinedOperator) As Boolean Implements ISyntaxFactsService.TryGetPredefinedOperator
            op = GetPredefinedOperator(token)
            Return op <> PredefinedOperator.None
        End Function

        Private Function GetPredefinedOperator(token As SyntaxToken) As PredefinedOperator
            Select Case token.Kind
                Case SyntaxKind.PlusToken, SyntaxKind.PlusEqualsToken
                    Return PredefinedOperator.Addition

                Case SyntaxKind.MinusToken, SyntaxKind.MinusEqualsToken
                    Return PredefinedOperator.Subtraction

                Case SyntaxKind.AndKeyword, SyntaxKind.AndAlsoKeyword
                    Return PredefinedOperator.BitwiseAnd

                Case SyntaxKind.OrKeyword, SyntaxKind.OrElseKeyword
                    Return PredefinedOperator.BitwiseOr

                Case SyntaxKind.AmpersandToken, SyntaxKind.AmpersandEqualsToken
                    Return PredefinedOperator.Concatenate

                Case SyntaxKind.SlashToken, SyntaxKind.SlashEqualsToken
                    Return PredefinedOperator.Division

                Case SyntaxKind.EqualsToken
                    Return PredefinedOperator.Equality

                Case SyntaxKind.XorKeyword
                    Return PredefinedOperator.ExclusiveOr

                Case SyntaxKind.CaretToken, SyntaxKind.CaretEqualsToken
                    Return PredefinedOperator.Exponent

                Case SyntaxKind.GreaterThanToken
                    Return PredefinedOperator.GreaterThan

                Case SyntaxKind.GreaterThanEqualsToken
                    Return PredefinedOperator.GreaterThanOrEqual

                Case SyntaxKind.LessThanGreaterThanToken
                    Return PredefinedOperator.Inequality

                Case SyntaxKind.BackslashToken, SyntaxKind.BackslashEqualsToken
                    Return PredefinedOperator.IntegerDivision

                Case SyntaxKind.LessThanLessThanToken, SyntaxKind.LessThanLessThanEqualsToken
                    Return PredefinedOperator.LeftShift
345

346 347
                Case SyntaxKind.LessThanToken
                    Return PredefinedOperator.LessThan
348

349 350
                Case SyntaxKind.LessThanEqualsToken
                    Return PredefinedOperator.LessThanOrEqual
351

352 353
                Case SyntaxKind.LikeKeyword
                    Return PredefinedOperator.Like
354

355 356
                Case SyntaxKind.NotKeyword
                    Return PredefinedOperator.Complement
357

358 359
                Case SyntaxKind.ModKeyword
                    Return PredefinedOperator.Modulus
360

361 362
                Case SyntaxKind.AsteriskToken, SyntaxKind.AsteriskEqualsToken
                    Return PredefinedOperator.Multiplication
363

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
                Case SyntaxKind.GreaterThanGreaterThanToken, SyntaxKind.GreaterThanGreaterThanEqualsToken
                    Return PredefinedOperator.RightShift

                Case Else
                    Return PredefinedOperator.None
            End Select
        End Function

        Public Function GetText(kind As Integer) As String Implements ISyntaxFactsService.GetText
            Return SyntaxFacts.GetText(CType(kind, SyntaxKind))
        End Function

        Public Function IsIdentifierPartCharacter(c As Char) As Boolean Implements ISyntaxFactsService.IsIdentifierPartCharacter
            Return SyntaxFacts.IsIdentifierPartCharacter(c)
        End Function

        Public Function IsIdentifierStartCharacter(c As Char) As Boolean Implements ISyntaxFactsService.IsIdentifierStartCharacter
            Return SyntaxFacts.IsIdentifierStartCharacter(c)
        End Function

        Public Function IsIdentifierEscapeCharacter(c As Char) As Boolean Implements ISyntaxFactsService.IsIdentifierEscapeCharacter
            Return c = "["c OrElse c = "]"c
        End Function

        Public Function IsValidIdentifier(identifier As String) As Boolean Implements ISyntaxFactsService.IsValidIdentifier
            Dim token = SyntaxFactory.ParseToken(identifier)
            ' TODO: There is no way to get the diagnostics to see if any are actually errors?
            Return IsIdentifier(token) AndAlso Not token.ContainsDiagnostics AndAlso token.ToString().Length = identifier.Length
        End Function

        Public Function IsVerbatimIdentifier(identifier As String) As Boolean Implements ISyntaxFactsService.IsVerbatimIdentifier
            Return IsValidIdentifier(identifier) AndAlso MakeHalfWidthIdentifier(identifier.First()) = "[" AndAlso MakeHalfWidthIdentifier(identifier.Last()) = "]"
        End Function

        Public Function IsTypeCharacter(c As Char) As Boolean Implements ISyntaxFactsService.IsTypeCharacter
            Return c = "%"c OrElse
400 401 402 403 404
                   c = "&"c OrElse
                   c = "@"c OrElse
                   c = "!"c OrElse
                   c = "#"c OrElse
                   c = "$"c
405
        End Function
P
Pilchie 已提交
406

407 408 409
        Public Function IsStartOfUnicodeEscapeSequence(c As Char) As Boolean Implements ISyntaxFactsService.IsStartOfUnicodeEscapeSequence
            Return False ' VB does not support identifiers with escaped unicode characters 
        End Function
410

411 412 413
        Public Function IsLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsLiteral
            Select Case token.Kind()
                Case _
414 415 416 417 418 419 420 421 422 423 424 425
                        SyntaxKind.IntegerLiteralToken,
                        SyntaxKind.CharacterLiteralToken,
                        SyntaxKind.DecimalLiteralToken,
                        SyntaxKind.FloatingLiteralToken,
                        SyntaxKind.DateLiteralToken,
                        SyntaxKind.StringLiteralToken,
                        SyntaxKind.DollarSignDoubleQuoteToken,
                        SyntaxKind.DoubleQuoteToken,
                        SyntaxKind.InterpolatedStringTextToken,
                        SyntaxKind.TrueKeyword,
                        SyntaxKind.FalseKeyword,
                        SyntaxKind.NothingKeyword
426 427
                    Return True
            End Select
P
Pilchie 已提交
428

429 430
            Return False
        End Function
P
Pilchie 已提交
431

432 433 434
        Public Function IsStringLiteralOrInterpolatedStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsStringLiteralOrInterpolatedStringLiteral
            Return token.IsKind(SyntaxKind.StringLiteralToken, SyntaxKind.InterpolatedStringTextToken)
        End Function
P
Pilchie 已提交
435

436 437 438
        Public Function IsNumericLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsNumericLiteralExpression
            Return If(node Is Nothing, False, node.IsKind(SyntaxKind.NumericLiteralExpression))
        End Function
P
Pilchie 已提交
439

440 441
        Public Function IsBindableToken(token As Microsoft.CodeAnalysis.SyntaxToken) As Boolean Implements ISyntaxFactsService.IsBindableToken
            Return Me.IsWord(token) OrElse
442 443
                Me.IsLiteral(token) OrElse
                Me.IsOperator(token)
444
        End Function
P
Pilchie 已提交
445

446
        Public Function IsSimpleMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSimpleMemberAccessExpression
447
            Return TypeOf node Is MemberAccessExpressionSyntax AndAlso
448
                DirectCast(node, MemberAccessExpressionSyntax).Kind = SyntaxKind.SimpleMemberAccessExpression
449
        End Function
P
Pilchie 已提交
450

451 452 453
        Public Function IsPointerMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsPointerMemberAccessExpression
            Return False
        End Function
P
Pilchie 已提交
454

455 456 457 458 459 460 461
        Public Sub GetNameAndArityOfSimpleName(node As SyntaxNode, ByRef name As String, ByRef arity As Integer) Implements ISyntaxFactsService.GetNameAndArityOfSimpleName
            Dim simpleName = TryCast(node, SimpleNameSyntax)
            If simpleName IsNot Nothing Then
                name = simpleName.Identifier.ValueText
                arity = simpleName.Arity
            End If
        End Sub
P
Pilchie 已提交
462

463 464 465 466 467 468 469
        Public Function GetExpressionOfMemberAccessExpression(node As SyntaxNode, Optional allowImplicitTarget As Boolean = False) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfMemberAccessExpression
            Return TryCast(node, MemberAccessExpressionSyntax)?.GetExpressionOfMemberAccessExpression(allowImplicitTarget)
        End Function

        Public Function GetTargetOfMemberBinding(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetTargetOfMemberBinding
            ' Member bindings are a C# concept.
            Return Nothing
470
        End Function
P
Pilchie 已提交
471

472
        Public Function GetExpressionOfConditionalAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfConditionalAccessExpression
473 474
            Return TryCast(node, ConditionalAccessExpressionSyntax)?.Expression
        End Function
P
Pilchie 已提交
475

476 477 478 479 480 481 482
        Public Function GetExpressionOfElementAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfElementAccessExpression
            Return TryCast(node, InvocationExpressionSyntax)?.Expression
        End Function

        Public Function GetArgumentListOfElementAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetArgumentListOfElementAccessExpression
            Return TryCast(node, InvocationExpressionSyntax)?.ArgumentList
        End Function
P
Pilchie 已提交
483

484 485 486
        Public Function GetExpressionOfInterpolation(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfInterpolation
            Return TryCast(node, InterpolationSyntax)?.Expression
        End Function
P
Pilchie 已提交
487

488 489 490
        Public Function IsInNamespaceOrTypeContext(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInNamespaceOrTypeContext
            Return SyntaxFacts.IsInNamespaceOrTypeContext(node)
        End Function
P
Pilchie 已提交
491

492 493 494
        Public Function IsInStaticContext(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInStaticContext
            Return node.IsInStaticContext()
        End Function
P
Pilchie 已提交
495

496 497 498
        Public Function GetExpressionOfArgument(node As Microsoft.CodeAnalysis.SyntaxNode) As Microsoft.CodeAnalysis.SyntaxNode Implements ISyntaxFactsService.GetExpressionOfArgument
            Return TryCast(node, ArgumentSyntax).GetArgumentExpression()
        End Function
P
Pilchie 已提交
499

500 501 502 503
        Public Function GetRefKindOfArgument(node As Microsoft.CodeAnalysis.SyntaxNode) As Microsoft.CodeAnalysis.RefKind Implements ISyntaxFactsService.GetRefKindOfArgument
            ' TODO(cyrusn): Consider the method this argument is passed to, to determine this.
            Return RefKind.None
        End Function
P
Pilchie 已提交
504

C
CyrusNajmabadi 已提交
505 506 507 508 509
        Public Function IsSimpleArgument(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSimpleArgument
            Dim argument = DirectCast(node, ArgumentSyntax)
            Return Not argument.IsNamed AndAlso Not argument.IsOmitted
        End Function

510 511 512
        Public Function IsInConstantContext(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInConstantContext
            Return node.IsInConstantContext()
        End Function
P
Pilchie 已提交
513

514 515 516
        Public Function IsInConstructor(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInConstructor
            Return node.GetAncestors(Of StatementSyntax).Any(Function(s) s.Kind = SyntaxKind.ConstructorBlock)
        End Function
P
Pilchie 已提交
517

518 519 520
        Public Function IsUnsafeContext(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsUnsafeContext
            Return False
        End Function
521

522 523 524
        Public Function GetNameOfAttribute(node As Microsoft.CodeAnalysis.SyntaxNode) As Microsoft.CodeAnalysis.SyntaxNode Implements ISyntaxFactsService.GetNameOfAttribute
            Return DirectCast(node, AttributeSyntax).Name
        End Function
525

526 527 528
        Public Function IsAttribute(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsAttribute
            Return TypeOf node Is AttributeSyntax
        End Function
529

530 531 532
        Public Function IsAttributeNamedArgumentIdentifier(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsAttributeNamedArgumentIdentifier
            Dim identifierName = TryCast(node, IdentifierNameSyntax)
            Return identifierName.IsParentKind(SyntaxKind.NameColonEquals) AndAlso
533 534 535
                identifierName.Parent.IsParentKind(SyntaxKind.SimpleArgument) AndAlso
                identifierName.Parent.Parent.IsParentKind(SyntaxKind.ArgumentList) AndAlso
                identifierName.Parent.Parent.Parent.IsParentKind(SyntaxKind.Attribute)
536
        End Function
537

538 539 540 541
        Public Function GetContainingTypeDeclaration(root As SyntaxNode, position As Integer) As SyntaxNode Implements ISyntaxFactsService.GetContainingTypeDeclaration
            If root Is Nothing Then
                Throw New ArgumentNullException(NameOf(root))
            End If
P
Pilchie 已提交
542

543 544 545
            If position < 0 OrElse position > root.Span.End Then
                Throw New ArgumentOutOfRangeException(NameOf(position))
            End If
P
Pilchie 已提交
546

547
            Return root.
548 549 550
                FindToken(position).
                GetAncestors(Of SyntaxNode)().
                FirstOrDefault(Function(n) TypeOf n Is TypeBlockSyntax OrElse TypeOf n Is DelegateStatementSyntax)
551
        End Function
P
Pilchie 已提交
552

553 554 555 556
        Public Function GetContainingVariableDeclaratorOfFieldDeclaration(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetContainingVariableDeclaratorOfFieldDeclaration
            If node Is Nothing Then
                Throw New ArgumentNullException(NameOf(node))
            End If
P
Pilchie 已提交
557

558
            Dim parent = node.Parent
P
Pilchie 已提交
559

560 561 562 563
            While node IsNot Nothing
                If node.Kind = SyntaxKind.VariableDeclarator AndAlso node.IsParentKind(SyntaxKind.FieldDeclaration) Then
                    Return node
                End If
P
Pilchie 已提交
564

565 566
                node = node.Parent
            End While
P
Pilchie 已提交
567

568 569
            Return Nothing
        End Function
570

571
        Public Function FindTokenOnLeftOfPosition(node As SyntaxNode,
572 573 574 575
                                                  position As Integer,
                                                  Optional includeSkipped As Boolean = True,
                                                  Optional includeDirectives As Boolean = False,
                                                  Optional includeDocumentationComments As Boolean = False) As SyntaxToken Implements ISyntaxFactsService.FindTokenOnLeftOfPosition
576 577
            Return node.FindTokenOnLeftOfPosition(position, includeSkipped, includeDirectives, includeDocumentationComments)
        End Function
578

579
        Public Function FindTokenOnRightOfPosition(node As SyntaxNode,
580 581 582 583
                                                   position As Integer,
                                                   Optional includeSkipped As Boolean = True,
                                                   Optional includeDirectives As Boolean = False,
                                                   Optional includeDocumentationComments As Boolean = False) As SyntaxToken Implements ISyntaxFactsService.FindTokenOnRightOfPosition
584 585
            Return node.FindTokenOnRightOfPosition(position, includeSkipped, includeDirectives, includeDocumentationComments)
        End Function
586

587 588 589
        Public Function IsObjectCreationExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsObjectCreationExpression
            Return TypeOf node Is ObjectCreationExpressionSyntax
        End Function
590

591
        Public Function IsObjectInitializerNamedAssignmentIdentifier(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsObjectInitializerNamedAssignmentIdentifier
592 593 594 595 596 597 598 599
            Dim unused As SyntaxNode = Nothing
            Return IsObjectInitializerNamedAssignmentIdentifier(node, unused)
        End Function

        Public Function IsObjectInitializerNamedAssignmentIdentifier(
                node As SyntaxNode,
                ByRef initializedInstance As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsObjectInitializerNamedAssignmentIdentifier

600
            Dim identifier = TryCast(node, IdentifierNameSyntax)
601 602 603 604 605 606 607 608 609
            If identifier?.IsChildNode(Of NamedFieldInitializerSyntax)(Function(n) n.Name) Then
                ' .parent is the NamedField.
                ' .parent.parent is the ObjectInitializer.
                ' .parent.parent.parent will be the ObjectCreationExpression.
                initializedInstance = identifier.Parent.Parent.Parent
                Return True
            End If

            Return False
610
        End Function
611

612 613 614 615 616
        Public Function IsElementAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsElementAccessExpression
            ' VB doesn't have a specialized node for element access.  Instead, it just uses an
            ' invocation expression or dictionary access expression.
            Return node.Kind = SyntaxKind.InvocationExpression OrElse node.Kind = SyntaxKind.DictionaryAccessExpression
        End Function
617

618 619 620
        Public Function ToIdentifierToken(name As String) As SyntaxToken Implements ISyntaxFactsService.ToIdentifierToken
            Return name.ToIdentifierToken()
        End Function
621

622 623 624
        Public Function Parenthesize(expression As SyntaxNode, Optional includeElasticTrivia As Boolean = True) As SyntaxNode Implements ISyntaxFactsService.Parenthesize
            Return DirectCast(expression, ExpressionSyntax).Parenthesize()
        End Function
625

626 627 628
        Public Function IsTypeNamedVarInVariableOrFieldDeclaration(token As SyntaxToken, parent As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsTypeNamedVarInVariableOrFieldDeclaration
            Return False
        End Function
P
Pilchie 已提交
629

630 631 632
        Public Function IsTypeNamedDynamic(token As SyntaxToken, parent As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsTypeNamedDynamic
            Return False
        End Function
P
Pilchie 已提交
633

634 635 636
        Public Function IsIndexerMemberCRef(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsIndexerMemberCRef
            Return False
        End Function
P
Pilchie 已提交
637

638 639 640
        Public Function GetContainingMemberDeclaration(root As SyntaxNode, position As Integer, Optional useFullSpan As Boolean = True) As SyntaxNode Implements ISyntaxFactsService.GetContainingMemberDeclaration
            Contract.ThrowIfNull(root, NameOf(root))
            Contract.ThrowIfTrue(position < 0 OrElse position > root.FullSpan.End, NameOf(position))
P
Pilchie 已提交
641

642 643 644 645 646
            Dim [end] = root.FullSpan.End
            If [end] = 0 Then
                ' empty file
                Return Nothing
            End If
P
Pilchie 已提交
647

648 649
            ' make sure position doesn't touch end of root
            position = Math.Min(position, [end] - 1)
P
Pilchie 已提交
650

651 652 653
            Dim node = root.FindToken(position).Parent
            While node IsNot Nothing
                If useFullSpan OrElse node.Span.Contains(position) Then
P
Pilchie 已提交
654

655 656 657
                    If TypeOf node Is MethodBlockBaseSyntax AndAlso Not TypeOf node.Parent Is PropertyBlockSyntax Then
                        Return node
                    End If
P
Pilchie 已提交
658

659 660 661
                    If TypeOf node Is PropertyStatementSyntax AndAlso Not TypeOf node.Parent Is PropertyBlockSyntax Then
                        Return node
                    End If
P
Pilchie 已提交
662

663 664 665
                    If TypeOf node Is EventStatementSyntax AndAlso Not TypeOf node.Parent Is EventBlockSyntax Then
                        Return node
                    End If
P
Pilchie 已提交
666

667
                    If TypeOf node Is PropertyBlockSyntax OrElse
668 669 670 671 672
                       TypeOf node Is TypeBlockSyntax OrElse
                       TypeOf node Is EnumBlockSyntax OrElse
                       TypeOf node Is NamespaceBlockSyntax OrElse
                       TypeOf node Is EventBlockSyntax OrElse
                       TypeOf node Is FieldDeclarationSyntax Then
673
                        Return node
674
                    End If
675
                End If
P
Pilchie 已提交
676

677 678
                node = node.Parent
            End While
P
Pilchie 已提交
679

680 681
            Return Nothing
        End Function
P
Pilchie 已提交
682

683
        Public Function IsMethodLevelMember(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsMethodLevelMember
P
Pilchie 已提交
684

685 686 687 688
            ' Note: Derived types of MethodBaseSyntax are expanded explicitly, since PropertyStatementSyntax and
            ' EventStatementSyntax will NOT be parented by MethodBlockBaseSyntax.  Additionally, there are things
            ' like AccessorStatementSyntax and DelegateStatementSyntax that we never want to tread as method level
            ' members.
P
Pilchie 已提交
689

690 691 692
            If TypeOf node Is MethodStatementSyntax AndAlso Not TypeOf node.Parent Is MethodBlockBaseSyntax Then
                Return True
            End If
P
Pilchie 已提交
693

694 695 696
            If TypeOf node Is SubNewStatementSyntax AndAlso Not TypeOf node.Parent Is MethodBlockBaseSyntax Then
                Return True
            End If
P
Pilchie 已提交
697

698 699 700
            If TypeOf node Is OperatorStatementSyntax AndAlso Not TypeOf node.Parent Is MethodBlockBaseSyntax Then
                Return True
            End If
701

702 703 704
            If TypeOf node Is PropertyStatementSyntax AndAlso Not TypeOf node.Parent Is PropertyBlockSyntax Then
                Return True
            End If
705

706 707 708
            If TypeOf node Is EventStatementSyntax AndAlso Not TypeOf node.Parent Is EventBlockSyntax Then
                Return True
            End If
709

710 711 712
            If TypeOf node Is DeclareStatementSyntax Then
                Return True
            End If
713

714
            Return TypeOf node Is ConstructorBlockSyntax OrElse
715 716 717 718 719 720
                   TypeOf node Is MethodBlockSyntax OrElse
                   TypeOf node Is OperatorBlockSyntax OrElse
                   TypeOf node Is EventBlockSyntax OrElse
                   TypeOf node Is PropertyBlockSyntax OrElse
                   TypeOf node Is EnumMemberDeclarationSyntax OrElse
                   TypeOf node Is FieldDeclarationSyntax
721 722 723 724 725 726 727
        End Function

        Public Function GetMemberBodySpanForSpeculativeBinding(node As SyntaxNode) As TextSpan Implements ISyntaxFactsService.GetMemberBodySpanForSpeculativeBinding
            Dim member = GetContainingMemberDeclaration(node, node.SpanStart)
            If member Is Nothing Then
                Return Nothing
            End If
728

729 730 731 732
            ' TODO: currently we only support method for now
            Dim method = TryCast(member, MethodBlockBaseSyntax)
            If method IsNot Nothing Then
                If method.BlockStatement Is Nothing OrElse method.EndBlockStatement Is Nothing Then
733
                    Return Nothing
P
Pilchie 已提交
734 735
                End If

736 737 738 739
                ' We don't want to include the BlockStatement or any trailing trivia up to and including its statement
                ' terminator in the span. Instead, we use the start of the first statement's leading trivia (if any) up
                ' to the start of the EndBlockStatement. If there aren't any statements in the block, we use the start
                ' of the EndBlockStatements leading trivia.
P
Pilchie 已提交
740

741 742
                Dim firstStatement = method.Statements.FirstOrDefault()
                Dim spanStart = If(firstStatement IsNot Nothing,
743 744
                                   firstStatement.FullSpan.Start,
                                   method.EndBlockStatement.FullSpan.Start)
745

746 747
                Return TextSpan.FromBounds(spanStart, method.EndBlockStatement.SpanStart)
            End If
P
Pilchie 已提交
748

749 750
            Return Nothing
        End Function
P
Pilchie 已提交
751

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
        Public Function ContainsInMemberBody(node As SyntaxNode, span As TextSpan) As Boolean Implements ISyntaxFactsService.ContainsInMemberBody
            Dim method = TryCast(node, MethodBlockBaseSyntax)
            If method IsNot Nothing Then
                Return method.Statements.Count > 0 AndAlso ContainsExclusively(GetSyntaxListSpan(method.Statements), span)
            End If

            Dim [event] = TryCast(node, EventBlockSyntax)
            If [event] IsNot Nothing Then
                Return [event].Accessors.Count > 0 AndAlso ContainsExclusively(GetSyntaxListSpan([event].Accessors), span)
            End If

            Dim [property] = TryCast(node, PropertyBlockSyntax)
            If [property] IsNot Nothing Then
                Return [property].Accessors.Count > 0 AndAlso ContainsExclusively(GetSyntaxListSpan([property].Accessors), span)
            End If

            Dim field = TryCast(node, FieldDeclarationSyntax)
            If field IsNot Nothing Then
                Return field.Declarators.Count > 0 AndAlso ContainsExclusively(GetSeparatedSyntaxListSpan(field.Declarators), span)
            End If

            Dim [enum] = TryCast(node, EnumMemberDeclarationSyntax)
            If [enum] IsNot Nothing Then
                Return [enum].Initializer IsNot Nothing AndAlso ContainsExclusively([enum].Initializer.Span, span)
            End If

            Dim propStatement = TryCast(node, PropertyStatementSyntax)
            If propStatement IsNot Nothing Then
                Return propStatement.Initializer IsNot Nothing AndAlso ContainsExclusively(propStatement.Initializer.Span, span)
            End If

            Return False
        End Function
P
Pilchie 已提交
785

786 787 788 789
        Private Function ContainsExclusively(outerSpan As TextSpan, innerSpan As TextSpan) As Boolean
            If innerSpan.IsEmpty Then
                Return outerSpan.Contains(innerSpan.Start)
            End If
P
Pilchie 已提交
790

791 792
            Return outerSpan.Contains(innerSpan)
        End Function
P
Pilchie 已提交
793

794 795 796 797
        Private Function GetSyntaxListSpan(Of T As SyntaxNode)(list As SyntaxList(Of T)) As TextSpan
            Contract.Requires(list.Count > 0)
            Return TextSpan.FromBounds(list.First.SpanStart, list.Last.Span.End)
        End Function
P
Pilchie 已提交
798

799 800 801 802
        Private Function GetSeparatedSyntaxListSpan(Of T As SyntaxNode)(list As SeparatedSyntaxList(Of T)) As TextSpan
            Contract.Requires(list.Count > 0)
            Return TextSpan.FromBounds(list.First.SpanStart, list.Last.Span.End)
        End Function
P
Pilchie 已提交
803

804 805 806 807 808
        Public Function GetMethodLevelMembers(root As SyntaxNode) As List(Of SyntaxNode) Implements ISyntaxFactsService.GetMethodLevelMembers
            Dim list = New List(Of SyntaxNode)()
            AppendMethodLevelMembers(root, list)
            Return list
        End Function
P
Pilchie 已提交
809

810 811
        Public Function IsTopLevelNodeWithMembers(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsTopLevelNodeWithMembers
            Return TypeOf node Is NamespaceBlockSyntax OrElse
812 813
                   TypeOf node Is TypeBlockSyntax OrElse
                   TypeOf node Is EnumBlockSyntax
814
        End Function
815

816 817 818 819 820
        Public Function TryGetDeclaredSymbolInfo(node As SyntaxNode, ByRef declaredSymbolInfo As DeclaredSymbolInfo) As Boolean Implements ISyntaxFactsService.TryGetDeclaredSymbolInfo
            Select Case node.Kind()
                Case SyntaxKind.ClassBlock
                    Dim classDecl = CType(node, ClassBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
821 822 823 824 825
                        classDecl.ClassStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Class, classDecl.ClassStatement.Identifier.Span,
                        GetInheritanceNames(classDecl))
826 827 828 829 830 831
                    Return True
                Case SyntaxKind.ConstructorBlock
                    Dim constructor = CType(node, ConstructorBlockSyntax)
                    Dim typeBlock = TryCast(constructor.Parent, TypeBlockSyntax)
                    If typeBlock IsNot Nothing Then
                        declaredSymbolInfo = New DeclaredSymbolInfo(
832 833 834 835 836 837 838
                            typeBlock.BlockStatement.Identifier.ValueText,
                            GetContainerDisplayName(node.Parent),
                            GetFullyQualifiedContainerName(node.Parent),
                            DeclaredSymbolInfoKind.Constructor,
                            constructor.SubNewStatement.NewKeyword.Span,
                            ImmutableArray(Of String).Empty,
                            parameterCount:=CType(If(constructor.SubNewStatement.ParameterList?.Parameters.Count, 0), UShort))
839

840 841 842 843 844
                        Return True
                    End If
                Case SyntaxKind.DelegateFunctionStatement, SyntaxKind.DelegateSubStatement
                    Dim delegateDecl = CType(node, DelegateStatementSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
845 846 847 848 849
                        delegateDecl.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Delegate, delegateDecl.Identifier.Span,
                        ImmutableArray(Of String).Empty)
850 851 852 853
                    Return True
                Case SyntaxKind.EnumBlock
                    Dim enumDecl = CType(node, EnumBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
854 855 856 857 858
                        enumDecl.EnumStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Enum, enumDecl.EnumStatement.Identifier.Span,
                        ImmutableArray(Of String).Empty)
859 860 861 862
                    Return True
                Case SyntaxKind.EnumMemberDeclaration
                    Dim enumMember = CType(node, EnumMemberDeclarationSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
863 864 865 866 867
                        enumMember.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.EnumMember, enumMember.Identifier.Span,
                        ImmutableArray(Of String).Empty)
868 869 870 871 872
                    Return True
                Case SyntaxKind.EventStatement
                    Dim eventDecl = CType(node, EventStatementSyntax)
                    Dim eventParent = If(TypeOf node.Parent Is EventBlockSyntax, node.Parent.Parent, node.Parent)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
873 874 875 876 877
                        eventDecl.Identifier.ValueText,
                        GetContainerDisplayName(eventParent),
                        GetFullyQualifiedContainerName(eventParent),
                        DeclaredSymbolInfoKind.Event, eventDecl.Identifier.Span,
                        ImmutableArray(Of String).Empty)
878 879 880 881
                    Return True
                Case SyntaxKind.FunctionBlock, SyntaxKind.SubBlock
                    Dim funcDecl = CType(node, MethodBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
882 883 884 885 886 887 888 889
                        funcDecl.SubOrFunctionStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Method,
                        funcDecl.SubOrFunctionStatement.Identifier.Span,
                        ImmutableArray(Of String).Empty,
                        parameterCount:=CType(If(funcDecl.SubOrFunctionStatement.ParameterList?.Parameters.Count, 0), UShort),
                        typeParameterCount:=CType(If(funcDecl.SubOrFunctionStatement.TypeParameterList?.Parameters.Count, 0), UShort))
890 891 892 893
                    Return True
                Case SyntaxKind.InterfaceBlock
                    Dim interfaceDecl = CType(node, InterfaceBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
894 895 896 897 898
                        interfaceDecl.InterfaceStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Interface, interfaceDecl.InterfaceStatement.Identifier.Span,
                        GetInheritanceNames(interfaceDecl))
899 900 901 902 903 904 905
                    Return True
                Case SyntaxKind.ModifiedIdentifier
                    Dim modifiedIdentifier = CType(node, ModifiedIdentifierSyntax)
                    Dim variableDeclarator = TryCast(modifiedIdentifier.Parent, VariableDeclaratorSyntax)
                    Dim fieldDecl = TryCast(variableDeclarator?.Parent, FieldDeclarationSyntax)
                    If fieldDecl IsNot Nothing Then
                        Dim kind = If(fieldDecl.Modifiers.Any(Function(m) m.Kind() = SyntaxKind.ConstKeyword),
906 907
                            DeclaredSymbolInfoKind.Constant,
                            DeclaredSymbolInfoKind.Field)
908
                        declaredSymbolInfo = New DeclaredSymbolInfo(
909 910 911 912 913
                            modifiedIdentifier.Identifier.ValueText,
                            GetContainerDisplayName(fieldDecl.Parent),
                            GetFullyQualifiedContainerName(fieldDecl.Parent),
                            kind, modifiedIdentifier.Identifier.Span,
                            ImmutableArray(Of String).Empty)
914 915 916 917 918
                        Return True
                    End If
                Case SyntaxKind.ModuleBlock
                    Dim moduleDecl = CType(node, ModuleBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
919 920 921 922 923
                        moduleDecl.ModuleStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Module, moduleDecl.ModuleStatement.Identifier.Span,
                        GetInheritanceNames(moduleDecl))
924 925 926 927 928
                    Return True
                Case SyntaxKind.PropertyStatement
                    Dim propertyDecl = CType(node, PropertyStatementSyntax)
                    Dim propertyParent = If(TypeOf node.Parent Is PropertyBlockSyntax, node.Parent.Parent, node.Parent)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
929 930 931 932 933
                        propertyDecl.Identifier.ValueText,
                        GetContainerDisplayName(propertyParent),
                        GetFullyQualifiedContainerName(propertyParent),
                        DeclaredSymbolInfoKind.Property, propertyDecl.Identifier.Span,
                        ImmutableArray(Of String).Empty)
934 935 936 937
                    Return True
                Case SyntaxKind.StructureBlock
                    Dim structDecl = CType(node, StructureBlockSyntax)
                    declaredSymbolInfo = New DeclaredSymbolInfo(
938 939 940 941 942
                        structDecl.StructureStatement.Identifier.ValueText,
                        GetContainerDisplayName(node.Parent),
                        GetFullyQualifiedContainerName(node.Parent),
                        DeclaredSymbolInfoKind.Struct, structDecl.StructureStatement.Identifier.Span,
                        GetInheritanceNames(structDecl))
943 944
                    Return True
            End Select
945

946 947 948 949 950
            declaredSymbolInfo = Nothing
            Return False
        End Function

        Private Function GetInheritanceNames(typeBlock As TypeBlockSyntax) As ImmutableArray(Of String)
951
            Dim builder = ArrayBuilder(Of String).GetInstance()
952 953 954 955 956 957 958 959 960 961 962

            Dim aliasMap = GetAliasMap(typeBlock)
            Try
                For Each inheritsStatement In typeBlock.Inherits
                    AddInheritanceNames(builder, inheritsStatement.Types, aliasMap)
                Next

                For Each implementsStatement In typeBlock.Implements
                    AddInheritanceNames(builder, implementsStatement.Types, aliasMap)
                Next

963
                Return builder.ToImmutableAndFree()
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
            Finally
                FreeAliasMap(aliasMap)
            End Try
        End Function

        Private Function GetAliasMap(typeBlock As TypeBlockSyntax) As Dictionary(Of String, String)
            Dim compilationUnit = typeBlock.SyntaxTree.GetCompilationUnitRoot()

            Dim aliasMap As Dictionary(Of String, String) = Nothing
            For Each import In compilationUnit.Imports
                For Each clause In import.ImportsClauses
                    If clause.IsKind(SyntaxKind.SimpleImportsClause) Then
                        Dim simpleImport = DirectCast(clause, SimpleImportsClauseSyntax)
                        If simpleImport.Alias IsNot Nothing Then
                            Dim mappedName = GetTypeName(simpleImport.Name)
                            If mappedName IsNot Nothing Then
                                aliasMap = If(aliasMap, AllocateAliasMap())
                                aliasMap(simpleImport.Alias.Identifier.ValueText) = mappedName
982 983
                            End If
                        End If
984
                    End If
985
                Next
986
            Next
987

988 989
            Return aliasMap
        End Function
990

991
        Private Sub AddInheritanceNames(
992
                builder As ArrayBuilder(Of String),
993 994
                types As SeparatedSyntaxList(Of TypeSyntax),
                aliasMap As Dictionary(Of String, String))
995

996 997 998 999
            For Each typeSyntax In types
                AddInheritanceName(builder, typeSyntax, aliasMap)
            Next
        End Sub
1000

1001
        Private Sub AddInheritanceName(
1002
                builder As ArrayBuilder(Of String),
1003 1004
                typeSyntax As TypeSyntax,
                aliasMap As Dictionary(Of String, String))
1005 1006 1007 1008 1009 1010 1011 1012
            Dim name = GetTypeName(typeSyntax)
            If name IsNot Nothing Then
                builder.Add(name)

                Dim mappedName As String = Nothing
                If aliasMap?.TryGetValue(name, mappedName) = True Then
                    ' Looks Like this could be an alias.  Also include the name the alias points to
                    builder.Add(mappedName)
1013
                End If
1014 1015
            End If
        End Sub
1016

1017 1018 1019 1020 1021 1022
        Private Function GetTypeName(typeSyntax As TypeSyntax) As String
            If TypeOf typeSyntax Is SimpleNameSyntax Then
                Return GetSimpleName(DirectCast(typeSyntax, SimpleNameSyntax))
            ElseIf TypeOf typeSyntax Is QualifiedNameSyntax Then
                Return GetSimpleName(DirectCast(typeSyntax, QualifiedNameSyntax).Right)
            End If
1023

1024 1025
            Return Nothing
        End Function
1026

1027 1028 1029
        Private Function GetSimpleName(simpleName As SimpleNameSyntax) As String
            Return simpleName.Identifier.ValueText
        End Function
1030

1031 1032 1033
        Private Function GetContainerDisplayName(node As SyntaxNode) As String
            Return GetDisplayName(node, DisplayNameOptions.IncludeTypeParameters)
        End Function
1034

1035 1036 1037
        Private Function GetFullyQualifiedContainerName(node As SyntaxNode) As String
            Return GetDisplayName(node, DisplayNameOptions.IncludeNamespaces)
        End Function
1038

1039
        Private Const s_dotToken As String = "."
1040

1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
        Public Function GetDisplayName(node As SyntaxNode, options As DisplayNameOptions, Optional rootNamespace As String = Nothing) As String Implements ISyntaxFactsService.GetDisplayName
            If node Is Nothing Then
                Return String.Empty
            End If

            Dim pooled = PooledStringBuilder.GetInstance()
            Dim builder = pooled.Builder

            ' member keyword (if any)
            Dim memberDeclaration = TryCast(node, DeclarationStatementSyntax)
            If (options And DisplayNameOptions.IncludeMemberKeyword) <> 0 Then
                Dim keywordToken = memberDeclaration.GetMemberKeywordToken()
                If keywordToken <> Nothing AndAlso Not keywordToken.IsMissing Then
                    builder.Append(keywordToken.Text)
                    builder.Append(" "c)
1056
                End If
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
            End If

            Dim names = ArrayBuilder(Of String).GetInstance()
            ' containing type(s)
            Dim parent = node.Parent
            While TypeOf parent Is TypeBlockSyntax
                names.Push(GetName(parent, options, containsGlobalKeyword:=False))
                parent = parent.Parent
            End While
            If (options And DisplayNameOptions.IncludeNamespaces) <> 0 Then
                ' containing namespace(s) in source (if any)
                Dim containsGlobalKeyword As Boolean = False
                While parent IsNot Nothing AndAlso parent.Kind() = SyntaxKind.NamespaceBlock
                    names.Push(GetName(parent, options, containsGlobalKeyword))
1071 1072
                    parent = parent.Parent
                End While
1073 1074 1075 1076
                ' root namespace (if any)
                If Not containsGlobalKeyword AndAlso Not String.IsNullOrEmpty(rootNamespace) Then
                    builder.Append(rootNamespace)
                    builder.Append(s_dotToken)
1077
                End If
1078 1079 1080 1081 1082 1083
            End If
            While Not names.IsEmpty()
                Dim name = names.Pop()
                If name IsNot Nothing Then
                    builder.Append(name)
                    builder.Append(s_dotToken)
1084
                End If
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
            End While
            names.Free()

            ' name (include generic type parameters)
            builder.Append(GetName(node, options, containsGlobalKeyword:=False))

            ' parameter list (if any)
            If (options And DisplayNameOptions.IncludeParameters) <> 0 Then
                builder.Append(memberDeclaration.GetParameterList())
            End If

            ' As clause (if any)
            If (options And DisplayNameOptions.IncludeType) <> 0 Then
                Dim asClause = memberDeclaration.GetAsClause()
                If asClause IsNot Nothing Then
                    builder.Append(" "c)
                    builder.Append(asClause)
1102
                End If
1103
            End If
1104

1105 1106
            Return pooled.ToStringAndFree()
        End Function
1107

1108 1109
        Private Shared Function GetName(node As SyntaxNode, options As DisplayNameOptions, ByRef containsGlobalKeyword As Boolean) As String
            Const missingTokenPlaceholder As String = "?"
1110

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
            Select Case node.Kind()
                Case SyntaxKind.CompilationUnit
                    Return Nothing
                Case SyntaxKind.IdentifierName
                    Dim identifier = DirectCast(node, IdentifierNameSyntax).Identifier
                    Return If(identifier.IsMissing, missingTokenPlaceholder, identifier.Text)
                Case SyntaxKind.IncompleteMember
                    Return missingTokenPlaceholder
                Case SyntaxKind.NamespaceBlock
                    Dim nameSyntax = CType(node, NamespaceBlockSyntax).NamespaceStatement.Name
                    If nameSyntax.Kind() = SyntaxKind.GlobalName Then
                        containsGlobalKeyword = True
1123
                        Return Nothing
1124 1125
                    Else
                        Return GetName(nameSyntax, options, containsGlobalKeyword)
1126
                    End If
1127 1128 1129 1130 1131 1132 1133
                Case SyntaxKind.QualifiedName
                    Dim qualified = CType(node, QualifiedNameSyntax)
                    If qualified.Left.Kind() = SyntaxKind.GlobalName Then
                        containsGlobalKeyword = True
                        Return GetName(qualified.Right, options, containsGlobalKeyword) ' don't use the Global prefix if specified
                    Else
                        Return GetName(qualified.Left, options, containsGlobalKeyword) + s_dotToken + GetName(qualified.Right, options, containsGlobalKeyword)
1134
                    End If
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
            End Select

            Dim name As String = Nothing
            Dim memberDeclaration = TryCast(node, DeclarationStatementSyntax)
            If memberDeclaration IsNot Nothing Then
                Dim nameToken = memberDeclaration.GetNameToken()
                If nameToken <> Nothing Then
                    name = If(nameToken.IsMissing, missingTokenPlaceholder, nameToken.Text)
                    If (options And DisplayNameOptions.IncludeTypeParameters) <> 0 Then
                        Dim pooled = PooledStringBuilder.GetInstance()
                        Dim builder = pooled.Builder
                        builder.Append(name)
                        AppendTypeParameterList(builder, memberDeclaration.GetTypeParameterList())
                        name = pooled.ToStringAndFree()
1149
                    End If
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
                End If
            End If
            Debug.Assert(name IsNot Nothing, "Unexpected node type " + node.Kind().ToString())
            Return name
        End Function

        Private Shared Sub AppendTypeParameterList(builder As StringBuilder, typeParameterList As TypeParameterListSyntax)
            If typeParameterList IsNot Nothing AndAlso typeParameterList.Parameters.Count > 0 Then
                builder.Append("(Of ")
                builder.Append(typeParameterList.Parameters(0).Identifier.Text)
                For i = 1 To typeParameterList.Parameters.Count - 1
                    builder.Append(", ")
                    builder.Append(typeParameterList.Parameters(i).Identifier.Text)
1163
                Next
1164 1165 1166
                builder.Append(")"c)
            End If
        End Sub
P
Pilchie 已提交
1167

1168 1169 1170 1171 1172 1173
        Private Sub AppendMethodLevelMembers(node As SyntaxNode, list As List(Of SyntaxNode))
            For Each member In node.GetMembers()
                If IsTopLevelNodeWithMembers(member) Then
                    AppendMethodLevelMembers(member, list)
                    Continue For
                End If
P
Pilchie 已提交
1174

1175 1176 1177 1178 1179
                If IsMethodLevelMember(member) Then
                    list.Add(member)
                End If
            Next
        End Sub
P
Pilchie 已提交
1180

1181 1182
        Public Function GetMethodLevelMemberId(root As SyntaxNode, node As SyntaxNode) As Integer Implements ISyntaxFactsService.GetMethodLevelMemberId
            Contract.Requires(root.SyntaxTree Is node.SyntaxTree)
P
Pilchie 已提交
1183

1184 1185 1186
            Dim currentId As Integer = Nothing
            Dim currentNode As SyntaxNode = Nothing
            Contract.ThrowIfFalse(TryGetMethodLevelMember(root, Function(n, i) n Is node, currentId, currentNode))
1187

1188 1189
            Contract.ThrowIfFalse(currentId >= 0)
            CheckMemberId(root, node, currentId)
P
Pilchie 已提交
1190

1191 1192 1193 1194 1195 1196
            Return currentId
        End Function

        Public Function GetMethodLevelMember(root As SyntaxNode, memberId As Integer) As SyntaxNode Implements ISyntaxFactsService.GetMethodLevelMember
            Dim currentId As Integer = Nothing
            Dim currentNode As SyntaxNode = Nothing
P
Pilchie 已提交
1197

1198 1199 1200 1201 1202 1203
            If Not TryGetMethodLevelMember(root, Function(n, i) i = memberId, currentId, currentNode) Then
                Return Nothing
            End If

            Contract.ThrowIfNull(currentNode)
            CheckMemberId(root, currentNode, memberId)
P
Pilchie 已提交
1204

1205 1206
            Return currentNode
        End Function
P
Pilchie 已提交
1207

1208 1209 1210
        Private Function TryGetMethodLevelMember(node As SyntaxNode, predicate As Func(Of SyntaxNode, Integer, Boolean), ByRef currentId As Integer, ByRef currentNode As SyntaxNode) As Boolean
            For Each member In node.GetMembers()
                If TypeOf member Is NamespaceBlockSyntax OrElse
1211 1212
                   TypeOf member Is TypeBlockSyntax OrElse
                   TypeOf member Is EnumBlockSyntax Then
1213 1214
                    If TryGetMethodLevelMember(member, predicate, currentId, currentNode) Then
                        Return True
P
Pilchie 已提交
1215 1216
                    End If

1217 1218
                    Continue For
                End If
P
Pilchie 已提交
1219

1220 1221 1222 1223
                If IsMethodLevelMember(member) Then
                    If predicate(member, currentId) Then
                        currentNode = member
                        Return True
1224
                    End If
P
Pilchie 已提交
1225

1226 1227 1228
                    currentId = currentId + 1
                End If
            Next
P
Pilchie 已提交
1229

1230 1231 1232
            currentNode = Nothing
            Return False
        End Function
P
Pilchie 已提交
1233

1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
        <Conditional("DEBUG")>
        Private Sub CheckMemberId(root As SyntaxNode, node As SyntaxNode, memberId As Integer)
            Dim list = GetMethodLevelMembers(root)
            Dim index = list.IndexOf(node)
            Contract.ThrowIfFalse(index = memberId)
        End Sub

        Public Function GetBindableParent(token As SyntaxToken) As SyntaxNode Implements ISyntaxFactsService.GetBindableParent
            Dim node = token.Parent
            While node IsNot Nothing
                Dim parent = node.Parent

                ' If this node is on the left side of a member access expression, don't ascend
                ' further or we'll end up binding to something else.
                Dim memberAccess = TryCast(parent, MemberAccessExpressionSyntax)
                If memberAccess IsNot Nothing Then
                    If memberAccess.Expression Is node Then
                        Exit While
P
Pilchie 已提交
1252
                    End If
1253
                End If
P
Pilchie 已提交
1254

1255 1256 1257 1258 1259
                ' If this node is on the left side of a qualified name, don't ascend
                ' further or we'll end up binding to something else.
                Dim qualifiedName = TryCast(parent, QualifiedNameSyntax)
                If qualifiedName IsNot Nothing Then
                    If qualifiedName.Left Is node Then
P
Pilchie 已提交
1260 1261
                        Exit While
                    End If
1262
                End If
P
Pilchie 已提交
1263

1264 1265 1266 1267 1268 1269
                ' If this node is the type of an object creation expression, return the
                ' object creation expression.
                Dim objectCreation = TryCast(parent, ObjectCreationExpressionSyntax)
                If objectCreation IsNot Nothing Then
                    If objectCreation.Type Is node Then
                        node = parent
P
Pilchie 已提交
1270 1271
                        Exit While
                    End If
1272
                End If
P
Pilchie 已提交
1273

1274 1275 1276
                ' The inside of an interpolated string is treated as its own token so we
                ' need to force navigation to the parent expression syntax.
                If TypeOf node Is InterpolatedStringTextSyntax AndAlso TypeOf parent Is InterpolatedStringExpressionSyntax Then
1277
                    node = parent
1278 1279
                    Exit While
                End If
1280

1281 1282 1283 1284
                ' If this node is not parented by a name, we're done.
                Dim name = TryCast(parent, NameSyntax)
                If name Is Nothing Then
                    Exit While
P
Pilchie 已提交
1285 1286
                End If

1287 1288
                node = parent
            End While
P
Pilchie 已提交
1289

1290 1291
            Return node
        End Function
P
Pilchie 已提交
1292

1293 1294 1295 1296 1297
        Public Function GetConstructors(root As SyntaxNode, cancellationToken As CancellationToken) As IEnumerable(Of SyntaxNode) Implements ISyntaxFactsService.GetConstructors
            Dim compilationUnit = TryCast(root, CompilationUnitSyntax)
            If compilationUnit Is Nothing Then
                Return SpecializedCollections.EmptyEnumerable(Of SyntaxNode)()
            End If
P
Pilchie 已提交
1298

1299 1300 1301 1302
            Dim constructors = New List(Of SyntaxNode)()
            AppendConstructors(compilationUnit.Members, constructors, cancellationToken)
            Return constructors
        End Function
P
Pilchie 已提交
1303

1304 1305 1306
        Private Sub AppendConstructors(members As SyntaxList(Of StatementSyntax), constructors As List(Of SyntaxNode), cancellationToken As CancellationToken)
            For Each member As StatementSyntax In members
                cancellationToken.ThrowIfCancellationRequested()
P
Pilchie 已提交
1307

1308 1309 1310 1311 1312
                Dim constructor = TryCast(member, ConstructorBlockSyntax)
                If constructor IsNot Nothing Then
                    constructors.Add(constructor)
                    Continue For
                End If
P
Pilchie 已提交
1313

1314 1315 1316
                Dim [namespace] = TryCast(member, NamespaceBlockSyntax)
                If [namespace] IsNot Nothing Then
                    AppendConstructors([namespace].Members, constructors, cancellationToken)
P
Pilchie 已提交
1317 1318
                End If

1319 1320 1321 1322
                Dim [class] = TryCast(member, ClassBlockSyntax)
                If [class] IsNot Nothing Then
                    AppendConstructors([class].Members, constructors, cancellationToken)
                End If
P
Pilchie 已提交
1323

1324 1325 1326
                Dim [struct] = TryCast(member, StructureBlockSyntax)
                If [struct] IsNot Nothing Then
                    AppendConstructors([struct].Members, constructors, cancellationToken)
P
Pilchie 已提交
1327
                End If
1328 1329
            Next
        End Sub
1330

1331 1332 1333 1334 1335 1336 1337 1338
        Public Function GetInactiveRegionSpanAroundPosition(tree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As TextSpan Implements ISyntaxFactsService.GetInactiveRegionSpanAroundPosition
            Dim trivia = tree.FindTriviaToLeft(position, cancellationToken)
            If trivia.Kind = SyntaxKind.DisabledTextTrivia Then
                Return trivia.FullSpan
            End If

            Return Nothing
        End Function
1339

1340 1341 1342 1343
        Public Function GetNameForArgument(argument As SyntaxNode) As String Implements ISyntaxFactsService.GetNameForArgument
            If TryCast(argument, ArgumentSyntax)?.IsNamed Then
                Return DirectCast(argument, SimpleArgumentSyntax).NameColonEquals.Name.Identifier.ValueText
            End If
1344

1345 1346 1347 1348 1349 1350 1351 1352 1353
            Return String.Empty
        End Function

        Public Function IsLeftSideOfDot(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLeftSideOfDot
            Return TryCast(node, ExpressionSyntax).IsLeftSideOfDot()
        End Function

        Public Function GetRightSideOfDot(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetRightSideOfDot
            Return If(TryCast(node, QualifiedNameSyntax)?.Right,
1354
                      TryCast(node, MemberAccessExpressionSyntax)?.Name)
1355
        End Function
1356

1357 1358 1359
        Public Function IsLeftSideOfAssignment(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLeftSideOfAssignment
            Return TryCast(node, ExpressionSyntax).IsLeftSideOfAnyAssignStatement
        End Function
1360

1361 1362 1363
        Public Function IsLeftSideOfAnyAssignment(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLeftSideOfAnyAssignment
            Return TryCast(node, ExpressionSyntax).IsLeftSideOfAnyAssignStatement
        End Function
1364

1365 1366 1367
        Public Function GetRightHandSideOfAssignment(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetRightHandSideOfAssignment
            Return TryCast(node, AssignmentStatementSyntax)?.Right
        End Function
1368

1369 1370 1371
        Public Function IsInferredAnonymousObjectMemberDeclarator(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInferredAnonymousObjectMemberDeclarator
            Return node.IsKind(SyntaxKind.InferredFieldInitializer)
        End Function
1372

1373 1374 1375
        Public Function IsOperandOfIncrementExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsOperandOfIncrementExpression
            Return False
        End Function
1376

1377 1378 1379
        Public Function IsOperandOfIncrementOrDecrementExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsOperandOfIncrementOrDecrementExpression
            Return False
        End Function
1380

1381 1382 1383
        Public Function GetContentsOfInterpolatedString(interpolatedString As SyntaxNode) As SyntaxList(Of SyntaxNode) Implements ISyntaxFactsService.GetContentsOfInterpolatedString
            Return (TryCast(interpolatedString, InterpolatedStringExpressionSyntax)?.Contents).Value
        End Function
1384

1385 1386 1387
        Public Function IsStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsStringLiteral
            Return token.IsKind(SyntaxKind.StringLiteralToken)
        End Function
1388

1389
        Public Function IsStringLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsStringLiteralExpression
C
CyrusNajmabadi 已提交
1390
            Return node.Kind() = SyntaxKind.StringLiteralExpression
1391 1392
        End Function

C
CyrusNajmabadi 已提交
1393 1394 1395 1396 1397
        Public Function IsVerbatimStringLiteral(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsVerbatimStringLiteral
            ' VB does not have verbatim strings
            Return False
        End Function

C
CyrusNajmabadi 已提交
1398
        Public Function GetArgumentsOfInvocationExpression(invocationExpression As SyntaxNode) As SeparatedSyntaxList(Of SyntaxNode) Implements ISyntaxFactsService.GetArgumentsOfInvocationExpression
1399 1400
            Dim arguments = TryCast(invocationExpression, InvocationExpressionSyntax)?.ArgumentList?.Arguments
            Return If(arguments.HasValue, arguments.Value, Nothing)
1401
        End Function
1402

1403 1404 1405
        Public Function ConvertToSingleLine(node As SyntaxNode, Optional useElasticTrivia As Boolean = False) As SyntaxNode Implements ISyntaxFactsService.ConvertToSingleLine
            Return node.ConvertToSingleLine(useElasticTrivia)
        End Function
P
Paul Vick 已提交
1406 1407 1408 1409 1410

        Public Function IsDocumentationComment(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDocumentationComment
            Return node.IsKind(SyntaxKind.DocumentationCommentTrivia)
        End Function

P
Paul Vick 已提交
1411
        Public Function IsUsingOrExternOrImport(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsUsingOrExternOrImport
P
Paul Vick 已提交
1412 1413 1414 1415
            Return node.IsKind(SyntaxKind.ImportsStatement)
        End Function

        Public Function IsGlobalAttribute(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsGlobalAttribute
P
Paul Vick 已提交
1416 1417 1418 1419 1420 1421 1422 1423
            If node.IsKind(SyntaxKind.Attribute) Then
                Dim attributeNode = CType(node, AttributeSyntax)
                If attributeNode.Target IsNot Nothing Then
                    Return attributeNode.Target.AttributeModifier.IsKind(SyntaxKind.AssemblyKeyword)
                End If
            End If

            Return False
P
Paul Vick 已提交
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
        End Function

        Public Function IsDeclaration(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDeclaration
            ' From the Visual Basic language spec:
            ' NamespaceMemberDeclaration  :=
            '    NamespaceDeclaration  |
            '    TypeDeclaration
            ' TypeDeclaration  ::=
            '    ModuleDeclaration  |
            '    NonModuleDeclaration
            ' NonModuleDeclaration  ::=
            '    EnumDeclaration  |
            '    StructureDeclaration  |
            '    InterfaceDeclaration  |
            '    ClassDeclaration  |
            '    DelegateDeclaration
            ' ClassMemberDeclaration  ::=
            '    NonModuleDeclaration  |
            '    EventMemberDeclaration  |
            '    VariableMemberDeclaration  |
            '    ConstantMemberDeclaration  |
            '    MethodMemberDeclaration  |
            '    PropertyMemberDeclaration  |
            '    ConstructorMemberDeclaration  |
            '    OperatorDeclaration
            Select Case node.Kind()
                ' Because fields declarations can define multiple symbols "Public a, b As Integer" 
                ' We want to get the VariableDeclarator node inside the field declaration to print out the symbol for the name.
                Case SyntaxKind.VariableDeclarator
                    If (node.Parent.IsKind(SyntaxKind.FieldDeclaration)) Then
                        Return True
                    End If
                    Return False

P
Paul Vick 已提交
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
                Case SyntaxKind.NamespaceStatement,
                     SyntaxKind.NamespaceBlock,
                     SyntaxKind.ModuleStatement,
                     SyntaxKind.ModuleBlock,
                     SyntaxKind.EnumStatement,
                     SyntaxKind.EnumBlock,
                     SyntaxKind.StructureStatement,
                     SyntaxKind.StructureBlock,
                     SyntaxKind.InterfaceStatement,
                     SyntaxKind.InterfaceBlock,
                     SyntaxKind.ClassStatement,
                     SyntaxKind.ClassBlock,
                     SyntaxKind.DelegateFunctionStatement,
                     SyntaxKind.DelegateSubStatement,
                     SyntaxKind.EventStatement,
                     SyntaxKind.EventBlock,
                     SyntaxKind.AddHandlerAccessorBlock,
                     SyntaxKind.RemoveHandlerAccessorBlock,
                     SyntaxKind.FieldDeclaration,
                     SyntaxKind.SubStatement,
                     SyntaxKind.SubBlock,
                     SyntaxKind.FunctionStatement,
                     SyntaxKind.FunctionBlock,
                     SyntaxKind.PropertyStatement,
                     SyntaxKind.PropertyBlock,
                     SyntaxKind.GetAccessorBlock,
                     SyntaxKind.SetAccessorBlock,
                     SyntaxKind.SubNewStatement,
                     SyntaxKind.ConstructorBlock,
                     SyntaxKind.OperatorStatement,
                     SyntaxKind.OperatorBlock
P
Paul Vick 已提交
1489 1490 1491 1492 1493
                    Return True
            End Select

            Return False
        End Function
1494 1495 1496 1497 1498 1499

        Public Sub AddFirstMissingCloseBrace(root As SyntaxNode, contextNode As SyntaxNode, ByRef newRoot As SyntaxNode, ByRef newContextNode As SyntaxNode) Implements ISyntaxFactsService.AddFirstMissingCloseBrace
            ' Nothing to be done.  VB doesn't have close braces
            newRoot = root
            newContextNode = contextNode
        End Sub
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550

        Public Function GetObjectCreationInitializer(objectCreationExpression As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetObjectCreationInitializer
            Return DirectCast(objectCreationExpression, ObjectCreationExpressionSyntax).Initializer
        End Function

        Public Function IsSimpleAssignmentStatement(statement As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSimpleAssignmentStatement
            Return statement.IsKind(SyntaxKind.SimpleAssignmentStatement)
        End Function

        Public Sub GetPartsOfAssignmentStatement(statement As SyntaxNode, ByRef left As SyntaxNode, ByRef right As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfAssignmentStatement
            Dim assignment = DirectCast(statement, AssignmentStatementSyntax)
            left = assignment.Left
            right = assignment.Right
        End Sub

        Public Function GetNameOfMemberAccessExpression(memberAccessExpression As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetNameOfMemberAccessExpression
            Return DirectCast(memberAccessExpression, MemberAccessExpressionSyntax).Name
        End Function

        Public Function GetOperatorTokenOfMemberAccessExpression(memberAccessExpression As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetOperatorTokenOfMemberAccessExpression
            Return DirectCast(memberAccessExpression, MemberAccessExpressionSyntax).OperatorToken
        End Function

        Public Function GetIdentifierOfSimpleName(node As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetIdentifierOfSimpleName
            Return DirectCast(node, SimpleNameSyntax).Identifier
        End Function

        Public Function GetIdentifierOfVariableDeclarator(node As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetIdentifierOfVariableDeclarator
            Return DirectCast(node, VariableDeclaratorSyntax).Names.Last().Identifier
        End Function

        Public Function IsIdentifierName(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsIdentifierName
            Return node.IsKind(SyntaxKind.IdentifierName)
        End Function

        Public Function IsLocalDeclarationStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLocalDeclarationStatement
            Return node.IsKind(SyntaxKind.LocalDeclarationStatement)
        End Function

        Public Function IsDeclaratorOfLocalDeclarationStatement(declarator As SyntaxNode, localDeclarationStatement As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDeclaratorOfLocalDeclarationStatement
            Return DirectCast(localDeclarationStatement, LocalDeclarationStatementSyntax).Declarators.
                Contains(DirectCast(declarator, VariableDeclaratorSyntax))
        End Function

        Public Function AreEquivalent(token1 As SyntaxToken, token2 As SyntaxToken) As Boolean Implements ISyntaxFactsService.AreEquivalent
            Return SyntaxFactory.AreEquivalent(token1, token2)
        End Function

        Public Function AreEquivalent(node1 As SyntaxNode, node2 As SyntaxNode) As Boolean Implements ISyntaxFactsService.AreEquivalent
            Return SyntaxFactory.AreEquivalent(node1, node2)
        End Function
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570

        Public Function IsExpressionOfInvocationExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsExpressionOfInvocationExpression
            Return node IsNot Nothing AndAlso TryCast(node.Parent, InvocationExpressionSyntax)?.Expression Is node
        End Function

        Public Function IsExpressionOfAwaitExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsExpressionOfAwaitExpression
            Return node IsNot Nothing AndAlso TryCast(node.Parent, AwaitExpressionSyntax)?.Expression Is node
        End Function

        Public Function IsExpressionOfMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsExpressionOfMemberAccessExpression
            Return node IsNot Nothing AndAlso TryCast(node.Parent, MemberAccessExpressionSyntax)?.Expression Is node
        End Function

        Public Function GetExpressionOfInvocationExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfInvocationExpression
            Return DirectCast(node, InvocationExpressionSyntax).Expression
        End Function

        Public Function GetExpressionOfAwaitExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfAwaitExpression
            Return DirectCast(node, AwaitExpressionSyntax).Expression
        End Function
1571 1572 1573 1574 1575 1576 1577 1578 1579

        Public Function IsPossibleTupleContext(
            syntaxTree As SyntaxTree,
            position As Integer,
            cancellationToken As CancellationToken) As Boolean Implements ISyntaxFactsService.IsPossibleTupleContext

            Dim token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken)
            Return syntaxTree.IsPossibleTupleContext(token, position)
        End Function
1580 1581 1582 1583 1584

        Public Function GetExpressionOfExpressionStatement(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfExpressionStatement
            Return DirectCast(node, ExpressionStatementSyntax).Expression
        End Function

1585 1586 1587 1588
        Public Function IsNullLiteralExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsNullLiteralExpression
            Return node.Kind() = SyntaxKind.NothingLiteralExpression
        End Function

1589 1590 1591 1592
        Public Function IsBinaryExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsBinaryExpression
            Return TypeOf node Is BinaryExpressionSyntax
        End Function

1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604
        Public Sub GetPartsOfBinaryExpression(node As SyntaxNode, ByRef left As SyntaxNode, ByRef right As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfBinaryExpression
            Dim binaryExpression = DirectCast(node, BinaryExpressionSyntax)
            left = binaryExpression.Left
            right = binaryExpression.Right
        End Sub

        Public Sub GetPartsOfConditionalExpression(node As SyntaxNode, ByRef condition As SyntaxNode, ByRef whenTrue As SyntaxNode, ByRef whenFalse As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfConditionalExpression
            Dim conditionalExpression = DirectCast(node, TernaryConditionalExpressionSyntax)
            condition = conditionalExpression.Condition
            whenTrue = conditionalExpression.WhenTrue
            whenFalse = conditionalExpression.WhenFalse
        End Sub
1605 1606 1607 1608

        Public Function WalkDownParentheses(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.WalkDownParentheses
            Return If(TryCast(node, ExpressionSyntax)?.WalkDownParentheses(), node)
        End Function
1609 1610 1611 1612 1613 1614 1615 1616 1617

        Public Function IsLogicalNotExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLogicalNotExpression
            Return node.IsKind(SyntaxKind.NotExpression)
        End Function

        Public Function GetOperandOfPrefixUnaryExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetOperandOfPrefixUnaryExpression
            Return DirectCast(node, UnaryExpressionSyntax).Operand
        End Function

1618 1619 1620 1621 1622
        Public Sub GetPartsOfMemberAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef name As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfMemberAccessExpression
            Dim memberAccess = DirectCast(node, MemberAccessExpressionSyntax)
            expression = memberAccess.Expression
            name = memberAccess.Name
        End Sub
1623

1624 1625
        Public Function GetNextExecutableStatement(statement As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetNextExecutableStatement
            Return DirectCast(statement, StatementSyntax).GetNextStatement()?.FirstAncestorOrSelf(Of ExecutableStatementSyntax)
1626
        End Function
C
CyrusNajmabadi 已提交
1627

1628 1629 1630 1631 1632 1633 1634
        Public Function IsWhitespaceTrivia(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsWhitespaceTrivia
            Return trivia.IsWhitespace()
        End Function

        Public Function IsEndOfLineTrivia(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsEndOfLineTrivia
            Return trivia.IsEndOfLine()
        End Function
C
CyrusNajmabadi 已提交
1635 1636 1637 1638 1639 1640 1641 1642

        Public Function IsRegularComment(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsRegularComment
            Return trivia.Kind = SyntaxKind.CommentTrivia
        End Function

        Public Function IsDocumentationComment(trivia As SyntaxTrivia) As Boolean Implements ISyntaxFactsService.IsDocumentationComment
            Return trivia.Kind = SyntaxKind.DocumentationCommentTrivia
        End Function
1643 1644 1645 1646 1647 1648 1649 1650

        Public Function IsOnTypeHeader(root As SyntaxNode, position As Integer) As Boolean Implements ISyntaxFactsService.IsOnTypeHeader
            Return False
        End Function

        Public Function IsBetweenTypeMembers(sourceText As SourceText, root As SyntaxNode, position As Integer) As Boolean Implements ISyntaxFactsService.IsBetweenTypeMembers
            Return False
        End Function
C
CyrusNajmabadi 已提交
1651 1652 1653 1654

        Public Function GetSelectedMembers(root As SyntaxNode, textSpan As TextSpan) As ImmutableArray(Of SyntaxNode) Implements ISyntaxFactsService.GetSelectedMembers
            Return ImmutableArray(Of SyntaxNode).CastUp(root.GetMembersInSpan(textSpan))
        End Function
C
CyrusNajmabadi 已提交
1655
    End Class
1656
End Namespace