Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / radix.js
1 /**
2  * @fileoverview Rule to flag use of parseInt without a radix argument
3  * @author James Allardice
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Helpers
16 //------------------------------------------------------------------------------
17
18 const MODE_ALWAYS = "always",
19     MODE_AS_NEEDED = "as-needed";
20
21 /**
22  * Checks whether a given variable is shadowed or not.
23  * @param {eslint-scope.Variable} variable A variable to check.
24  * @returns {boolean} `true` if the variable is shadowed.
25  */
26 function isShadowed(variable) {
27     return variable.defs.length >= 1;
28 }
29
30 /**
31  * Checks whether a given node is a MemberExpression of `parseInt` method or not.
32  * @param {ASTNode} node A node to check.
33  * @returns {boolean} `true` if the node is a MemberExpression of `parseInt`
34  *      method.
35  */
36 function isParseIntMethod(node) {
37     return (
38         node.type === "MemberExpression" &&
39         !node.computed &&
40         node.property.type === "Identifier" &&
41         node.property.name === "parseInt"
42     );
43 }
44
45 /**
46  * Checks whether a given node is a valid value of radix or not.
47  *
48  * The following values are invalid.
49  *
50  * - A literal except numbers.
51  * - undefined.
52  * @param {ASTNode} radix A node of radix to check.
53  * @returns {boolean} `true` if the node is valid.
54  */
55 function isValidRadix(radix) {
56     return !(
57         (radix.type === "Literal" && typeof radix.value !== "number") ||
58         (radix.type === "Identifier" && radix.name === "undefined")
59     );
60 }
61
62 /**
63  * Checks whether a given node is a default value of radix or not.
64  * @param {ASTNode} radix A node of radix to check.
65  * @returns {boolean} `true` if the node is the literal node of `10`.
66  */
67 function isDefaultRadix(radix) {
68     return radix.type === "Literal" && radix.value === 10;
69 }
70
71 //------------------------------------------------------------------------------
72 // Rule Definition
73 //------------------------------------------------------------------------------
74
75 module.exports = {
76     meta: {
77         type: "suggestion",
78
79         docs: {
80             description: "enforce the consistent use of the radix argument when using `parseInt()`",
81             category: "Best Practices",
82             recommended: false,
83             url: "https://eslint.org/docs/rules/radix"
84         },
85
86         schema: [
87             {
88                 enum: ["always", "as-needed"]
89             }
90         ]
91     },
92
93     create(context) {
94         const mode = context.options[0] || MODE_ALWAYS;
95
96         /**
97          * Checks the arguments of a given CallExpression node and reports it if it
98          * offends this rule.
99          * @param {ASTNode} node A CallExpression node to check.
100          * @returns {void}
101          */
102         function checkArguments(node) {
103             const args = node.arguments;
104
105             switch (args.length) {
106                 case 0:
107                     context.report({
108                         node,
109                         message: "Missing parameters."
110                     });
111                     break;
112
113                 case 1:
114                     if (mode === MODE_ALWAYS) {
115                         context.report({
116                             node,
117                             message: "Missing radix parameter."
118                         });
119                     }
120                     break;
121
122                 default:
123                     if (mode === MODE_AS_NEEDED && isDefaultRadix(args[1])) {
124                         context.report({
125                             node,
126                             message: "Redundant radix parameter."
127                         });
128                     } else if (!isValidRadix(args[1])) {
129                         context.report({
130                             node,
131                             message: "Invalid radix parameter."
132                         });
133                     }
134                     break;
135             }
136         }
137
138         return {
139             "Program:exit"() {
140                 const scope = context.getScope();
141                 let variable;
142
143                 // Check `parseInt()`
144                 variable = astUtils.getVariableByName(scope, "parseInt");
145                 if (!isShadowed(variable)) {
146                     variable.references.forEach(reference => {
147                         const node = reference.identifier;
148
149                         if (astUtils.isCallee(node)) {
150                             checkArguments(node.parent);
151                         }
152                     });
153                 }
154
155                 // Check `Number.parseInt()`
156                 variable = astUtils.getVariableByName(scope, "Number");
157                 if (!isShadowed(variable)) {
158                     variable.references.forEach(reference => {
159                         const node = reference.identifier.parent;
160
161                         if (isParseIntMethod(node) && astUtils.isCallee(node)) {
162                             checkArguments(node.parent);
163                         }
164                     });
165                 }
166             }
167         };
168     }
169 };