/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/VisualBasicDataFlowAnalysis.vb
303 строки
13 KB
Tomáš Matoušek
EnC: Implements support for #line mappings (#53735)
04 июн 2021, 07:43
Не верифицирован
04 июн 2021, 07:43
4458d00
Код
Авторство
О чём код?
' 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.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis.PooledObjects Namespace Microsoft.CodeAnalysis.VisualBasic ''' <summary> ''' This class implements the region data flow analysis operations. Region data flow analysis provides information ''' how data flows into and out of a region. The analysis is 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 VisualBasicDataFlowAnalysis Inherits DataFlowAnalysis Private ReadOnly _context As RegionAnalysisContext Private _variablesDeclared As ImmutableArray(Of ISymbol) Private _unassignedVariables As HashSet(Of Symbol) Private _dataFlowsIn As ImmutableArray(Of ISymbol) Private _definitelyAssignedOnEntry As ImmutableArray(Of ISymbol) Private _definitelyAssignedOnExit As ImmutableArray(Of ISymbol) Private _dataFlowsOut As ImmutableArray(Of ISymbol) Private _alwaysAssigned As ImmutableArray(Of ISymbol) Private _readInside As ImmutableArray(Of ISymbol) Private _writtenInside As ImmutableArray(Of ISymbol) Private _readOutside As ImmutableArray(Of ISymbol) Private _writtenOutside As ImmutableArray(Of ISymbol) Private _captured As ImmutableArray(Of ISymbol) Private _capturedInside As ImmutableArray(Of ISymbol) Private _capturedOutside As ImmutableArray(Of ISymbol) Private _succeeded As Boolean? Private _invalidRegionDetected As Boolean Friend Sub New(_context As RegionAnalysisContext) Me._context = _context End Sub ''' <summary> ''' A collection of the local variables that are declared within the region. Note that the region must be ''' bounded by a method's body or a field's initializer, so parameter symbols are never included in the result. ''' </summary> Public Overrides ReadOnly Property VariablesDeclared As ImmutableArray(Of ISymbol) Get If _variablesDeclared.IsDefault Then Dim result = If(Me._context.Failed, ImmutableArray(Of ISymbol).Empty, Normalize(VariablesDeclaredWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo))) ImmutableInterlocked.InterlockedCompareExchange(_variablesDeclared, result, Nothing) End If Return _variablesDeclared End Get End Property Private ReadOnly Property UnassignedVariables As HashSet(Of Symbol) Get If _unassignedVariables Is Nothing Then Dim result = If(Me._context.Failed, New HashSet(Of Symbol)(), UnassignedVariablesWalker.Analyze(_context.AnalysisInfo)) Interlocked.CompareExchange(_unassignedVariables, result, Nothing) End If Return _unassignedVariables End Get End Property ''' <summary> ''' A collection of the local variables for which a value assigned outside the region may be used inside the region. ''' </summary> Public Overrides ReadOnly Property DataFlowsIn As ImmutableArray(Of ISymbol) Get If _dataFlowsIn.IsDefault Then Me._succeeded = Not Me._context.Failed Dim result = If(Me._context.Failed, ImmutableArray(Of ISymbol).Empty, Normalize(DataFlowsInWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo, UnassignedVariables, _succeeded, _invalidRegionDetected))) ImmutableInterlocked.InterlockedCompareExchange(_dataFlowsIn, result, Nothing) End If Return _dataFlowsIn End Get End Property Public Overrides ReadOnly Property DefinitelyAssignedOnEntry As ImmutableArray(Of ISymbol) Get Return ComputeDefinitelyAssignedValues().onEntry End Get End Property Public Overrides ReadOnly Property DefinitelyAssignedOnExit As ImmutableArray(Of ISymbol) Get Return ComputeDefinitelyAssignedValues().onExit End Get End Property Private Function ComputeDefinitelyAssignedValues() As (onEntry As ImmutableArray(Of ISymbol), onExit As ImmutableArray(Of ISymbol)) ' Check for _definitelyAssignedOnExit as that's the last thing we write to. If it's not ' Default, then we'll have written to both variables and can safely read from either of ' them. If _definitelyAssignedOnExit.IsDefault Then Dim entry = ImmutableArray(Of ISymbol).Empty Dim ex = ImmutableArray(Of ISymbol).Empty Dim discarded = DataFlowsIn If Not Me._context.Failed Then Dim tuple = DefinitelyAssignedWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo) entry = Normalize(tuple.entry) ex = Normalize(tuple.ex) End If ImmutableInterlocked.InterlockedInitialize(_definitelyAssignedOnEntry, entry) ImmutableInterlocked.InterlockedInitialize(_definitelyAssignedOnExit, ex) End If Return (_definitelyAssignedOnEntry, _definitelyAssignedOnExit) End Function ''' <summary> ''' A collection of the local variables for which a value assigned inside the region may be used outside the region. ''' </summary> Public Overrides ReadOnly Property DataFlowsOut As ImmutableArray(Of ISymbol) Get Dim discarded = DataFlowsIn If _dataFlowsOut.IsDefault Then Dim result = If(Me._context.Failed, ImmutableArray(Of ISymbol).Empty, Normalize(DataFlowsOutWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo, UnassignedVariables, _dataFlowsIn))) ImmutableInterlocked.InterlockedCompareExchange(_dataFlowsOut, result, Nothing) End If Return _dataFlowsOut End Get End Property ''' <summary> ''' A collection of the local variables for which a value is always assigned inside the region. ''' </summary> Public Overrides ReadOnly Property AlwaysAssigned As ImmutableArray(Of ISymbol) Get If _alwaysAssigned.IsDefault Then Dim result = If(Me._context.Failed, ImmutableArray(Of ISymbol).Empty, Normalize(AlwaysAssignedWalker.Analyze(_context.AnalysisInfo, _context.RegionInfo))) ImmutableInterlocked.InterlockedCompareExchange(_alwaysAssigned, result, Nothing) End If Return _alwaysAssigned End Get End Property ''' <summary> ''' A collection of the local variables that are read inside the region. ''' </summary> Public Overrides ReadOnly Property ReadInside As ImmutableArray(Of ISymbol) Get If _readInside.IsDefault Then AnalyzeReadWrite() End If Return _readInside End Get End Property ''' <summary> ''' A collection of local variables that are written inside the region. ''' </summary> Public Overrides ReadOnly Property WrittenInside As ImmutableArray(Of ISymbol) Get If _writtenInside.IsDefault Then AnalyzeReadWrite() End If Return _writtenInside End Get End Property ''' <summary> ''' A collection of the local variables that are read outside the region. ''' </summary> Public Overrides ReadOnly Property ReadOutside As ImmutableArray(Of ISymbol) Get If _readOutside.IsDefault Then AnalyzeReadWrite() End If Return _readOutside End Get End Property ''' <summary> ''' A collection of local variables that are written inside the region. ''' </summary> Public Overrides ReadOnly Property WrittenOutside As ImmutableArray(Of ISymbol) Get If _writtenOutside.IsDefault Then AnalyzeReadWrite() End If Return _writtenOutside End Get End Property Private Sub AnalyzeReadWrite() Dim readInside As IEnumerable(Of Symbol) = Nothing Dim writtenInside As IEnumerable(Of Symbol) = Nothing Dim readOutside As IEnumerable(Of Symbol) = Nothing Dim writtenOutside As IEnumerable(Of Symbol) = Nothing Dim captured As IEnumerable(Of Symbol) = Nothing Dim capturedInside As IEnumerable(Of Symbol) = Nothing Dim capturedOutside As IEnumerable(Of Symbol) = Nothing If Not Me.Succeeded Then readInside = Enumerable.Empty(Of Symbol)() writtenInside = readInside readOutside = readInside writtenOutside = readInside captured = readInside capturedInside = readInside capturedOutside = readInside Else ReadWriteWalker.Analyze( _context.AnalysisInfo, _context.RegionInfo, readInside:=readInside, writtenInside:=writtenInside, readOutside:=readOutside, writtenOutside:=writtenOutside, captured:=captured, capturedInside:=capturedInside, capturedOutside:=capturedOutside) End If ImmutableInterlocked.InterlockedCompareExchange(Me._readInside, Normalize(readInside), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._writtenInside, Normalize(writtenInside), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._readOutside, Normalize(readOutside), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._writtenOutside, Normalize(writtenOutside), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._captured, Normalize(captured), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._capturedInside, Normalize(capturedInside), Nothing) ImmutableInterlocked.InterlockedCompareExchange(Me._capturedOutside, Normalize(capturedOutside), Nothing) End Sub ''' <summary> ''' A collection of the local variables that have been referenced in anonymous functions ''' and therefore must be moved to a field of a frame class. ''' </summary> Public Overrides ReadOnly Property Captured As ImmutableArray(Of ISymbol) Get If Me._captured.IsDefault Then AnalyzeReadWrite() End If Return Me._captured End Get End Property Public Overrides ReadOnly Property CapturedInside As ImmutableArray(Of ISymbol) Get If Me._capturedInside.IsDefault Then AnalyzeReadWrite() End If Return Me._capturedInside End Get End Property Public Overrides ReadOnly Property CapturedOutside As ImmutableArray(Of ISymbol) Get If Me._capturedOutside.IsDefault Then AnalyzeReadWrite() End If Return Me._capturedOutside End Get End Property Friend ReadOnly Property InvalidRegionDetectedInternal As Boolean Get Return If(Me.Succeeded, False, Me._invalidRegionDetected) End Get End Property Public NotOverridable Overrides ReadOnly Property Succeeded As Boolean Get If Me._succeeded Is Nothing Then Dim discarded = DataFlowsIn End If Return Me._succeeded.Value End Get End Property Public Overrides ReadOnly Property UnsafeAddressTaken As ImmutableArray(Of ISymbol) Get Return ImmutableArray(Of ISymbol).Empty End Get End Property Public Overrides ReadOnly Property UsedLocalFunctions As ImmutableArray(Of IMethodSymbol) Get Return ImmutableArray(Of IMethodSymbol).Empty End Get End Property Friend Function Normalize(data As IEnumerable(Of Symbol)) As ImmutableArray(Of ISymbol) Dim builder = ArrayBuilder(Of Symbol).GetInstance() builder.AddRange(data.Where(Function(s) s.CanBeReferencedByName)) builder.Sort(LexicalOrderSymbolComparer.Instance) Return builder.ToImmutableAndFree().As(Of ISymbol)() End Function End Class End Namespace