Repository: eslint/eslint (JavaScript)

Issue:
`prefer-numeric-literals` overlooks template literal
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

<!--
    If you are using ESLint v6.5.0 or later, you can run ESLint with the `--env-info` flag and paste the output here.
-->

* **ESLint Version:** v7.0.0-alpha.2
* **Node Version:** v11.15.0
* **npm Version:** 6.7.0

**What parser (default, Babel-ESLint, etc.) are you using?**

default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js

```

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->

* [online-demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgcHJlZmVyLW51bWVyaWMtbGl0ZXJhbHM6IFwiZXJyb3JcIiovXG5cbnBhcnNlSW50KGAxMTExMTAxMTFgLCAyKSA9PT0gNTAzOyIsIm9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hVmVyc2lvbiI6MTEsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnsianN4Ijp0cnVlfX0sInJ1bGVzIjp7fSwiZW52Ijp7ImJyb3dzZXIiOmZhbHNlLCJub2RlIjpmYWxzZX19fQ==)
```js
/*eslint prefer-numeric-literals: "error"*/

parseInt(`111110111`, 2) === 503;
```

**What did you expect to happen?**

1 error. 

**What actually happened? Please include the actual, raw output from ESLint.**

No error

**Are you willing to submit a pull request to fix this bug?**

Yes.



Discussion:
I agree it's reasonable to treat "static" template literals as string literals in this rule  :+1: 
I agree that this is a missing case :+1:



Patch:
diff --git a/docs/rules/prefer-numeric-literals.md b/docs/rules/prefer-numeric-literals.md
index 7f4dac1ce1bb..bf81e5ec3363 100644
--- a/docs/rules/prefer-numeric-literals.md
+++ b/docs/rules/prefer-numeric-literals.md
@@ -17,6 +17,7 @@ Examples of **incorrect** code for this rule:
 /*eslint prefer-numeric-literals: "error"*/
 
 parseInt("111110111", 2) === 503;
+parseInt(`111110111`, 2) === 503;
 parseInt("767", 8) === 503;
 parseInt("1F7", 16) === 503;
 Number.parseInt("111110111", 2) === 503;
diff --git a/lib/rules/prefer-numeric-literals.js b/lib/rules/prefer-numeric-literals.js
index c352d88dc07c..2a4fb5d954aa 100644
--- a/lib/rules/prefer-numeric-literals.js
+++ b/lib/rules/prefer-numeric-literals.js
@@ -79,13 +79,13 @@ module.exports = {
 
             "CallExpression[arguments.length=2]"(node) {
                 const [strNode, radixNode] = node.arguments,
-                    str = strNode.value,
+                    str = astUtils.getStaticStringValue(strNode),
                     radix = radixNode.value;
 
                 if (
-                    strNode.type === "Literal" &&
+                    str !== null &&
+                    astUtils.isStringLiteral(strNode) &&
                     radixNode.type === "Literal" &&
-                    typeof str === "string" &&
                     typeof radix === "number" &&
                     radixMap.has(radix) &&
                     isParseInt(node.callee)


Test patch:
diff --git a/tests/lib/rules/prefer-numeric-literals.js b/tests/lib/rules/prefer-numeric-literals.js
index 4d3037f4469e..d8ce4117140d 100644
--- a/tests/lib/rules/prefer-numeric-literals.js
+++ b/tests/lib/rules/prefer-numeric-literals.js
@@ -37,6 +37,8 @@ ruleTester.run("prefer-numeric-literals", rule, {
         "parseInt(1e5, 16);",
         "parseInt('11', '2');",
         "Number.parseInt('11', '8');",
+        "parseInt(/foo/, 2);",
+        "parseInt(`11${foo}`, 2);",
         {
             code: "parseInt('11', 2n);",
             parserOptions: { ecmaVersion: 2020 }
@@ -49,6 +51,10 @@ ruleTester.run("prefer-numeric-literals", rule, {
             code: "parseInt('11', 16n);",
             parserOptions: { ecmaVersion: 2020 }
         },
+        {
+            code: "parseInt(`11`, 16n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
         {
             code: "parseInt(1n, 2);",
             parserOptions: { ecmaVersion: 2020 }
@@ -112,6 +118,42 @@ ruleTester.run("prefer-numeric-literals", rule, {
             output: null, // not fixed, javascript doesn't support emoji literals
             errors: [{ message: "Use hexadecimal literals instead of Number.parseInt()." }]
         },
+        {
+            code: "parseInt(`111110111`, 2) === 503;",
+            output: "0b111110111 === 503;",
+            errors: [{ message: "Use binary literals instead of parseInt()." }]
+        }, {
+            code: "parseInt(`767`, 8) === 503;",
+            output: "0o767 === 503;",
+            errors: [{ message: "Use octal literals instead of parseInt()." }]
+        }, {
+            code: "parseInt(`1F7`, 16) === 255;",
+            output: "0x1F7 === 255;",
+            errors: [{ message: "Use hexadecimal literals instead of parseInt()." }]
+        },
+        {
+            code: "parseInt('', 8);",
+            output: null, // not fixed, it's empty string
+            errors: [{ message: "Use octal literals instead of parseInt()." }]
+        },
+        {
+            code: "parseInt(``, 8);",
+            output: null, // not fixed, it's empty string
+            errors: [{ message: "Use octal literals instead of parseInt()." }]
+        },
+        {
+            code: "parseInt(`7999`, 8);",
+            output: null, // not fixed, unexpected 9 in parseInt string
+            errors: [{ message: "Use octal literals instead of parseInt()." }]
+        }, {
+            code: "parseInt(`1234`, 2);",
+            output: null, // not fixed, invalid binary string
+            errors: [{ message: "Use binary literals instead of parseInt()." }]
+        }, {
+            code: "parseInt(`1234.5`, 8);",
+            output: null, // not fixed, this isn't an integer
+            errors: [{ message: "Use octal literals instead of parseInt()." }]
+        },
 
         // Adjacent tokens tests
         {
@@ -262,6 +304,11 @@ ruleTester.run("prefer-numeric-literals", rule, {
             output: null,
             errors: 1
         },
+        {
+            code: "parseInt(`11`/**/, 2);",
+            output: null,
+            errors: 1
+        },
         {
             code: "parseInt('11', 2 /**/);",
             output: null,