"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _crypto = require("crypto");

var _template = _interopRequireDefault(require("@babel/template"));

var _sourceCoverage = require("./source-coverage");

var _constants = require("./constants");

var _instrumenter = require("./instrumenter");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// pattern for istanbul to ignore a section
const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/; // pattern for istanbul to ignore the whole file

const COMMENT_FILE_RE = /^\s*istanbul\s+ignore\s+(file)(?=\W|$)/; // source map URL pattern

const SOURCE_MAP_RE = /[#@]\s*sourceMappingURL=(.*)\s*$/m; // generate a variable name from hashing the supplied file path

function genVar(filename) {
  const hash = (0, _crypto.createHash)(_constants.SHA);
  hash.update(filename);
  return 'cov_' + parseInt(hash.digest('hex').substr(0, 12), 16).toString(36);
} // VisitState holds the state of the visitor, provides helper functions
// and is the `this` for the individual coverage visitors.


class VisitState {
  constructor(types, sourceFilePath, inputSourceMap, ignoreClassMethods = []) {
    this.varName = genVar(sourceFilePath);
    this.attrs = {};
    this.nextIgnore = null;
    this.cov = new _sourceCoverage.SourceCoverage(sourceFilePath);

    if (typeof inputSourceMap !== 'undefined') {
      this.cov.inputSourceMap(inputSourceMap);
    }

    this.ignoreClassMethods = ignoreClassMethods;
    this.types = types;
    this.sourceMappingURL = null;
  } // should we ignore the node? Yes, if specifically ignoring
  // or if the node is generated.


  shouldIgnore(path) {
    return this.nextIgnore || !path.node.loc;
  } // extract the ignore comment hint (next|if|else) or null


  hintFor(node) {
    let hint = null;

    if (node.leadingComments) {
      node.leadingComments.forEach(c => {
        const v = (c.value ||
        /* istanbul ignore next: paranoid check */
        '').trim();
        const groups = v.match(COMMENT_RE);

        if (groups) {
          hint = groups[1];
        }
      });
    }

    return hint;
  } // extract a source map URL from comments and keep track of it


  maybeAssignSourceMapURL(node) {
    const extractURL = comments => {
      if (!comments) {
        return;
      }

      comments.forEach(c => {
        const v = (c.value ||
        /* istanbul ignore next: paranoid check */
        '').trim();
        const groups = v.match(SOURCE_MAP_RE);

        if (groups) {
          this.sourceMappingURL = groups[1];
        }
      });
    };

    extractURL(node.leadingComments);
    extractURL(node.trailingComments);
  } // for these expressions the statement counter needs to be hoisted, so
  // function name inference can be preserved


  counterNeedsHoisting(path) {
    return path.isFunctionExpression() || path.isArrowFunctionExpression() || path.isClassExpression();
  } // all the generic stuff that needs to be done on enter for every node


  onEnter(path) {
    const n = path.node;
    this.maybeAssignSourceMapURL(n); // if already ignoring, nothing more to do

    if (this.nextIgnore !== null) {
      return;
    } // check hint to see if ignore should be turned on


    const hint = this.hintFor(n);

    if (hint === 'next') {
      this.nextIgnore = n;
      return;
    } // else check custom node attribute set by a prior visitor


    if (this.getAttr(path.node, 'skip-all') !== null) {
      this.nextIgnore = n;
    } // else check for ignored class methods


    if (path.isFunctionExpression() && this.ignoreClassMethods.some(name => path.node.id && name === path.node.id.name)) {
      this.nextIgnore = n;
      return;
    }

    if (path.isClassMethod() && this.ignoreClassMethods.some(name => name === path.node.key.name)) {
      this.nextIgnore = n;
      return;
    }
  } // all the generic stuff on exit of a node,
  // including reseting ignores and custom node attrs


  onExit(path) {
    // restore ignore status, if needed
    if (path.node === this.nextIgnore) {
      this.nextIgnore = null;
    } // nuke all attributes for the node


    delete path.node.__cov__;
  } // set a node attribute for the supplied node


  setAttr(node, name, value) {
    node.__cov__ = node.__cov__ || {};
    node.__cov__[name] = value;
  } // retrieve a node attribute for the supplied node or null


  getAttr(node, name) {
    const c = node.__cov__;

    if (!c) {
      return null;
    }

    return c[name];
  } //


  increase(type, id, index) {
    const T = this.types;
    const wrap = index !== null ? // If `index` present, turn `x` into `x[index]`.
    x => T.memberExpression(x, T.numericLiteral(index), true) : x => x;
    return T.updateExpression('++', wrap(T.memberExpression(T.memberExpression(T.identifier(this.varName), T.identifier(type)), T.numericLiteral(id), true)));
  }

  insertCounter(path, increment) {
    const T = this.types;

    if (path.isBlockStatement()) {
      path.node.body.unshift(T.expressionStatement(increment));
    } else if (path.isStatement()) {
      path.insertBefore(T.expressionStatement(increment));
    } else if (this.counterNeedsHoisting(path) && T.isVariableDeclarator(path.parentPath)) {
      // make an attempt to hoist the statement counter, so that
      // function names are maintained.
      const parent = path.parentPath.parentPath;

      if (parent && T.isExportNamedDeclaration(parent.parentPath)) {
        parent.parentPath.insertBefore(T.expressionStatement(increment));
      } else if (parent && (T.isProgram(parent.parentPath) || T.isBlockStatement(parent.parentPath))) {
        parent.insertBefore(T.expressionStatement(increment));
      } else {
        path.replaceWith(T.sequenceExpression([increment, path.node]));
      }
    }
    /* istanbul ignore else: not expected */
    else if (path.isExpression()) {
        path.replaceWith(T.sequenceExpression([increment, path.node]));
      } else {
        console.error('Unable to insert counter for node type:', path.node.type);
      }
  }

  insertStatementCounter(path) {
    /* istanbul ignore if: paranoid check */
    if (!(path.node && path.node.loc)) {
      return;
    }

    const index = this.cov.newStatement(path.node.loc);
    const increment = this.increase('s', index, null);
    this.insertCounter(path, increment);
  }

  insertFunctionCounter(path) {
    const T = this.types;
    /* istanbul ignore if: paranoid check */

    if (!(path.node && path.node.loc)) {
      return;
    }

    const n = path.node;
    let dloc = null; // get location for declaration

    switch (n.type) {
      case 'FunctionDeclaration':
        /* istanbul ignore else: paranoid check */
        if (n.id) {
          dloc = n.id.loc;
        }

        break;

      case 'FunctionExpression':
        if (n.id) {
          dloc = n.id.loc;
        }

        break;
    }

    if (!dloc) {
      dloc = {
        start: n.loc.start,
        end: {
          line: n.loc.start.line,
          column: n.loc.start.column + 1
        }
      };
    }

    const name = path.node.id ? path.node.id.name : path.node.name;
    const index = this.cov.newFunction(name, dloc, path.node.body.loc);
    const increment = this.increase('f', index, null);
    const body = path.get('body');
    /* istanbul ignore else: not expected */

    if (body.isBlockStatement()) {
      body.node.body.unshift(T.expressionStatement(increment));
    } else {
      console.error('Unable to process function body node type:', path.node.type);
    }
  }

  getBranchIncrement(branchName, loc) {
    const index = this.cov.addBranchPath(branchName, loc);
    return this.increase('b', branchName, index);
  }

  insertBranchCounter(path, branchName, loc) {
    const increment = this.getBranchIncrement(branchName, loc || path.node.loc);
    this.insertCounter(path, increment);
  }

  findLeaves(node, accumulator, parent, property) {
    if (!node) {
      return;
    }

    if (node.type === 'LogicalExpression') {
      const hint = this.hintFor(node);

      if (hint !== 'next') {
        this.findLeaves(node.left, accumulator, node, 'left');
        this.findLeaves(node.right, accumulator, node, 'right');
      }
    } else {
      accumulator.push({
        node,
        parent,
        property
      });
    }
  }

} // generic function that takes a set of visitor methods and
// returns a visitor object with `enter` and `exit` properties,
// such that:
//
// * standard entry processing is done
// * the supplied visitors are called only when ignore is not in effect
//   This relieves them from worrying about ignore states and generated nodes.
// * standard exit processing is done
//


function entries(...enter) {
  // the enter function
  const wrappedEntry = function wrappedEntry(path, node) {
    this.onEnter(path);

    if (this.shouldIgnore(path)) {
      return;
    }

    enter.forEach(e => {
      e.call(this, path, node);
    });
  };

  const exit = function exit(path, node) {
    this.onExit(path, node);
  };

  return {
    enter: wrappedEntry,
    exit
  };
}

function coverStatement(path) {
  this.insertStatementCounter(path);
}
/* istanbul ignore next: no node.js support */


function coverAssignmentPattern(path) {
  const n = path.node;
  const b = this.cov.newBranch('default-arg', n.loc);
  this.insertBranchCounter(path.get('right'), b);
}

function coverFunction(path) {
  this.insertFunctionCounter(path);
}

function coverVariableDeclarator(path) {
  this.insertStatementCounter(path.get('init'));
}

function coverClassPropDeclarator(path) {
  this.insertStatementCounter(path.get('value'));
}

function makeBlock(path) {
  const T = this.types;

  if (!path.node) {
    path.replaceWith(T.blockStatement([]));
  }

  if (!path.isBlockStatement()) {
    path.replaceWith(T.blockStatement([path.node]));
    path.node.loc = path.node.body[0].loc;
  }
}

function blockProp(prop) {
  return function (path) {
    makeBlock.call(this, path.get(prop));
  };
}

function makeParenthesizedExpressionForNonIdentifier(path) {
  const T = this.types;

  if (path.node && !path.isIdentifier()) {
    path.replaceWith(T.parenthesizedExpression(path.node));
  }
}

function parenthesizedExpressionProp(prop) {
  return function (path) {
    makeParenthesizedExpressionForNonIdentifier.call(this, path.get(prop));
  };
}

function convertArrowExpression(path) {
  const n = path.node;
  const T = this.types;

  if (!T.isBlockStatement(n.body)) {
    const bloc = n.body.loc;

    if (n.expression === true) {
      n.expression = false;
    }

    n.body = T.blockStatement([T.returnStatement(n.body)]); // restore body location

    n.body.loc = bloc; // set up the location for the return statement so it gets
    // instrumented

    n.body.body[0].loc = bloc;
  }
}

function coverIfBranches(path) {
  const n = path.node;
  const hint = this.hintFor(n);
  const ignoreIf = hint === 'if';
  const ignoreElse = hint === 'else';
  const branch = this.cov.newBranch('if', n.loc);

  if (ignoreIf) {
    this.setAttr(n.consequent, 'skip-all', true);
  } else {
    this.insertBranchCounter(path.get('consequent'), branch, n.loc);
  }

  if (ignoreElse) {
    this.setAttr(n.alternate, 'skip-all', true);
  } else {
    this.insertBranchCounter(path.get('alternate'), branch, n.loc);
  }
}

function createSwitchBranch(path) {
  const b = this.cov.newBranch('switch', path.node.loc);
  this.setAttr(path.node, 'branchName', b);
}

function coverSwitchCase(path) {
  const T = this.types;
  const b = this.getAttr(path.parentPath.node, 'branchName');
  /* istanbul ignore if: paranoid check */

  if (b === null) {
    throw new Error('Unable to get switch branch name');
  }

  const increment = this.getBranchIncrement(b, path.node.loc);
  path.node.consequent.unshift(T.expressionStatement(increment));
}

function coverTernary(path) {
  const n = path.node;
  const branch = this.cov.newBranch('cond-expr', path.node.loc);
  const cHint = this.hintFor(n.consequent);
  const aHint = this.hintFor(n.alternate);

  if (cHint !== 'next') {
    this.insertBranchCounter(path.get('consequent'), branch);
  }

  if (aHint !== 'next') {
    this.insertBranchCounter(path.get('alternate'), branch);
  }
}

function coverLogicalExpression(path) {
  const T = this.types;

  if (path.parentPath.node.type === 'LogicalExpression') {
    return; // already processed
  }

  const leaves = [];
  this.findLeaves(path.node, leaves);
  const b = this.cov.newBranch('binary-expr', path.node.loc);

  for (let i = 0; i < leaves.length; i += 1) {
    const leaf = leaves[i];
    const hint = this.hintFor(leaf.node);

    if (hint === 'next') {
      continue;
    }

    const increment = this.getBranchIncrement(b, leaf.node.loc);

    if (!increment) {
      continue;
    }

    leaf.parent[leaf.property] = T.sequenceExpression([increment, leaf.node]);
  }
}

const codeVisitor = {
  ArrowFunctionExpression: entries(convertArrowExpression, coverFunction),
  AssignmentPattern: entries(coverAssignmentPattern),
  BlockStatement: entries(),
  // ignore processing only
  ExportDefaultDeclaration: entries(),
  // ignore processing only
  ExportNamedDeclaration: entries(),
  // ignore processing only
  ClassMethod: entries(coverFunction),
  ClassDeclaration: entries(parenthesizedExpressionProp('superClass')),
  ClassProperty: entries(coverClassPropDeclarator),
  ClassPrivateProperty: entries(coverClassPropDeclarator),
  ObjectMethod: entries(coverFunction),
  ExpressionStatement: entries(coverStatement),
  BreakStatement: entries(coverStatement),
  ContinueStatement: entries(coverStatement),
  DebuggerStatement: entries(coverStatement),
  ReturnStatement: entries(coverStatement),
  ThrowStatement: entries(coverStatement),
  TryStatement: entries(coverStatement),
  VariableDeclaration: entries(),
  // ignore processing only
  VariableDeclarator: entries(coverVariableDeclarator),
  IfStatement: entries(blockProp('consequent'), blockProp('alternate'), coverStatement, coverIfBranches),
  ForStatement: entries(blockProp('body'), coverStatement),
  ForInStatement: entries(blockProp('body'), coverStatement),
  ForOfStatement: entries(blockProp('body'), coverStatement),
  WhileStatement: entries(blockProp('body'), coverStatement),
  DoWhileStatement: entries(blockProp('body'), coverStatement),
  SwitchStatement: entries(createSwitchBranch, coverStatement),
  SwitchCase: entries(coverSwitchCase),
  WithStatement: entries(blockProp('body'), coverStatement),
  FunctionDeclaration: entries(coverFunction),
  FunctionExpression: entries(coverFunction),
  LabeledStatement: entries(coverStatement),
  ConditionalExpression: entries(coverTernary),
  LogicalExpression: entries(coverLogicalExpression)
};
const globalTemplateAlteredFunction = (0, _template.default)(`
        var Function = (function(){}).constructor;
        var global = (new Function(GLOBAL_COVERAGE_SCOPE))();
`);
const globalTemplateFunction = (0, _template.default)(`
        var global = (new Function(GLOBAL_COVERAGE_SCOPE))();
`);
const globalTemplateVariable = (0, _template.default)(`
        var global = GLOBAL_COVERAGE_SCOPE;
`); // the template to insert at the top of the program.

const coverageTemplate = (0, _template.default)(`
    var COVERAGE_VAR = (function () {
        var path = PATH;
        var hash = HASH;
        GLOBAL_COVERAGE_TEMPLATE
        var gcv = GLOBAL_COVERAGE_VAR;
        var coverageData = INITIAL;
        var coverage = global[gcv] || (global[gcv] = {});
        if (coverage[path] && coverage[path].hash === hash) {
            return coverage[path];
        }
        return coverage[path] = coverageData;
    })();
`); // the rewire plugin (and potentially other babel middleware)
// may cause files to be instrumented twice, see:
// https://github.com/istanbuljs/babel-plugin-istanbul/issues/94
// we should only instrument code for coverage the first time
// it's run through istanbul-lib-instrument.

function alreadyInstrumented(path, visitState) {
  return path.scope.hasBinding(visitState.varName);
}

function shouldIgnoreFile(programNode) {
  return programNode.parent && programNode.parent.comments.some(c => COMMENT_FILE_RE.test(c.value));
}

const defaultProgramVisitorOpts = {
  inputSourceMap: undefined
};
/**
 * programVisitor is a `babel` adaptor for instrumentation.
 * It returns an object with two methods `enter` and `exit`.
 * These should be assigned to or called from `Program` entry and exit functions
 * in a babel visitor.
 * These functions do not make assumptions about the state set by Babel and thus
 * can be used in a context other than a Babel plugin.
 *
 * The exit function returns an object that currently has the following keys:
 *
 * `fileCoverage` - the file coverage object created for the source file.
 * `sourceMappingURL` - any source mapping URL found when processing the file.
 *
 * @param {Object} types - an instance of babel-types
 * @param {string} sourceFilePath - the path to source file
 * @param {Object} opts - additional options
 * @param {string} [opts.coverageVariable=__coverage__] the global coverage variable name.
 * @param {string} [opts.coverageGlobalScope=this] the global coverage variable scope.
 * @param {boolean} [opts.coverageGlobalScopeFunc=true] use an evaluated function to find coverageGlobalScope.
 * @param {Array} [opts.ignoreClassMethods=[]] names of methods to ignore by default on classes.
 * @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the
 * original code.
 */

function programVisitor(types, sourceFilePath = 'unknown.js', opts = defaultProgramVisitorOpts) {
  const T = types; // This sets some unused options but ensures all required options are initialized

  opts = Object.assign({}, (0, _instrumenter.defaultOpts)(), defaultProgramVisitorOpts, opts);
  const visitState = new VisitState(types, sourceFilePath, opts.inputSourceMap, opts.ignoreClassMethods);
  return {
    enter(path) {
      if (shouldIgnoreFile(path.find(p => p.isProgram()))) {
        return;
      }

      if (alreadyInstrumented(path, visitState)) {
        return;
      }

      path.traverse(codeVisitor, visitState);
    },

    exit(path) {
      if (alreadyInstrumented(path, visitState)) {
        return;
      }

      visitState.cov.freeze();
      const coverageData = visitState.cov.toJSON();

      if (shouldIgnoreFile(path.find(p => p.isProgram()))) {
        return {
          fileCoverage: coverageData,
          sourceMappingURL: visitState.sourceMappingURL
        };
      }

      coverageData[_constants.MAGIC_KEY] = _constants.MAGIC_VALUE;
      const hash = (0, _crypto.createHash)(_constants.SHA).update(JSON.stringify(coverageData)).digest('hex');
      coverageData.hash = hash;
      const coverageNode = T.valueToNode(coverageData);
      delete coverageData[_constants.MAGIC_KEY];
      delete coverageData.hash;
      let gvTemplate;

      if (opts.coverageGlobalScopeFunc) {
        if (path.scope.getBinding('Function')) {
          gvTemplate = globalTemplateAlteredFunction({
            GLOBAL_COVERAGE_SCOPE: T.stringLiteral('return ' + opts.coverageGlobalScope)
          });
        } else {
          gvTemplate = globalTemplateFunction({
            GLOBAL_COVERAGE_SCOPE: T.stringLiteral('return ' + opts.coverageGlobalScope)
          });
        }
      } else {
        gvTemplate = globalTemplateVariable({
          GLOBAL_COVERAGE_SCOPE: opts.coverageGlobalScope
        });
      }

      const cv = coverageTemplate({
        GLOBAL_COVERAGE_VAR: T.stringLiteral(opts.coverageVariable),
        GLOBAL_COVERAGE_TEMPLATE: gvTemplate,
        COVERAGE_VAR: T.identifier(visitState.varName),
        PATH: T.stringLiteral(sourceFilePath),
        INITIAL: coverageNode,
        HASH: T.stringLiteral(hash)
      });
      cv._blockHoist = 5;
      path.node.body.unshift(cv);
      return {
        fileCoverage: coverageData,
        sourceMappingURL: visitState.sourceMappingURL
      };
    }

  };
}

var _default = programVisitor;
exports.default = _default;