Skip to content

Commit

Permalink
support flow captures in LVA
Browse files Browse the repository at this point in the history
  • Loading branch information
mary-georgiou-sonarsource committed Jun 20, 2024
1 parent 5c57827 commit 22cdbc9
Show file tree
Hide file tree
Showing 3 changed files with 382 additions and 361 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System.Collections.Concurrent;
using System.ComponentModel.Design;
using SonarAnalyzer.CFG.Roslyn;

namespace SonarAnalyzer.CFG.LiveVariableAnalysis;

public sealed class RoslynLiveVariableAnalysis : LiveVariableAnalysisBase<ControlFlowGraph, BasicBlock>
{
private readonly ConcurrentDictionary<CaptureId, ConcurrentBag<IOperation>> flowCaptureOperations = [];
private readonly Dictionary<CaptureId, List<IOperation>> flowCaptureOperations = [];
private readonly Dictionary<int, List<BasicBlock>> blockPredecessors = [];
private readonly Dictionary<int, List<BasicBlock>> blockSuccessors = [];

Expand Down Expand Up @@ -84,18 +84,27 @@ private void LiveCaptureAnalysis(ControlFlowGraph cfg)
if (IFlowCaptureOperationWrapper.IsInstance(operation.Instance))
{
var flowCapture = IFlowCaptureOperationWrapper.FromOperation(operation.Instance);
if (!IFlowCaptureReferenceOperationWrapper.IsInstance(flowCapture.Value))

if (IFlowCaptureReferenceOperationWrapper.IsInstance(flowCapture.Value)
&& IFlowCaptureReferenceOperationWrapper.FromOperation(flowCapture.Value) is var capture
&& flowCaptureOperations.TryGetValue(capture.Id, out var capturedOperations))
{
if (flowCaptureOperations.ContainsKey(flowCapture.Id))
{
flowCaptureOperations[flowCapture.Id].AddRange(capturedOperations);
}
else
{
flowCaptureOperations.Add(flowCapture.Id, capturedOperations);
}
}
else if (flowCaptureOperations.TryGetValue(flowCapture.Id, out capturedOperations))
{
_ = flowCaptureOperations.TryGetValue(flowCapture.Id, out var captureOperations);
var value = captureOperations ?? [];
value.Add(flowCapture.Value);
flowCaptureOperations.TryAdd(flowCapture.Id, value);
flowCaptureOperations[flowCapture.Id] = [.. capturedOperations, flowCapture.Value];
}
else
{
var flowCaptureReference = IFlowCaptureReferenceOperationWrapper.FromOperation(flowCapture.Value);
_ = flowCaptureOperations.TryGetValue(flowCaptureReference.Id, out var captureOperations);
flowCaptureOperations.TryAdd(flowCapture.Id, captureOperations);
flowCaptureOperations.Add(flowCapture.Id, [flowCapture.Value]);
}
}
}
Expand Down Expand Up @@ -204,32 +213,23 @@ private sealed class RoslynState : State
public RoslynState(RoslynLiveVariableAnalysis owner) =>
this.owner = owner;

public void ProcessBlock(ControlFlowGraph cfg, BasicBlock block, ConcurrentDictionary<CaptureId, ConcurrentBag<IOperation>> flowCaptureOperations = null)
public void ProcessBlock(ControlFlowGraph cfg, BasicBlock block, Dictionary<CaptureId, List<IOperation>> flowCaptureOperations = null)
{
if (flowCaptureOperations is null)
{
flowCaptureOperations = new();
}
flowCaptureOperations ??= [];

foreach (var op in block.OperationsAndBranchValue.ToReversedExecutionOrder())
{
var operation = op.Instance;
if (IFlowCaptureOperationWrapper.IsInstance(operation)
&& flowCaptureOperations.TryGetValue(IFlowCaptureOperationWrapper.FromOperation(operation).Id, out var captureOperations))
if ((IFlowCaptureOperationWrapper.IsInstance(operation)
&& flowCaptureOperations.TryGetValue(IFlowCaptureOperationWrapper.FromOperation(operation).Id, out var capturedOps))
|| (IFlowCaptureReferenceOperationWrapper.IsInstance(operation)
&& flowCaptureOperations.TryGetValue(IFlowCaptureReferenceOperationWrapper.FromOperation(operation).Id, out capturedOps)))
{
foreach (var captureOpeation in captureOperations)
foreach (var capturedOperation in capturedOps)
{
ProcessOperation(cfg, captureOpeation);
ProcessOperation(cfg, capturedOperation);
}
}
else if (IFlowCaptureReferenceOperationWrapper.IsInstance(operation)
&& flowCaptureOperations.TryGetValue(IFlowCaptureReferenceOperationWrapper.FromOperation(operation).Id, out captureOperations))
{
foreach (var captureOpeation in captureOperations)
{
ProcessOperation(cfg, captureOpeation);
}

}
else
{
ProcessOperation(cfg, operation);
Expand Down
Loading

0 comments on commit 22cdbc9

Please sign in to comment.