File: src\Workspaces\SharedUtilitiesAndExtensions\Workspace\VisualBasic\Extensions\TypeBlockSyntaxExtensions.vb
Web Access
Project: src\src\Workspaces\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj (Microsoft.CodeAnalysis.VisualBasic.Workspaces)
' 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.Runtime.CompilerServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
    Friend Module TypeBlockSyntaxExtensions
        <Extension>
        Public Function GetInsertionIndices(destination As TypeBlockSyntax,
                                            cancellationToken As CancellationToken) As IList(Of Boolean)
            Dim members = destination.Members
 
            Dim indices = New List(Of Boolean)
            If members.Count = 0 Then
                Dim start = destination.BlockStatement.Span.End
                Dim [end] = destination.EndBlockStatement.SpanStart
 
                indices.Add(Not destination.OverlapsHiddenPosition(destination.BlockStatement, destination.EndBlockStatement, cancellationToken))
            Else
                ' First, see if we can insert between the start of the typeblock, and it's first
                ' member.
                indices.Add(Not destination.OverlapsHiddenPosition(destination.BlockStatement, destination.Members.First, cancellationToken))
 
                ' Now, walk between each member and see if something can be inserted between it and
                ' the next member
                For i = 0 To members.Count - 2
                    Dim member1 = members(i)
                    Dim member2 = members(i + 1)
 
                    indices.Add(Not destination.OverlapsHiddenPosition(member1, member2, cancellationToken))
                Next
 
                ' Last, see if we can insert between the last member and the end of the typeblock
                indices.Add(Not destination.OverlapsHiddenPosition(destination.Members.Last, destination.EndBlockStatement, cancellationToken))
            End If
 
            Return indices
        End Function
 
        Private Function ReplaceTrailingColonToEndOfLineTrivia(Of TNode As SyntaxNode)(node As TNode) As TNode
            Return node.WithTrailingTrivia(node.GetTrailingTrivia().Select(Function(t) If(t.Kind = SyntaxKind.ColonTrivia, SyntaxFactory.ElasticCarriageReturnLineFeed, t)))
        End Function
 
        Private Function EnsureProperList(Of TSyntax As SyntaxNode)(list As SyntaxList(Of TSyntax)) As SyntaxList(Of TSyntax)
            Dim allElements = list
            If Not allElements.Last().GetTrailingTrivia().Any(Function(t) t.Kind = SyntaxKind.EndOfLineTrivia OrElse t.Kind = SyntaxKind.ColonTrivia) Then
                Return SyntaxFactory.SingletonList(Of TSyntax)(
                    allElements.Last().WithAppendedTrailingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed))
            ElseIf allElements.Last().GetTrailingTrivia().Any(Function(t) t.Kind = SyntaxKind.ColonTrivia) Then
                Return SyntaxFactory.List(Of TSyntax)(
                    allElements.Take(allElements.Count - 1).Concat(ReplaceTrailingColonToEndOfLineTrivia(allElements.Last())))
            End If
 
            Return list
        End Function
 
        Private Function EnsureProperInherits(destinationType As TypeBlockSyntax) As SyntaxList(Of InheritsStatementSyntax)
            Dim allElements = destinationType.Inherits
            If allElements.Count > 0 AndAlso
               destinationType.Implements.Count = 0 Then
                Return EnsureProperList(destinationType.Inherits)
            End If
 
            Return destinationType.Inherits
        End Function
 
        Private Function EnsureProperImplements(destinationType As TypeBlockSyntax) As SyntaxList(Of ImplementsStatementSyntax)
            Dim allElements = destinationType.Implements
            If allElements.Count > 0 Then
                Return EnsureProperList(destinationType.Implements)
            End If
 
            Return destinationType.Implements
        End Function
 
        Private Function EnsureProperBegin(destinationType As TypeBlockSyntax) As TypeStatementSyntax
            If destinationType.Inherits.Count = 0 AndAlso
               destinationType.Implements.Count = 0 AndAlso
               destinationType.BlockStatement.GetTrailingTrivia().Any(Function(t) t.Kind = SyntaxKind.ColonTrivia) Then
                Return ReplaceTrailingColonToEndOfLineTrivia(destinationType.BlockStatement)
            End If
 
            Return destinationType.BlockStatement
        End Function
 
        Private Function EnsureEndTokens(destinationType As TypeBlockSyntax) As EndBlockStatementSyntax
            If destinationType.EndBlockStatement.IsMissing Then
                Select Case destinationType.Kind
                    Case SyntaxKind.ClassBlock
                        Return SyntaxFactory.EndClassStatement().WithAdditionalAnnotations(Formatter.Annotation)
                    Case SyntaxKind.InterfaceBlock
                        Return SyntaxFactory.EndInterfaceStatement().WithAdditionalAnnotations(Formatter.Annotation)
                    Case SyntaxKind.StructureBlock
                        Return SyntaxFactory.EndStructureStatement().WithAdditionalAnnotations(Formatter.Annotation)
                End Select
            End If
 
            Return destinationType.EndBlockStatement
        End Function
 
        <Extension>
        Public Function FixTerminators(destinationType As TypeBlockSyntax) As TypeBlockSyntax
            Return destinationType.WithInherits(EnsureProperInherits(destinationType)).
                                   WithImplements(EnsureProperImplements(destinationType)).
                                   WithBlockStatement(EnsureProperBegin(destinationType)).
                                   WithEndBlockStatement(EnsureEndTokens(destinationType))
        End Function
    End Module
End Namespace