collapse method

CallGraph collapse(
  1. NodeType type, {
  2. bool dropCallNodes = false,
})

Compute a collapsed version of the call-graph, where

Implementation

CallGraph collapse(NodeType type, {bool dropCallNodes = false}) {
  final graphNodesByData = <Object, CallGraphNode>{};
  final graphNodeByEntityId = <CallGraphNode?>[];

  ProgramInfoNode collapsed(ProgramInfoNode nn) {
    // Root always collapses onto itself.
    if (nn == program.root) {
      return nn;
    }

    // Even though all code is grouped into libraries, not all libraries
    // are grouped into packages (e.g. dart:* libraries). Meaning
    // that if we are collapsing by package we need to stop right before
    // hitting the root node.
    var n = nn;
    while (n.parent != program.root && n.type != type) {
      n = n.parent!;
    }
    return n;
  }

  CallGraphNode callGraphNodeFor(Object data) {
    return graphNodesByData.putIfAbsent(data, () {
      final n = CallGraphNode(graphNodesByData.length, data: data);
      if (data is ProgramInfoNode) {
        if (graphNodeByEntityId.length <= data.id) {
          graphNodeByEntityId.length = data.id * 2 + 1;
        }
        graphNodeByEntityId[data.id] = n;
      }
      return n;
    });
  }

  final newNodes = nodes.map((n) {
    if (n.data is ProgramInfoNode) {
      return callGraphNodeFor(collapsed(n.data));
    } else if (!dropCallNodes) {
      return callGraphNodeFor(n.data);
    }
  }).toList(growable: false);

  for (var n in nodes) {
    for (var succ in n.succ) {
      final from = newNodes[n.id];
      final to = newNodes[succ.id];

      if (from != null && to != null) {
        from.connectTo(to);
      }
    }
  }

  return CallGraph._(program, graphNodesByData.values.toList(growable: false),
      graphNodeByEntityId);
}