File: TaskList\VisualBasicTaskListService.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.Composition
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.TaskList
 
Namespace Microsoft.CodeAnalysis.VisualBasic.TaskList
    <ExportLanguageService(GetType(ITaskListService), LanguageNames.VisualBasic), [Shared]>
    Friend Class VisualBasicTaskListService
        Inherits AbstractTaskListService
 
        <ImportingConstructor>
        <Obsolete(MefConstruction.ImportingConstructorMessage, True)>
        Public Sub New()
        End Sub
 
        Protected Overrides Sub AppendTaskListItems(
                commentDescriptors As ImmutableArray(Of TaskListItemDescriptor),
                document As SyntacticDocument,
                trivia As SyntaxTrivia,
                items As ArrayBuilder(Of TaskListItem))
            If PreprocessorHasComment(trivia) Then
                Dim commentTrivia = trivia.GetStructure().DescendantTrivia().First(Function(t) t.RawKind = SyntaxKind.CommentTrivia)
 
                AppendTaskListItemsOnSingleLine(commentDescriptors, document, commentTrivia.ToFullString(), commentTrivia.FullSpan.Start, items)
                Return
            End If
 
            If IsSingleLineComment(trivia) Then
                ProcessMultilineComment(commentDescriptors, document, trivia, postfixLength:=0, items)
                Return
            End If
 
            Throw ExceptionUtilities.Unreachable
        End Sub
 
        Protected Overrides Function GetNormalizedText(message As String) As String
            Return SyntaxFacts.MakeHalfWidthIdentifier(message)
        End Function
 
        Protected Overrides Function IsIdentifierCharacter(ch As Char) As Boolean
            Return SyntaxFacts.IsIdentifierPartCharacter(ch)
        End Function
 
        Protected Overrides Function GetCommentStartingIndex(message As String) As Integer
            ' 3 for REM
            Dim index = GetFirstCharacterIndex(message)
            If index >= message.Length OrElse
                       index > message.Length - 3 Then
                Return index
            End If
 
            Dim remText = message.Substring(index, "REM".Length)
            If SyntaxFacts.GetKeywordKind(remText) = SyntaxKind.REMKeyword Then
                Return GetFirstCharacterIndex(message, index + remText.Length)
            End If
 
            Return index
        End Function
 
        Private Shared Function GetFirstCharacterIndex(message As String, Optional start As Integer = 0) As Integer
            Dim index = GetFirstNonWhitespace(message, start)
 
            Dim singleQuote = 0
            For i = index To message.Length - 1 Step 1
                If IsSingleQuote(message(i)) AndAlso singleQuote < 3 Then
                    singleQuote = singleQuote + 1
                Else
                    If singleQuote = 1 OrElse singleQuote = 3 Then
                        Return GetFirstNonWhitespace(message, i)
                    Else
                        Return index
                    End If
                End If
            Next
 
            Return message.Length
        End Function
 
        Private Shared Function GetFirstNonWhitespace(message As String, start As Integer) As Integer
            For i = start To message.Length - 1 Step 1
                If Not SyntaxFacts.IsWhitespace(message(i)) Then
                    Return i
                End If
            Next
 
            Return message.Length
        End Function
 
        Protected Overrides Function IsMultilineComment(trivia As SyntaxTrivia) As Boolean
            ' vb doesn't have multiline comment
            Return False
        End Function
 
        Protected Overrides Function IsSingleLineComment(trivia As SyntaxTrivia) As Boolean
            Return trivia.RawKind = SyntaxKind.CommentTrivia OrElse trivia.RawKind = SyntaxKind.DocumentationCommentTrivia
        End Function
 
        Protected Overrides Function PreprocessorHasComment(trivia As SyntaxTrivia) As Boolean
            Return SyntaxFacts.IsPreprocessorDirective(CType(trivia.RawKind, SyntaxKind)) AndAlso
                           trivia.GetStructure().DescendantTrivia().Any(Function(t) t.RawKind = SyntaxKind.CommentTrivia)
        End Function
 
        ' TODO: remove this if SyntaxFacts.IsSingleQuote become public
        Private Const s_DWCH_SQ As Char = ChrW(&HFF07)      '// DW single quote
        Private Const s_DWCH_LSMART_Q As Char = ChrW(&H2018S)      '// DW left single smart quote
        Private Const s_DWCH_RSMART_Q As Char = ChrW(&H2019S)      '// DW right single smart quote
 
        Private Shared Function IsSingleQuote(c As Char) As Boolean
            ' // Besides the half width and full width ', we also check for Unicode
            ' // LEFT SINGLE QUOTATION MARK and RIGHT SINGLE QUOTATION MARK because
            ' // IME editors paste them in. This isn't really technically correct
            ' // because we ignore the left-ness or right-ness, but see VS 170991
            Return c = "'"c OrElse (c >= s_DWCH_LSMART_Q AndAlso (c = s_DWCH_SQ Or c = s_DWCH_LSMART_Q Or c = s_DWCH_RSMART_Q))
        End Function
    End Class
End Namespace