File: Analysis\FlowAnalysis\UnassignedVariablesWalker.vb
Web Access
Project: src\src\roslyn\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.Collections.Generic
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic

    ''' <summary>
    ''' An analysis that computes the set of variables that may be used
    ''' before being assigned anywhere within a method.
    ''' </summary>
    ''' <remarks></remarks>
    Friend NotInheritable Class UnassignedVariablesWalker
        Inherits DataFlowPass

        ' TODO: normalize the result by removing variables that are unassigned in an unmodified flow analysis.
        Private Sub New(info As FlowAnalysisInfo)
            MyBase.New(info, suppressConstExpressionsSupport:=False, trackStructsWithIntrinsicTypedFields:=True)
        End Sub

        Friend Overloads Shared Function Analyze(info As FlowAnalysisInfo) As HashSet(Of Symbol)
            Dim walker = New UnassignedVariablesWalker(info)
            Try
                Return If(walker.Analyze(), walker._result, New HashSet(Of Symbol)())
            Finally
                walker.Free()
            End Try
        End Function

        Private ReadOnly _result As HashSet(Of Symbol) = New HashSet(Of Symbol)()

        Protected Overrides Sub ReportUnassigned(local As Symbol,
                                                 node As SyntaxNode,
                                                 rwContext As ReadWriteContext,
                                                 Optional slot As Integer = SlotKind.NotTracked,
                                                 Optional boundFieldAccess As BoundFieldAccess = Nothing)

            Debug.Assert(local.Kind <> SymbolKind.Field OrElse boundFieldAccess IsNot Nothing)

            If local.Kind = SymbolKind.Field Then
                Dim sym As Symbol = GetNodeSymbol(boundFieldAccess)

                ' Ambiguous implicit receiver with should not even considered to be unassigned
                Debug.Assert(Not TypeOf sym Is AmbiguousLocalsPseudoSymbol)

                If sym IsNot Nothing Then
                    _result.Add(sym)
                End If

            Else
                _result.Add(local)
            End If

            MyBase.ReportUnassigned(local, node, rwContext, slot, boundFieldAccess)
        End Sub

        Protected Overrides ReadOnly Property SuppressRedimOperandRvalueOnPreserve As Boolean
            Get
                Return False
            End Get
        End Property

        Friend Overrides Sub AssignLocalOnDeclaration(local As LocalSymbol, node As BoundLocalDeclaration)
            ' NOTE: static locals should not be considered assigned even in presence of initializer
            If Not local.IsStatic Then
                MyBase.AssignLocalOnDeclaration(local, node)
            End If
        End Sub

        Protected Overrides ReadOnly Property IgnoreOutSemantics As Boolean
            Get
                Return False
            End Get
        End Property

        Protected Overrides ReadOnly Property EnableBreakingFlowAnalysisFeatures As Boolean
            Get
                Return True
            End Get
        End Property

    End Class

End Namespace