Code coverage report for 6to5/traverse/index.js

Statements: 96.47% (82 / 85)      Branches: 93.18% (41 / 44)      Functions: 91.67% (11 / 12)      Lines: 97.22% (70 / 72)      Ignored: none     

All files » 6to5/traverse/ » index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 1391   1 1 1   1   494889     494888 227 243   227       494661 494661   494660 494660     494660     494660   494660 503396 503396   461525 464092 464092     464053   464050     464050 610601 610601       464050 464050     464050 464050     464036   459857       459857     459849 150744       461525 144435 147002     144427   317090         1 8064 101952 101952 101952 101952 101952 101952 101952 101952 101952   101952 101952     8064 203904     8064 8064   8064     1 7   7   7             7     6   5 42 2 2         5    
module.exports = traverse;
 
var Scope = require("./scope");
var t     = require("../types");
var _     = require("lodash");
 
function traverse(parent, callbacks, opts) {
  // falsy node
  if (!parent) return;
 
  // array of nodes
  if (_.isArray(parent)) {
    _.each(parent, function (node) {
      traverse(node, callbacks, opts);
    });
    return;
  }
 
  // unknown node type to traverse
  var keys = t.VISITOR_KEYS[parent.type];
  if (!keys) return;
 
  opts = opts || {};
  if (_.isArray(opts)) opts = { blacklist: opts };
 
  // blacklist these node types from being traversed
  var blacklistTypes = opts.blacklist || [];
 
  // normalise callbacks
  if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
 
  _.each(keys, function (key) {
    var nodes = parent[key];
    if (!nodes) return;
 
    var handle = function (obj, key) {
      var node = obj[key];
      if (!node) return;
 
      // type is blacklisted
      if (_.contains(blacklistTypes, node.type)) return;
 
      var result;
 
      // replace node
      var maybeReplace = function (result) {
        Iif (result === false) return;
        if (result != null) node = obj[key] = result;
      };
 
      //
      var opts2 = _.clone(opts);
      if (t.isScope(node)) opts2.scope = new Scope(opts.scope, node);
 
      // enter
      Eif (callbacks.enter) {
        result = callbacks.enter(node, parent, opts2);
 
        // stop iteration
        if (result === false) return;
 
        maybeReplace(result);
      }
 
      // traverse node
      traverse(node, callbacks, opts2);
 
      // exit
      if (callbacks.exit) {
        maybeReplace(callbacks.exit(node, parent, opts2));
      }
    };
 
    if (_.isArray(nodes)) {
      _.each(nodes, function (node, i) {
        handle(nodes, i);
      });
 
      parent[key] = _.flatten(parent[key]);
    } else {
      handle(parent, key);
    }
  });
}
 
traverse.removeProperties = function (tree) {
  var clear = function (node) {
    delete node.extendedRange;
    delete node._scopeIds;
    delete node._parent;
    delete node.tokens;
    delete node.range;
    delete node.start;
    delete node.end;
    delete node.loc;
    delete node.raw;
 
    clearComments(node.trailingComments);
    clearComments(node.leadingComments);
  };
 
  var clearComments = function (comments) {
    _.each(comments, clear);
  };
 
  clear(tree);
  traverse(tree, clear);
 
  return tree;
};
 
traverse.hasType = function (tree, type, blacklistTypes) {
  blacklistTypes = [].concat(blacklistTypes || []);
 
  var has = false;
 
  Iif (_.isArray(tree)) {
    // array of nodes, find the first
    return tree.some(function (node) {
      return traverse.hasType(node, type, blacklistTypes);
    });
  } else {
    // the node we're searching in is blacklisted
    if (_.contains(blacklistTypes, tree.type)) return false;
 
    // the type we're looking for is the same as the passed node
    if (tree.type === type) return true;
 
    traverse(tree, function (node) {
      if (node.type === type) {
        has = true;
        return false;
      }
    }, { blacklist: blacklistTypes });
  }
 
  return has;
};