_expand(nodeArrays) {
    var traversals = nodeArrays.map(nodes => {
      return this._traversals[nodes[0].loc.filename];
    });

    var headPositions = nodeArrays.map((nodes, i) => {
      return traversals[i].indexOf(nodes[0]);
    });

    var tailPositions = nodeArrays.map((nodes, i) => {
      var last = nodes[nodes.length - 1];
      return traversals[i].indexOf(last);
    });

    var incr = (pos) => pos + 1;
    var decr = (pos) => pos - 1;
    var getNode = (pos, i) => traversals[i][pos];
    var alreadyIncluded = (nodes) => {
      return nodes.some(node => {
        return nodeArrays.some(array => array.indexOf(node) !== -1)
      });
    };

    var isComplete = (nodes) => {
      return (!NodeUtils.typesMatch(nodes) || alreadyIncluded(nodes)) ||
        (this._identifiers && !NodeUtils.identifiersMatch(nodes)) ||
        (this._literals && !NodeUtils.literalsMatch(nodes));
    };

    while (true) {
      headPositions = headPositions.map(decr);
      let nodes = headPositions.map(getNode);
      if (isComplete(nodes)) break;
      nodeArrays.forEach((array, i) => array.unshift(nodes[i]));
    }

    while (true) {
      tailPositions = tailPositions.map(incr);
      let nodes = tailPositions.map(getNode);
      if (isComplete(nodes)) break;
      nodeArrays.forEach((array, i) => array.push(nodes[i]));
    }
  }
Expands each instance of a match to the largest common sequence of nodes
with the same type, and optionally identifiers. Each array of nodes is
modified in place.

@private

@param {Node[][]} nodeArrays