.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / prefer-numeric-literals.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/prefer-numeric-literals.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/prefer-numeric-literals.js
new file mode 100644 (file)
index 0000000..cc82e66
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * @fileoverview Rule to disallow `parseInt()` in favor of binary, octal, and hexadecimal literals
+ * @author Annie Zhang, Henry Zhu
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const radixMap = new Map([
+    [2, { system: "binary", literalPrefix: "0b" }],
+    [8, { system: "octal", literalPrefix: "0o" }],
+    [16, { system: "hexadecimal", literalPrefix: "0x" }]
+]);
+
+/**
+ * Checks to see if a CallExpression's callee node is `parseInt` or
+ * `Number.parseInt`.
+ * @param {ASTNode} calleeNode The callee node to evaluate.
+ * @returns {boolean} True if the callee is `parseInt` or `Number.parseInt`,
+ * false otherwise.
+ */
+function isParseInt(calleeNode) {
+    return (
+        astUtils.isSpecificId(calleeNode, "parseInt") ||
+        astUtils.isSpecificMemberAccess(calleeNode, "Number", "parseInt")
+    );
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "suggestion",
+
+        docs: {
+            description: "disallow `parseInt()` and `Number.parseInt()` in favor of binary, octal, and hexadecimal literals",
+            category: "ECMAScript 6",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/prefer-numeric-literals"
+        },
+
+        schema: [],
+
+        messages: {
+            useLiteral: "Use {{system}} literals instead of {{functionName}}()."
+        },
+
+        fixable: "code"
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+
+        //----------------------------------------------------------------------
+        // Public
+        //----------------------------------------------------------------------
+
+        return {
+
+            "CallExpression[arguments.length=2]"(node) {
+                const [strNode, radixNode] = node.arguments,
+                    str = astUtils.getStaticStringValue(strNode),
+                    radix = radixNode.value;
+
+                if (
+                    str !== null &&
+                    astUtils.isStringLiteral(strNode) &&
+                    radixNode.type === "Literal" &&
+                    typeof radix === "number" &&
+                    radixMap.has(radix) &&
+                    isParseInt(node.callee)
+                ) {
+
+                    const { system, literalPrefix } = radixMap.get(radix);
+
+                    context.report({
+                        node,
+                        messageId: "useLiteral",
+                        data: {
+                            system,
+                            functionName: sourceCode.getText(node.callee)
+                        },
+                        fix(fixer) {
+                            if (sourceCode.getCommentsInside(node).length) {
+                                return null;
+                            }
+
+                            const replacement = `${literalPrefix}${str}`;
+
+                            if (+replacement !== parseInt(str, radix)) {
+
+                                /*
+                                 * If the newly-produced literal would be invalid, (e.g. 0b1234),
+                                 * or it would yield an incorrect parseInt result for some other reason, don't make a fix.
+                                 *
+                                 * If `str` had numeric separators, `+replacement` will evaluate to `NaN` because unary `+`
+                                 * per the specification doesn't support numeric separators. Thus, the above condition will be `true`
+                                 * (`NaN !== anything` is always `true`) regardless of the `parseInt(str, radix)` value.
+                                 * Consequently, no autofixes will be made. This is correct behavior because `parseInt` also
+                                 * doesn't support numeric separators, but it does parse part of the string before the first `_`,
+                                 * so the autofix would be invalid:
+                                 *
+                                 *   parseInt("1_1", 2) // === 1
+                                 *   0b1_1 // === 3
+                                 */
+                                return null;
+                            }
+
+                            const tokenBefore = sourceCode.getTokenBefore(node),
+                                tokenAfter = sourceCode.getTokenAfter(node);
+                            let prefix = "",
+                                suffix = "";
+
+                            if (
+                                tokenBefore &&
+                                tokenBefore.range[1] === node.range[0] &&
+                                !astUtils.canTokensBeAdjacent(tokenBefore, replacement)
+                            ) {
+                                prefix = " ";
+                            }
+
+                            if (
+                                tokenAfter &&
+                                node.range[1] === tokenAfter.range[0] &&
+                                !astUtils.canTokensBeAdjacent(replacement, tokenAfter)
+                            ) {
+                                suffix = " ";
+                            }
+
+                            return fixer.replaceText(node, `${prefix}${replacement}${suffix}`);
+                        }
+                    });
+                }
+            }
+        };
+    }
+};