in DataExtraction/SourceGraphExtractionUtils/GraphDataExtractor.cs [686:755]
private static void CopySubgraphAroundHole(
SourceGraph sourceGraph,
IEnumerable<SyntaxNodeOrToken> targetNodes,
ISet<SyntaxNodeOrToken> forbiddenNodes,
SourceGraph resultGraph,
int numSymbolsAddedSoFar = 0)
{
var allowedNodes = new HashSet<SyntaxNodeOrToken>(sourceGraph.Nodes.Where(n => !forbiddenNodes.Contains(n)));
/// <summary>
/// Filter edges that are "active" in the output graph.
///
/// The current implementation allows all edges except from the GuardedBy[Negation].
/// GuardedBy[Negation] edges are inlcuded only if the label of the source node
/// is in the set of identifiers of the descendants of the target node.
/// </summary>
bool IsActiveEdge(Edge<SyntaxNodeOrToken, SourceGraphEdge> edge)
{
if (edge.Label != SourceGraphEdge.GuardedBy && edge.Label != SourceGraphEdge.GuardedByNegation)
{
return true;
}
var sourceNodeLabel = edge.Source.ToString();
if (edge.Target.IsToken)
{
return edge.Target.ToString().Equals(sourceNodeLabel);
}
// If our target token (the only element of forbidden nodes at this point) is a descendant of the target,
// we are considering a slot inside a condition. In that case, keep all GuardedBy edges.
if (edge.Target.AsNode().DescendantTokens().Any(token => forbiddenNodes.Contains(token)))
{
return true;
}
return edge.Target.AsNode().DescendantTokens()
.Where(t => allowedNodes.Contains(t))
.Any(t => t.ToString().Equals(sourceNodeLabel));
}
var nodesToSyntaxRemainingBudget = new Dictionary<SyntaxNodeOrToken, int>();
foreach (var targetNode in targetNodes)
{
GetReachableNodes(sourceGraph, OnlySyntaxEdgesCost, MAX_SYNTAX_BUDGET, targetNode, allowedNodes, nodesToSyntaxRemainingBudget, IsActiveEdge);
}
var nodesToDataflowRemainingBudget = new Dictionary<SyntaxNodeOrToken, int>();
foreach (var targetNode in targetNodes)
{
GetReachableNodes(sourceGraph, OnlyDataflowEdgesCost, MAX_DATAFLOW_BUDGET, targetNode, nodesToSyntaxRemainingBudget.Keys, nodesToDataflowRemainingBudget, IsActiveEdge);
// This ensures that all targetNodes appear in the nodesToDataflowRemainingBudget
nodesToDataflowRemainingBudget[targetNode] = MAX_DATAFLOW_BUDGET + MAX_SYNTAX_BUDGET;
}
// Order the nodes by cost so that nodes smaller cost are reached first.
foreach (var node in nodesToDataflowRemainingBudget.Keys.OrderByDescending(n => nodesToDataflowRemainingBudget[n]))
{
foreach (var edge in sourceGraph.GetOutEdges(node))
{
if (edge.Label == SourceGraphEdge.LastUsedVariable) continue;
if (resultGraph.CountNodes > MAX_NUM_NODES_PER_GRAPH + ADDITIONAL_NODES_PER_CANDIDATE_SYMBOL * numSymbolsAddedSoFar &&
!(resultGraph.ContainsNode(node) && resultGraph.ContainsNode(edge.Target))) continue;
if (nodesToDataflowRemainingBudget.ContainsKey(edge.Target) && !forbiddenNodes.Contains(node) && !forbiddenNodes.Contains(edge.Target))
{
resultGraph.AddEdge(node, edge.Label, edge.Target);
}
}
}
}