<commit_before>import _ from 'lodash';
import estraverse from 'estraverse';
import {matchesAst, extract} from '../utils/matches-ast';

export default function(ast) {
  estraverse.replace(ast, {
    enter(node) {
      const {memberExpr, thisParam, arrayParam} = matchApplyCall(node);
      if (memberExpr && _.isEqual(omitLoc(memberExpr.object), omitLoc(thisParam))) {
        return {
          type: 'CallExpression',
          callee: memberExpr,
          arguments: [
            {
              type: 'SpreadElement',
              argument: arrayParam,
            }
          ]
        };
      }
    }
  });
}

// Recursively strips `loc` fields from given object and its nested objects,
// removing the location information that we don't care about when comparing
// AST nodes.
function omitLoc(obj) {
  if (_.isPlainObject(obj)) {
    return _(obj).omit('loc').mapValues(omitLoc).value();
  }
  else if (_.isArray(obj)) {
    return obj.map(omitLoc);
  }
  else {
    return obj;
  }
}

var matchApplyCall = matchesAst({
  type: 'CallExpression',
  callee: {
    type: 'MemberExpression',
    computed: false,
    object: extract('memberExpr', {
      type: 'MemberExpression',
    }),
    property: {
      type: 'Identifier',
      name: 'apply'
    }
  },
  arguments: [
    extract('thisParam'),
    extract('arrayParam')
  ]
});<commit_msg>Fix failure of arg-spread with LoDash 4.7.0<commit_after>import _ from 'lodash';
import estraverse from 'estraverse';
import {matchesAst, extract} from '../utils/matches-ast';

export default function(ast) {
  estraverse.replace(ast, {
    enter(node) {
      const {memberExpr, thisParam, arrayParam} = matchApplyCall(node);
      if (memberExpr && _.isEqual(omitLoc(memberExpr.object), omitLoc(thisParam))) {
        return {
          type: 'CallExpression',
          callee: memberExpr,
          arguments: [
            {
              type: 'SpreadElement',
              argument: arrayParam,
            }
          ]
        };
      }
    }
  });
}

// Recursively strips `loc` fields from given object and its nested objects,
// removing the location information that we don't care about when comparing
// AST nodes.
function omitLoc(obj) {
  if (_.isArray(obj)) {
    return obj.map(omitLoc);
  }
  else if (_.isObjectLike(obj)) {
    return _(obj).omit('loc').mapValues(omitLoc).value();
  }
  else {
    return obj;
  }
}

var matchApplyCall = matchesAst({
  type: 'CallExpression',
  callee: {
    type: 'MemberExpression',
    computed: false,
    object: extract('memberExpr', {
      type: 'MemberExpression',
    }),
    property: {
      type: 'Identifier',
      name: 'apply'
    }
  },
  arguments: [
    extract('thisParam'),
    extract('arrayParam')
  ]
});
{'fraction_non_alphanumeric': 0.13462240058372857, 'fraction_numerical': 0.0010944910616563297, 'mean_word_length': 2.5703125, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3367861', 'n_tokens_mistral': 848, 'n_tokens_neox': 827, 'n_words': 198}