• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Prohibit the `if (err) throw err;` pattern
3 * @author Teddy Katz
4 */
5
6'use strict';
7
8const utils = require('./rules-utils.js');
9
10module.exports = {
11  meta: {
12    fixable: 'code'
13  },
14  create(context) {
15    const sourceCode = context.getSourceCode();
16    let assertImported = false;
17
18    function hasSameTokens(nodeA, nodeB) {
19      const aTokens = sourceCode.getTokens(nodeA);
20      const bTokens = sourceCode.getTokens(nodeB);
21
22      return aTokens.length === bTokens.length &&
23        aTokens.every((token, index) => {
24          return token.type === bTokens[index].type &&
25            token.value === bTokens[index].value;
26        });
27    }
28
29    function checkAssertNode(node) {
30      if (utils.isRequired(node, ['assert'])) {
31        assertImported = true;
32      }
33    }
34
35    return {
36      'CallExpression': (node) => checkAssertNode(node),
37      'IfStatement': (node) => {
38        const firstStatement = node.consequent.type === 'BlockStatement' ?
39          node.consequent.body[0] :
40          node.consequent;
41        if (
42          firstStatement &&
43          firstStatement.type === 'ThrowStatement' &&
44          hasSameTokens(node.test, firstStatement.argument)
45        ) {
46          const argument = sourceCode.getText(node.test);
47          context.report({
48            node: firstStatement,
49            message: 'Use assert.ifError({{argument}}) instead.',
50            data: { argument },
51            fix: (fixer) => {
52              if (assertImported) {
53                return fixer.replaceText(
54                  node,
55                  `assert.ifError(${argument});`
56                );
57              }
58            }
59          });
60        }
61      }
62    };
63  }
64};
65