File: SignatureHelp\AbstractIntrinsicOperatorSignatureHelpProvider.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.Threading
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.SignatureHelp
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Utilities.IntrinsicOperators
 
Namespace Microsoft.CodeAnalysis.VisualBasic.SignatureHelp
    Friend MustInherit Class AbstractIntrinsicOperatorSignatureHelpProvider(Of TSyntaxNode As SyntaxNode)
        Inherits AbstractVisualBasicSignatureHelpProvider
 
        Protected MustOverride Function IsTriggerToken(token As SyntaxToken) As Boolean
        Protected MustOverride Function IsArgumentListToken(node As TSyntaxNode, token As SyntaxToken) As Boolean
        Protected MustOverride Function GetIntrinsicOperatorDocumentationAsync(node As TSyntaxNode, document As Document, cancellationToken As CancellationToken) As ValueTask(Of IEnumerable(Of AbstractIntrinsicOperatorDocumentation))
 
        Private Function TryGetSyntaxNode(root As SyntaxNode, position As Integer, syntaxFacts As ISyntaxFactsService, triggerReason As SignatureHelpTriggerReason, cancellationToken As CancellationToken, ByRef node As TSyntaxNode) As Boolean
            Return CommonSignatureHelpUtilities.TryGetSyntax(
                root,
                position,
                syntaxFacts,
                triggerReason,
                AddressOf IsTriggerToken,
                AddressOf IsArgumentListToken,
                cancellationToken,
                node)
        End Function
 
        Protected Overrides Async Function GetItemsWorkerAsync(document As Document, position As Integer, triggerInfo As SignatureHelpTriggerInfo, options As MemberDisplayOptions, cancellationToken As CancellationToken) As Task(Of SignatureHelpItems)
            Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False)
 
            Dim node As TSyntaxNode = Nothing
            If Not TryGetSyntaxNode(root, position, document.GetLanguageService(Of ISyntaxFactsService), triggerInfo.TriggerReason, cancellationToken, node) Then
                Return Nothing
            End If
 
            Dim items As New List(Of SignatureHelpItem)
 
            Dim semanticModel = Await document.ReuseExistingSpeculativeModelAsync(node, cancellationToken).ConfigureAwait(False)
            For Each documentation In Await GetIntrinsicOperatorDocumentationAsync(node, document, cancellationToken).ConfigureAwait(False)
                Dim signatureHelpItem = GetSignatureHelpItemForIntrinsicOperator(document, semanticModel, node.SpanStart, documentation, cancellationToken)
                items.Add(signatureHelpItem)
            Next
 
            Dim textSpan = CommonSignatureHelpUtilities.GetSignatureHelpSpan(node, node.SpanStart, Function(n) n.ChildTokens.FirstOrDefault(Function(c) c.Kind = SyntaxKind.CloseParenToken))
            Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService)
 
            Return CreateSignatureHelpItems(
                items, textSpan,
                GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken), selectedItemIndex:=Nothing, parameterIndexOverride:=-1)
        End Function
 
        Friend Shared Function GetSignatureHelpItemForIntrinsicOperator(document As Document, semanticModel As SemanticModel, position As Integer, documentation As AbstractIntrinsicOperatorDocumentation, cancellationToken As CancellationToken) As SignatureHelpItem
            Dim parameters As New List(Of SignatureHelpSymbolParameter)
 
            For i = 0 To documentation.ParameterCount - 1
                Dim capturedIndex = i
                parameters.Add(
                    New SignatureHelpSymbolParameter(
                        name:=documentation.GetParameterName(i),
                        isOptional:=False,
                        documentationFactory:=Function(c As CancellationToken) documentation.GetParameterDocumentation(capturedIndex).ToSymbolDisplayParts().ToTaggedText(),
                        displayParts:=documentation.GetParameterDisplayParts(i)))
            Next
 
            Dim suffixParts = documentation.GetSuffix(semanticModel, position, Nothing, cancellationToken)
 
            Dim structuralTypeDisplayService = document.GetLanguageService(Of IStructuralTypeDisplayService)()
 
            Return CreateItem(
                Nothing, semanticModel, position,
                structuralTypeDisplayService,
                isVariadic:=False,
                documentationFactory:=Function(c) SpecializedCollections.SingletonEnumerable(New TaggedText(TextTags.Text, documentation.DocumentationText)),
                prefixParts:=documentation.PrefixParts,
                separatorParts:=GetSeparatorParts(),
                suffixParts:=suffixParts,
                parameters:=parameters)
        End Function
 
        Protected Overridable Function GetCurrentArgumentStateWorker(node As SyntaxNode, position As Integer) As SignatureHelpState
            Dim commaTokens As New List(Of SyntaxToken)
            commaTokens.AddRange(node.ChildTokens().Where(Function(token) token.Kind = SyntaxKind.CommaToken))
 
            ' Also get any leading skipped tokens on the next token after this node
            Dim nextToken = node.GetLastToken().GetNextToken()
 
            For Each leadingTrivia In nextToken.LeadingTrivia
                If leadingTrivia.Kind = SyntaxKind.SkippedTokensTrivia Then
                    commaTokens.AddRange(leadingTrivia.GetStructure().ChildTokens().Where(Function(token) token.Kind = SyntaxKind.CommaToken))
                End If
            Next
 
            ' Count how many commas are before us
            Return New SignatureHelpState(
                SemanticParameterIndex:=commaTokens.Where(Function(token) token.SpanStart < position).Count(),
                SyntacticArgumentCount:=commaTokens.Count() + 1,
                ArgumentName:=Nothing,
                ArgumentNames:=Nothing)
        End Function
 
        Private Function GetCurrentArgumentState(root As SyntaxNode, position As Integer, syntaxFacts As ISyntaxFactsService, currentSpan As TextSpan, cancellationToken As CancellationToken) As SignatureHelpState
            Dim node As TSyntaxNode = Nothing
            If TryGetSyntaxNode(root, position, syntaxFacts, SignatureHelpTriggerReason.InvokeSignatureHelpCommand, cancellationToken, node) AndAlso
                currentSpan.Start = node.SpanStart Then
 
                Return GetCurrentArgumentStateWorker(node, position)
            End If
 
            Return Nothing
        End Function
    End Class
End Namespace