File: Analysis\FlowAnalysis\UnassignedVariablesWalker.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.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