in DataExtraction/SourceGraphExtractionUtils/Utils/VariableUseGraph.cs [12:84]
public static void AddDataFlowEdges(SourceGraph sourceGraph, SyntaxNodeOrToken tokenOfInterest, ICollection<SyntaxNodeOrToken> forbiddenNodes = null, ICollection<Edge<SyntaxNodeOrToken, SourceGraphEdge>> addedEdges = null)
{
//There's nothing before the declaration, so we don't need to bother:
if (sourceGraph.DeclarationNodes.Contains(tokenOfInterest))
{
return;
}
//We only ever need to visit each node once, so collect visited nodes here:
var visitedNodes = new HashSet<(SyntaxNodeOrToken, bool)>();
//Start from all predecessors of the token of interest:
var toVisit = new Stack<(SyntaxNodeOrToken node, bool haveFoundUse)>();
foreach (var (_, label, target) in sourceGraph.GetOutEdges(tokenOfInterest))
{
if (label != SourceGraphEdge.LastUsedVariable || (forbiddenNodes?.Contains(target) ?? false))
{
continue;
}
if (visitedNodes.Add((target, false)))
{
toVisit.Push((target, false));
}
}
string nodeLabelToLookFor = tokenOfInterest.ToString();
while (toVisit.Count > 0)
{
var (node, haveFoundUse) = toVisit.Pop();
if (node.ToString().Equals(nodeLabelToLookFor))
{
if (!haveFoundUse)
{
var lastUseEdge = new Edge<SyntaxNodeOrToken, SourceGraphEdge>(tokenOfInterest, SourceGraphEdge.LastUse, node);
if (sourceGraph.AddEdge(lastUseEdge))
{
addedEdges?.Add(lastUseEdge);
}
haveFoundUse = true;
}
if (sourceGraph.WrittenVariableNodes.Contains(node))
{
var lastWriteEdge = new Edge<SyntaxNodeOrToken, SourceGraphEdge>(tokenOfInterest, SourceGraphEdge.LastWrite, node);
if (sourceGraph.AddEdge(lastWriteEdge))
{
addedEdges?.Add(lastWriteEdge);
}
//We are done with this path -- we found a use and a write!
continue;
}
//There's nothing before the declaration, so we don't need to bother to recurse further:
if (sourceGraph.DeclarationNodes.Contains(node))
{
continue;
}
}
foreach (var (_, label, target) in sourceGraph.GetOutEdges(node))
{
if (label != SourceGraphEdge.LastUsedVariable || (forbiddenNodes?.Contains(target) ?? false))
{
continue;
}
if (visitedNodes.Add((target, haveFoundUse)))
{
toVisit.Push((target, haveFoundUse));
}
}
}
}