File: Analysis\FlowAnalysis\ControlFlowAnalysis.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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
Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    ''' <summary>
    ''' This class implements the region control flow analysis operations.  Region control flow analysis provides
    ''' information about statements which enter and leave a region. The analysis done lazily. When created, it performs
    ''' no analysis, but simply caches the arguments. Then, the first time one of the analysis results is used it
    ''' computes that one result and caches it. Each result is computed using a custom algorithm.
    ''' </summary>
    Friend Class VisualBasicControlFlowAnalysis
        Inherits ControlFlowAnalysis
 
        Private ReadOnly _context As RegionAnalysisContext
 
        Private _entryPoints As ImmutableArray(Of SyntaxNode)
        Private _exitPoints As ImmutableArray(Of SyntaxNode)
        Private _regionStartPointIsReachable As Object
        Private _regionEndPointIsReachable As Object
        Private _succeeded As Boolean?
 
        Friend Sub New(_context As RegionAnalysisContext)
            Me._context = _context
        End Sub
 
        ''' <summary>
        ''' A collection of statements outside the region that jump into the region.
        ''' </summary>
        Public Overrides ReadOnly Property EntryPoints As ImmutableArray(Of SyntaxNode)
            Get
                If _entryPoints.IsDefault Then
                    Me._succeeded = Not Me._context.Failed
                    Dim result = If(Me._context.Failed, ImmutableArray(Of SyntaxNode).Empty,
                                    DirectCast(EntryPointsWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo, _succeeded), IEnumerable(Of SyntaxNode)).ToImmutableArray())
                    ImmutableInterlocked.InterlockedCompareExchange(_entryPoints, result, Nothing)
                End If
                Return _entryPoints
            End Get
        End Property
 
        ''' <summary>
        ''' A collection of statements inside the region that jump to locations outside the region.
        ''' </summary>
        Public Overrides ReadOnly Property ExitPoints As ImmutableArray(Of SyntaxNode)
            Get
                If _exitPoints.IsDefault Then
                    Dim result = If(Me._context.Failed, ImmutableArray(Of SyntaxNode).Empty,
                                    DirectCast(ExitPointsWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo), IEnumerable(Of SyntaxNode)).ToImmutableArray())
                    ImmutableInterlocked.InterlockedCompareExchange(_exitPoints, result, Nothing)
                End If
                Return _exitPoints
            End Get
        End Property
 
        ''' <summary>
        ''' Returns true if and only if the last statement in the region can complete normally or the region contains no
        ''' statements.
        ''' </summary>
        Public NotOverridable Overrides ReadOnly Property EndPointIsReachable As Boolean
            Get
                If _regionStartPointIsReachable Is Nothing Then
                    ComputeReachability()
                End If
                Return DirectCast(_regionEndPointIsReachable, Boolean)
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property StartPointIsReachable As Boolean
            Get
                If _regionStartPointIsReachable Is Nothing Then
                    ComputeReachability()
                End If
                Return DirectCast(_regionStartPointIsReachable, Boolean)
            End Get
        End Property
 
        Private Sub ComputeReachability()
            Dim startPointIsReachable As Boolean = False
            Dim endPointIsReachable As Boolean = False
 
            If Me._context.Failed Then
                startPointIsReachable = True
                endPointIsReachable = True
            Else
                RegionReachableWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo, startPointIsReachable, endPointIsReachable)
            End If
 
            Interlocked.CompareExchange(_regionStartPointIsReachable, startPointIsReachable, Nothing)
            Interlocked.CompareExchange(_regionEndPointIsReachable, endPointIsReachable, Nothing)
        End Sub
 
        ''' <summary>
        ''' A collection of return, exit sub, exit function, exit operator and exit property statements found within the region that return to the enclosing method.
        ''' </summary>
        Public Overrides ReadOnly Property ReturnStatements As ImmutableArray(Of SyntaxNode)
            Get
                Return ExitPoints.WhereAsArray(Function(s As SyntaxNode) As Boolean
                                                   Return s.IsKind(SyntaxKind.ReturnStatement) Or
                                                s.IsKind(SyntaxKind.ExitSubStatement) Or
                                                s.IsKind(SyntaxKind.ExitFunctionStatement) Or
                                                s.IsKind(SyntaxKind.ExitOperatorStatement) Or
                                                s.IsKind(SyntaxKind.ExitPropertyStatement)
                                               End Function)
            End Get
        End Property
 
        Public NotOverridable Overrides ReadOnly Property Succeeded As Boolean
            Get
                If Me._succeeded Is Nothing Then
                    Dim discarded = EntryPoints
                End If
 
                Return Me._succeeded.Value
            End Get
        End Property
 
    End Class
 
End Namespace