File: CodeRefactorings\NodeSelectionHelpers.vb
Web Access
Project: src\src\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj (Microsoft.CodeAnalysis.VisualBasic.Features)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
 
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings
    Friend Module NodeSelectionHelpers
        Friend Async Function GetSelectedMemberDeclarationAsync(context As CodeRefactoringContext) As Task(Of ImmutableArray(Of SyntaxNode))
            Dim document As Document = context.Document
            Dim span As TextSpan = context.Span
            Dim cancellationToken As CancellationToken = context.CancellationToken
            If span.IsEmpty Then
                ' MethodBaseSyntax also includes properties
                Dim methodMember = Await context.TryGetRelevantNodeAsync(Of MethodBaseSyntax)().ConfigureAwait(False)
                If methodMember IsNot Nothing Then
                    Return ImmutableArray.Create(Of SyntaxNode)(methodMember)
                End If
                ' Gets field variable declarations (not including the keywords like Public/Shared, etc), which are not methods
                Dim fieldDeclaration = Await context.TryGetRelevantNodeAsync(Of FieldDeclarationSyntax).ConfigureAwait(False)
                If fieldDeclaration Is Nothing Then
                    ' Gets the identifier + type of the field itself (ex. TestField As Integer), since it is nested in the variable declaration
                    ' And so the token's parent is not a variable declaration
                    Dim modifiedIdentifier = Await context.TryGetRelevantNodeAsync(Of ModifiedIdentifierSyntax).ConfigureAwait(False)
                    If modifiedIdentifier Is Nothing Then
                        Return ImmutableArray(Of SyntaxNode).Empty
                    Else
                        Return ImmutableArray.Create(Of SyntaxNode)(modifiedIdentifier)
                    End If
                Else
                    ' Field declarations can contain multiple variables (each of which are a "member")
                    Return fieldDeclaration.Declarators.SelectMany(Function(vds) vds.Names).Cast(Of SyntaxNode).AsImmutable()
                End If
            Else
                ' if the span is non-empty, then we get potentially multiple members
                ' Note: even though this method handles the empty span case, we don't use it because it doesn't correctly
                ' pick up on keywords before the declaration, such as "public static int".
                ' We could potentially use it for every case if that behavior changes
                Dim tree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False)
                Dim selectedMembers = Await VisualBasicSelectedMembers.Instance.
                    GetSelectedMembersAsync(tree, span, allowPartialSelection:=True, cancellationToken).ConfigureAwait(False)
                If selectedMembers.OfType(Of IncompleteMemberSyntax)().Any() Then
                    Return ImmutableArray(Of SyntaxNode).Empty
                Else
                    Return selectedMembers
                End If
            End If
        End Function
    End Module
End Namespace