/**
 * @fileoverview Reject run_test() definitions where they aren't necessary.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

"use strict";

// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------

module.exports = function(context) {

  // ---------------------------------------------------------------------------
  // Public
  //  --------------------------------------------------------------------------

  return {
    "Program > FunctionDeclaration": function(node) {
      if (node.id.name === "run_test" &&
          node.body.type === "BlockStatement" &&
          node.body.body.length === 1 &&
          node.body.body[0].type === "ExpressionStatement" &&
          node.body.body[0].expression.type === "CallExpression" &&
          node.body.body[0].expression.callee.name === "run_next_test") {
        context.report({
          node,
          fix: fixer => {
            let sourceCode = context.getSourceCode();
            let startNode;
            if (sourceCode.getCommentsBefore) {
              // ESLint 4 has getCommentsBefore.
              startNode = sourceCode.getCommentsBefore(node);
            } else if (node && node.body && node.leadingComments) {
              // This is for ESLint 3.
              startNode = node.leadingComments;
            }

            // If we have comments, we want the start node to be the comments,
            // rather than the token before the comments, so that we don't
            // remove the comments - for run_test, these are likely to be useful
            // information about the test.
            if (startNode && startNode.length) {
              startNode = startNode[startNode.length - 1];
            } else {
              startNode = sourceCode.getTokenBefore(node);
            }

            return fixer.removeRange([
              // If there's no startNode, we fall back to zero, i.e. start of
              // file.
              startNode ? (startNode.end + 1) : 0,
              // We know the function is a block and it'll end with }. Normally
              // there's a new line after that, so just advance past it. This
              // may be slightly not dodgy in some cases, but covers the existing
              // cases.
              node.end + 1
            ]);
          },
          message: "Useless run_test function - only contains run_next_test; whole function can be removed"
        });
      }
    }
  };
};
