Repository: eslint/eslint (js)

Issue:
`overrides` with processor works unexpectedly
<!--
    ESLint adheres to the Open JS Foundation Code of Conduct:
    https://eslint.org/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://eslint.org/chat/help

    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:** 7.21.0
* **Node Version:** v14.16.0
* **npm Version:** 7.5.6
* **Operating System:** GNU/Linux 5.4.0-1024-gcp

**What parser (default, `@babel/eslint-parser`, `@typescript-eslint/parser`, etc.) are you using?**

Default

**Please show your full configuration:**

https://github.com/JounQin/test/blob/eslint/.eslintrc.js

**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: -->
https://github.com/JounQin/test/blob/eslint/test.cjs

<!-- Paste the command you used to run ESLint: -->
```bash
yarn eslint test.cjs
```

**What did you expect to happen?**

No error because prettier is intended to be disabled

**What actually happened? Please copy-paste the actual, raw output from ESLint.**

```log
Oops! Something went wrong! :(

ESLint: 7.21.0

Error: ENOTDIR: not a directory, stat '/workspace/test/test.cjs/0_.cjs'
Occurred while linting /workspace/test/test.cjs/0_.cjs:1
    at Object.statSync (fs.js:1086:3)
    at isTypeSync (/workspace/test/node_modules/prettier/third-party.js:9748:46)
    at getDirectorySync (/workspace/test/node_modules/prettier/third-party.js:9802:62)
    at ExplorerSync.searchSync (/workspace/test/node_modules/prettier/third-party.js:9950:66)
    at _resolveConfig (/workspace/test/node_modules/prettier/index.js:25592:50)
    at Function.resolveConfig.sync (/workspace/test/node_modules/prettier/index.js:25621:42)
    at Program (/workspace/test/node_modules/eslint-plugin-prettier/eslint-plugin-prettier.js:167:40)
    at /workspace/test/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/workspace/test/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
```

**Steps to reproduce this issue:**

<!-- Please tell us exactly how to see the issue you're describing -->

1. clone https://github.com/JounQin/test/tree/eslint or open https://turquoise-limpet-v0as7arg.ws-us03.gitpod.io/
2. run `yarn eslint test.cjs`, there will be an error
3. toggle the comment in `.eslintrc.js` and run `yarn eslint test.cjs` again, there will be no error, but it is not expected, I want to check `test.cjs` with `prettier` but disable it on code block

**Are you willing to submit a pull request to fix this bug?**

I don't know how to fix it easily.

Pull request description:
Update: lint code block with same extension but different content
close #14207

<!--
    Thank you for contributing!

    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

#### Prerequisites checklist

- [x] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/master/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

[ ] Documentation update
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

#### What changes did you make? (Give an overview)

As title

#### Is there anything you'd like reviewers to focus on?


Patch:
diff --git a/.gitignore b/.gitignore
index a24ba1b65..a00550b00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,5 @@ versions.json
 .temp-eslintcache
 /tests/fixtures/autofix-integration/temp.js
 yarn.lock
-package-lock.json
\ No newline at end of file
+package-lock.json
+pnpm-lock.yaml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f825a2cd..aa02c0b4c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+v7.24.0 - April 9, 2021
+
+* [`0c346c8`](https://github.com/eslint/eslint/commit/0c346c87fa83c6d1184fdafb9c0748c2e15a423d) Chore: ignore `pnpm-lock.yaml` (#14303) (Nitin Kumar)
+* [`f06ecdf`](https://github.com/eslint/eslint/commit/f06ecdf78b6d6f366434d73a6acfe7041d575223) Update: Add disallowTemplateShorthand option in no-implicit-coercion (#13579) (Remco Haszing)
+* [`71a80e3`](https://github.com/eslint/eslint/commit/71a80e38aab2dada01b808ed43d9b0e806d863c4) Docs: fix broken links in Node.js API docs toc (#14296) (u-sho (Shouhei Uechi))
+* [`bd46dc4`](https://github.com/eslint/eslint/commit/bd46dc4647faa4c3bbb5f60d4c00616a64081398) Docs: Fix incorrect reference to "braces" in arrow-parens (#14300) (emclain)
+* [`0d6235e`](https://github.com/eslint/eslint/commit/0d6235ea201b8b90761ee69bb4d46ae18899c28d) Docs: update header in max-lines (#14273) (Shinigami)
+* [`70c9216`](https://github.com/eslint/eslint/commit/70c92164017238e329e3a2d1654a0227b8f953f7) Docs: Update issue triage to include blocked column (#14275) (Nicholas C. Zakas)
+* [`abca186`](https://github.com/eslint/eslint/commit/abca186a845200fd7728c4e5f220973e640054f9) Docs: Fix typo in suggestions section (#14293) (Kevin Partington)
+* [`c4d8b0d`](https://github.com/eslint/eslint/commit/c4d8b0db62b859e721105d4bc0f4044ce346995e) Fix: no-unused-vars ignoreRestSiblings check assignments (fixes #14163) (#14264) (YeonJuan)
+* [`b51d077`](https://github.com/eslint/eslint/commit/b51d0778d76c2aa27578caca3ea82c867dced3e4) Update: add ignoreNonDeclaration to no-multi-assign rule (fixes #12545) (#14185) (t-mangoe)
+* [`c981fb1`](https://github.com/eslint/eslint/commit/c981fb1994cd04914042ced1980aa86b68ba7be9) Chore: Upgrade mocha to 8.3.2 (#14278) (Stephen Wade)
+* [`147fc04`](https://github.com/eslint/eslint/commit/147fc045e699811fab33dddf77498324ddf7e9d6) Docs: Fix `repro:needed` label in bug report template (#14285) (Milos Djermanovic)
+* [`e1cfde9`](https://github.com/eslint/eslint/commit/e1cfde93eec71a15c2df1ad660a7a6171204ba80) Docs: Update bug report template (#14276) (Nicholas C. Zakas)
+* [`c85c2f1`](https://github.com/eslint/eslint/commit/c85c2f1138a9e952655f19ee780ab0c8e35431a8) Docs: Add fatal to Node.js API LintMessage type (#14251) (Brandon Mills)
+
 v7.23.0 - March 26, 2021
 
 * [`687ccae`](https://github.com/eslint/eslint/commit/687ccae517b8b815cf21e948f80d22e2bf118a99) Update: add option "allowInParentheses" to no-sequences (fixes #14197) (#14199) (Daniel Rentz)
diff --git a/docs/rules/no-implicit-coercion.md b/docs/rules/no-implicit-coercion.md
index f78e40c66..8ccee339f 100644
--- a/docs/rules/no-implicit-coercion.md
+++ b/docs/rules/no-implicit-coercion.md
@@ -33,10 +33,11 @@ This rule is aimed to flag shorter notations for the type conversion, then sugge
 
 This rule has three main options and one override option to allow some coercions as required.
 
-* `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
-* `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
-* `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
-* `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
+-   `"boolean"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `boolean` type.
+-   `"number"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `number` type.
+-   `"string"` (`true` by default) - When this is `true`, this rule warns shorter type conversions for `string` type.
+-   `"disallowTemplateShorthand"` (`false` by default) - When this is `true`, this rule warns `string` type conversions using `${expression}` form.
+-   `"allow"` (`empty` by default) - Each entry in this array can be one of `~`, `!!`, `+` or `*` that are to be allowed.
 
 Note that operator `+` in `allow` list would allow `+foo` (number coercion) as well as `"" + foo` (string coercion).
 
@@ -106,6 +107,42 @@ var s = String(foo);
 foo = String(foo);
 ```
 
+### disallowTemplateShorthand
+
+This option is **not** affected by the `string` option.
+
+Examples of **incorrect** code for the `{ "disallowTemplateShorthand": true }` option:
+
+```js
+/*eslint no-implicit-coercion: ["error", { "disallowTemplateShorthand": true }]*/
+
+var s = `${foo}`;
+```
+
+Examples of **correct** code for the `{ "disallowTemplateShorthand": true }` option:
+
+```js
+/*eslint no-implicit-coercion: ["error", { "disallowTemplateShorthand": true }]*/
+
+var s = String(foo);
+
+var s = `a${foo}`;
+
+var s = `${foo}b`;
+
+var s = `${foo}${bar}`;
+
+var s = tag`${foo}`;
+```
+
+Examples of **correct** code for the default `{ "disallowTemplateShorthand": false }` option:
+
+```js
+/*eslint no-implicit-coercion: ["error", { "disallowTemplateShorthand": false }]*/
+
+var s = `${foo}`;
+```
+
 ### allow
 
 Using `allow` list, we can override and allow specific operators.
diff --git a/docs/rules/no-sequences.md b/docs/rules/no-sequences.md
index af4a7a0ed..d4efc1c5b 100644
--- a/docs/rules/no-sequences.md
+++ b/docs/rules/no-sequences.md
@@ -39,6 +39,8 @@ switch (val = foo(), val) {}
 while (val = foo(), val < 42);
 
 with (doSomething(), val) {}
+
+const foo = (val) => (console.log('bar'), val);
 ```
 
 Examples of **correct** code for this rule:
@@ -61,6 +63,8 @@ switch ((val = foo(), val)) {}
 while ((val = foo(), val < 42));
 
 with ((doSomething(), val)) {}
+
+const foo = (val) => ((console.log('bar'), val));
 ```
 
 ## Options
@@ -91,6 +95,8 @@ switch ((val = foo(), val)) {}
 while ((val = foo(), val < 42));
 
 with ((doSomething(), val)) {}
+
+const foo = (val) => ((console.log('bar'), val));
 ```
 
 Examples of **correct** code for this rule with the `{ "allowInParentheses": false }` option:
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index adb5c2155..576816b5b 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -1308,9 +1308,9 @@ class Linter {
                 return [];
             }
 
-            // Resolve configuration again if the file extension was changed.
-            if (configForRecursive && path.extname(blockName) !== originalExtname) {
-                debug("Resolving configuration again because the file extension was changed.");
+            // Resolve configuration again if the file content or extension was changed.
+            if (configForRecursive && (text !== blockText || path.extname(blockName) !== originalExtname)) {
+                debug("Resolving configuration again because the file content or extension was changed.");
                 return this._verifyWithConfigArray(
                     blockText,
                     configForRecursive,
diff --git a/lib/rules/no-implicit-coercion.js b/lib/rules/no-implicit-coercion.js
index a639711ec..b9bb45489 100644
--- a/lib/rules/no-implicit-coercion.js
+++ b/lib/rules/no-implicit-coercion.js
@@ -24,6 +24,7 @@ function parseOptions(options) {
         boolean: "boolean" in options ? options.boolean : true,
         number: "number" in options ? options.number : true,
         string: "string" in options ? options.string : true,
+        disallowTemplateShorthand: "disallowTemplateShorthand" in options ? options.disallowTemplateShorthand : false,
         allow: options.allow || []
     };
 }
@@ -180,6 +181,10 @@ module.exports = {
                     type: "boolean",
                     default: true
                 },
+                disallowTemplateShorthand: {
+                    type: "boolean",
+                    default: false
+                },
                 allow: {
                     type: "array",
                     items: {
@@ -299,6 +304,38 @@ module.exports = {
 
                     report(node, recommendation, true);
                 }
+            },
+
+            TemplateLiteral(node) {
+                if (!options.disallowTemplateShorthand) {
+                    return;
+                }
+
+                // tag`${foo}`
+                if (node.parent.type === "TaggedTemplateExpression") {
+                    return;
+                }
+
+                // `` or `${foo}${bar}`
+                if (node.expressions.length !== 1) {
+                    return;
+                }
+
+
+                //  `prefix${foo}`
+                if (node.quasis[0].value.cooked !== "") {
+                    return;
+                }
+
+                //  `${foo}postfix`
+                if (node.quasis[1].value.cooked !== "") {
+                    return;
+                }
+
+                const code = sourceCode.getText(node.expressions[0]);
+                const recommendation = `String(${code})`;
+
+                report(node, recommendation, true);
             }
         };
     }
diff --git a/package.json b/package.json
index 8f1308965..b414ca6ea 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "7.23.0",
+  "version": "7.24.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {


Test patch:
diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js
index ec7f13cd8..c7783a6c0 100644
--- a/tests/lib/eslint/eslint.js
+++ b/tests/lib/eslint/eslint.js
@@ -2917,6 +2917,54 @@ describe("ESLint", () => {
                 assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
             });
 
+            it("should run processors when calling lintText with processor resolves same extension but different content correctly", async () => {
+                let count = 0;
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["test-processor"],
+                        overrides: [{
+                            files: ["**/*.txt/*.txt"],
+                            rules: {
+                                "no-console": 2,
+                                "no-unused-vars": 2
+                            }
+                        }]
+                    },
+                    extensions: ["txt"],
+                    ignore: false,
+                    plugins: {
+                        "test-processor": {
+                            processors: {
+                                ".txt": {
+                                    preprocess(text) {
+                                        count++;
+                                        return [
+                                            {
+
+                                                // it will be run twice, and text will be as-is at the second time, then it will not run third time
+                                                text: text.replace("a()", "b()"),
+                                                filename: ".txt"
+                                            }
+                                        ];
+                                    },
+                                    postprocess(messages) {
+                                        messages[0][0].ruleId = "post-processed";
+                                        return messages[0];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                });
+                const results = await eslint.lintText("function a() {console.log(\"Test\");}", { filePath: "tests/fixtures/processors/test/test-processor.txt" });
+
+                assert.strictEqual(count, 2);
+                assert.strictEqual(results[0].messages[0].message, "'b' is defined but never used.");
+                assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
+            });
+
             describe("autofixing with processors", () => {
                 const HTML_PROCESSOR = Object.freeze({
                     preprocess(text) {
diff --git a/tests/lib/rules/no-implicit-coercion.js b/tests/lib/rules/no-implicit-coercion.js
index fa2b68b49..fa0a63824 100644
--- a/tests/lib/rules/no-implicit-coercion.js
+++ b/tests/lib/rules/no-implicit-coercion.js
@@ -88,6 +88,13 @@ ruleTester.run("no-implicit-coercion", rule, {
         { code: "`${foo}` + ''", parserOptions: { ecmaVersion: 6 } },
         "foo += 'bar'",
         { code: "foo += `${bar}`", parserOptions: { ecmaVersion: 6 } },
+        { code: "`a${foo}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "`${foo}b`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "`${foo}${bar}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "tag`${foo}`", options: [{ disallowTemplateShorthand: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "`${foo}`", parserOptions: { ecmaVersion: 6 } },
+        { code: "`${foo}`", options: [{ }], parserOptions: { ecmaVersion: 6 } },
+        { code: "`${foo}`", options: [{ disallowTemplateShorthand: false }], parserOptions: { ecmaVersion: 6 } },
         "+42"
     ],
     invalid: [
@@ -248,6 +255,39 @@ ruleTester.run("no-implicit-coercion", rule, {
                 type: "BinaryExpression"
             }]
         },
+        {
+            code: "`${foo}`",
+            output: "String(foo)",
+            options: [{ disallowTemplateShorthand: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "useRecommendation",
+                data: { recommendation: "String(foo)" },
+                type: "TemplateLiteral"
+            }]
+        },
+        {
+            code: "`\\\n${foo}`",
+            output: "String(foo)",
+            options: [{ disallowTemplateShorthand: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "useRecommendation",
+                data: { recommendation: "String(foo)" },
+                type: "TemplateLiteral"
+            }]
+        },
+        {
+            code: "`${foo}\\\n`",
+            output: "String(foo)",
+            options: [{ disallowTemplateShorthand: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "useRecommendation",
+                data: { recommendation: "String(foo)" },
+                type: "TemplateLiteral"
+            }]
+        },
         {
             code: "foo += \"\"",
             output: "foo = String(foo)",