summaryrefslogtreecommitdiffstats
path: root/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js
blob: 4b7aeb5151b4c34d580c837a34139c5318e5a815 (plain)
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
/**
 * @fileoverview Rule to prevent throwing bare Cr.ERRORs.
 *
 * 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";

function isCr(object) {
  return object.type === "Identifier" && object.name === "Cr";
}

function isComponentsResults(object) {
  return (
    object.type === "MemberExpression" &&
    object.object.type === "Identifier" &&
    object.object.name === "Components" &&
    object.property.type === "Identifier" &&
    object.property.name === "results"
  );
}

function isNewError(argument) {
  return (
    argument.type === "NewExpression" &&
    argument.callee.type === "Identifier" &&
    argument.callee.name === "Error" &&
    argument.arguments.length === 1
  );
}

function fixT(context, node, argument, fixer) {
  const sourceText = context.getSourceCode().getText(argument);
  return fixer.replaceText(node, `Components.Exception("", ${sourceText})`);
}

module.exports = {
  meta: {
    docs: {
      url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/no-throw-cr-literal.html",
    },
    fixable: "code",
    messages: {
      bareCR: "Do not throw bare Cr.ERRORs, use Components.Exception instead",
      bareComponentsResults:
        "Do not throw bare Components.results.ERRORs, use Components.Exception instead",
      newErrorCR:
        "Do not pass Cr.ERRORs to new Error(), use Components.Exception instead",
      newErrorComponentsResults:
        "Do not pass Components.results.ERRORs to new Error(), use Components.Exception instead",
    },
    schema: [],
    type: "problem",
  },

  create(context) {
    return {
      ThrowStatement(node) {
        if (node.argument.type === "MemberExpression") {
          const fix = fixT.bind(null, context, node.argument, node.argument);

          if (isCr(node.argument.object)) {
            context.report({
              node,
              messageId: "bareCR",
              fix,
            });
          } else if (isComponentsResults(node.argument.object)) {
            context.report({
              node,
              messageId: "bareComponentsResults",
              fix,
            });
          }
        } else if (isNewError(node.argument)) {
          const argument = node.argument.arguments[0];

          if (argument.type === "MemberExpression") {
            const fix = fixT.bind(null, context, node.argument, argument);

            if (isCr(argument.object)) {
              context.report({
                node,
                messageId: "newErrorCR",
                fix,
              });
            } else if (isComponentsResults(argument.object)) {
              context.report({
                node,
                messageId: "newErrorComponentsResults",
                fix,
              });
            }
          }
        }
      },
    };
  },
};