File: Completion\CompletionProviders\CompletionUtilities.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 Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.Completion.Providers
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.Text
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
    Friend Module CompletionUtilities
        Private Const UnicodeEllipsis = ChrW(&H2026)
        Private Const OfSuffix = "(Of"
        Private Const GenericSuffix = OfSuffix + " " & UnicodeEllipsis & ")"
 
        Friend ReadOnly CommonTriggerChars As ImmutableHashSet(Of Char) = ImmutableHashSet.Create("."c, "["c, "#"c, " "c, "="c, "<"c, "{"c)
 
        Friend ReadOnly CommonTriggerCharsAndParen As ImmutableHashSet(Of Char) = CommonTriggerChars.Add("("c)
 
        Friend ReadOnly SpaceTriggerChar As ImmutableHashSet(Of Char) = CommonTriggerChars.Add(" "c)
 
        Public Function GetCompletionItemSpan(text As SourceText, position As Integer) As TextSpan
            Return CommonCompletionUtilities.GetWordSpan(
                text, position,
                AddressOf IsCompletionItemStartCharacter,
                AddressOf IsCompletionItemCharacter)
        End Function
 
        Public Function IsWordStartCharacter(ch As Char) As Boolean
            Return SyntaxFacts.IsIdentifierStartCharacter(ch)
        End Function
 
        Private Function IsWordCharacter(ch As Char) As Boolean
            Return SyntaxFacts.IsIdentifierStartCharacter(ch) OrElse SyntaxFacts.IsIdentifierPartCharacter(ch)
        End Function
 
        Private Function IsCompletionItemStartCharacter(ch As Char) As Boolean
            Return ch = "#"c OrElse ch = "["c OrElse IsWordCharacter(ch)
        End Function
 
        Private Function IsCompletionItemCharacter(ch As Char) As Boolean
            Return ch = "]"c OrElse IsWordCharacter(ch)
        End Function
 
        Public Function IsDefaultTriggerCharacter(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean
            Dim ch = text(characterPosition)
            If CommonTriggerChars.Contains(ch) Then
                Return True
            End If
 
            Return IsStartingNewWord(text, characterPosition, options)
        End Function
 
        Public Function IsDefaultTriggerCharacterOrParen(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean
            Dim ch = text(characterPosition)
 
            Return _
                ch = "("c OrElse
                CommonTriggerChars.Contains(ch) OrElse
                IsStartingNewWord(text, characterPosition, options)
        End Function
 
        Public Function IsTriggerAfterSpaceOrStartOfWordCharacter(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean
            ' Bring up on space or at the start of a word.
            Dim ch = text(characterPosition)
 
            Return ch = " "c OrElse IsStartingNewWord(text, characterPosition, options)
        End Function
 
        Private Function IsStartingNewWord(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean
            If Not options.TriggerOnTypingLetters Then
                Return False
            End If
 
            Return CommonCompletionUtilities.IsStartingNewWord(
                text, characterPosition, AddressOf IsWordStartCharacter, AddressOf IsWordCharacter)
        End Function
 
        Public Function GetDisplayAndSuffixAndInsertionText(
            symbol As ISymbol,
            context As SyntaxContext) As (displayText As String, suffix As String, insertionText As String)
 
            Dim name As String = Nothing
            If Not CommonCompletionUtilities.TryRemoveAttributeSuffix(symbol, context, name) Then
                name = symbol.Name
            End If
 
            Dim displayText = GetDisplayText(name, symbol)
            Dim insertionText = GetInsertionText(name, symbol, context)
            Dim suffix = GetSuffix(symbol)
 
            Return (displayText, suffix, insertionText)
        End Function
 
        Private Function GetDisplayText(name As String, symbol As ISymbol) As String
            If symbol.IsConstructor() Then
                Return "New"
            Else
                Return name
            End If
        End Function
 
        Private Function GetSuffix(symbol As ISymbol) As String
            If symbol.IsConstructor() Then
                Return ""
            ElseIf symbol.GetArity() > 0 Then
                Return GenericSuffix
            Else
                Return ""
            End If
        End Function
 
        Private Function GetInsertionText(name As String, symbol As ISymbol, context As SyntaxContext) As String
            name = name.EscapeIdentifier(context.IsRightOfNameSeparator, symbol, context.IsWithinAsyncMethod)
 
            If symbol.IsConstructor() Then
                name = "New"
            ElseIf symbol.GetArity() > 0 Then
                name += OfSuffix
            End If
 
            Return name
        End Function
 
        Public Function GetInsertionTextAtInsertionTime(item As CompletionItem, ch As Char) As String
            Dim insertionText = SymbolCompletionItem.GetInsertionText(item)
 
            ' If this item was generic, customize what we insert depending on if the user typed
            ' open paren or not.
            If ch = "("c AndAlso item.DisplayTextSuffix = GenericSuffix Then
                Return insertionText.Substring(0, insertionText.IndexOf("("c))
            End If
 
            If ch = "]"c Then
                If insertionText(0) <> "["c Then
                    ' user is committing with ].  If the item doesn't start with '['
                    ' then add that to the beginning so [ and ] properly pair up.
                    Return "[" + insertionText
                End If
 
                If insertionText.EndsWith("]") Then
                    ' If the user commits with "]" and the item already ends with "]"
                    ' then trim "]" off the end so we don't have ]] inserted into the
                    ' document.
                    Return insertionText.Substring(0, insertionText.Length - 1)
                End If
            End If
 
            Return insertionText
        End Function
    End Module
End Namespace