public static void AddDataFlowEdges()

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));
                    }
                }
            }
        }