File: Completion\KeywordRecommenders\PreprocessorDirectives\PreprocessorHelpers.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.Runtime.CompilerServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.PreprocessorDirectives
    Friend Module PreprocessorHelpers
        <Extension()>
        Public Function GetInnermostIfPreprocessorKind(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As SyntaxKind?
            Dim kindStack = New IfDirectiveVisitor(syntaxTree, position, cancellationToken).GetStack()
 
            If kindStack.Count = 0 Then
                Return Nothing
            Else
                Return kindStack.Peek()
            End If
        End Function
 
        Private Class IfDirectiveVisitor
            Inherits VisualBasicSyntaxVisitor
 
            Private ReadOnly _kindStack As New Stack(Of SyntaxKind)
            Private ReadOnly _maxPosition As Integer
 
            Public Sub New(syntaxTree As SyntaxTree, maxPosition As Integer, cancellationToken As CancellationToken)
                _maxPosition = maxPosition
                Visit(syntaxTree.GetRoot(cancellationToken))
            End Sub
 
            Public Overrides Sub DefaultVisit(node As SyntaxNode)
                If Not node.ContainsDirectives Then
                    Return
                End If
 
                For Each leadingTrivia In node.GetLeadingTrivia()
                    If leadingTrivia.HasStructure Then
                        Visit(leadingTrivia.GetStructure())
                    End If
                Next
 
                For Each child In node.ChildNodesAndTokens()
                    If child.FullSpan.Start > _maxPosition Then
                        Exit For
                    End If
 
                    If child.IsNode Then
                        Visit(child.AsNode())
                    End If
                Next
 
                For Each followingTrivia In node.GetTrailingTrivia()
                    If followingTrivia.HasStructure Then
                        Visit(followingTrivia.GetStructure())
                    End If
                Next
            End Sub
 
            Public Overrides Sub VisitIfDirectiveTrivia(node As IfDirectiveTriviaSyntax)
                If node.Kind = SyntaxKind.IfDirectiveTrivia Then
                    _kindStack.Push(node.Kind)
                ElseIf node.Kind = SyntaxKind.ElseIfDirectiveTrivia Then
                    ' If we're closing our previous context, then pop that one
                    If _kindStack.Count > 0 Then
                        _kindStack.Pop()
                    End If
 
                    _kindStack.Push(node.Kind)
                End If
            End Sub
 
            Public Overrides Sub VisitElseDirectiveTrivia(node As ElseDirectiveTriviaSyntax)
                If _kindStack.Count > 0 Then
                    _kindStack.Pop()
                End If
 
                _kindStack.Push(node.Kind)
 
            End Sub
 
            Public Overrides Sub VisitEndIfDirectiveTrivia(node As EndIfDirectiveTriviaSyntax)
                If _kindStack.Count > 0 Then
                    _kindStack.Pop()
                End If
            End Sub
 
            Public Function GetStack() As Stack(Of SyntaxKind)
                Return _kindStack
            End Function
        End Class
    End Module
End Namespace