Repository: eslint/eslint
Pull request #15439 (2021-12-19 08:38:13)

feat: no-restricted-imports support casing
<!--
    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/HEAD/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

<!--
    The following template is intentionally not a markdown checkbox list for the reasons
    explained in https://github.com/eslint/eslint/pull/12848#issuecomment-580302888
-->

[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-proposal.md))
[x] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-change-proposal.md))
[ ] Add autofix 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.)
-->

**What rule do you want to change?**

[no-restricted-imports](https://eslint.org/docs/rules/no-restricted-imports)

**Does this change cause the rule to produce more or fewer warnings?**

By default, the amount of warnings is unchanged.  Otherwise, it should be fewer warnings.

**How will the change be implemented? (New option, new default behavior, etc.)?**

A new option is added, with a default value that maintains backwards-compatibility.

**Please provide some example code that this change will affect:**

```js
import 'food';
import 'fooBar';
```

```json
"no-restricted-imports": ["error", {
    "patterns": [{
      "group": ["foo[A-Z]*"]
    }]
}]
```

**What does the rule currently do for this code?**

It will issue warnings for both imports.

**What will the rule do after it's changed?**

If we add the new option:

```json
"no-restricted-imports": ["error", {
    "patterns": [{
      "group": ["foo[A-Z]*"],
      "caseSensitive": true
    }]
}]
```

The rule will issue a warning **ONLY** for the second import.

<!--
    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)

Enhances [no-restricted-imports](https://eslint.org/docs/rules/no-restricted-imports) to support more granular import restrictions via case-sensitive pattern matching.  By default, this rule remains case-insensitive to maintain backwards compatibility with earlier versions.  Only by explicitly specifying it in a custom pattern object (see the added docs) can it be triggered.

Path matching in `.gitignore` can be case-sensitive, and `ignore@5.2.0` supports this as well as maintains support for relative paths, whose support was dropped after `4.0.6` but restored in `5.2.0` (this was a blocker for past upgrades).

#### Is there anything you'd like reviewers to focus on?

N/A

linux-foundation-easycla[bot]: <a href="https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15439/#/?version=2"><img src="https://s3.amazonaws.com/cla-project-logo-prod/cla-not-signed.svg" alt="CLA Not Signed" align="left" height="28" width="328" ></a><br/><br /><ul><li><a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15439/#/?version=2' target='_blank'>:x:</a> - gfyoung The commit (dc3b2192433218fce3d742c6bc097ae75a8b6bf4) is not authorized under a signed CLA. <a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19114526/11061773/15439/#/?version=2' target='_blank'>Please click here to be authorized</a>. For further assistance with EasyCLA, <a href='https://jira.linuxfoundation.org/servicedesk/customer/portal/4' target='_blank'>please submit a support request ticket</a>.</li></ul>
eslint-github-bot[bot]: Hi @gfyoung!, thanks for the Pull Request

The **first commit message** isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.

- The commit message tag wasn't recognized. Did you mean "docs", "fix", or "feat"?
- There should be a space following the initial tag and colon, for example 'feat: Message'.
- The first letter of the tag should be in lowercase

**To Fix:** You can fix this problem by running `git commit --amend`, editing your commit message, and then running `git push -f` to update this pull request.

Read more about contributing to ESLint [here](https://eslint.org/docs/developer-guide/contributing/)

mdjermanovic: The option makes sense to me :+1:, and it would be nice to update the `ignore` dependency.

Waiting for more opinions from team members, since this is an enhancement.
gfyoung: @mdjermanovic: PR has been updated with the requested changes, with tests still passing. 👍
btmills: This seems reasonable, but before adding new API, I find it helpful to understand the motivation. @gfyoung can you elaborate a bit on what use case you're trying to accomplish with case-sensitive path patterns?
gfyoung: @btmills: I believe the use case described in the PR description illustrates the motivation.

If not, please let me know what further information or detail is required.
btmills: @gfyoung the PR description covered a lot of the _how_ but not much of the _why_.  What are you hoping to do with ESLint that you can't today?
gfyoung: > What are you hoping to do with ESLint that you can't today?

I want to be able to do more granular import restrictions using case-sensitive regular expressions.
btmills: Okay, and what are you hoping to use case-sensitive import restrictions for?
gfyoung: The example provided in the [PR description](https://github.com/eslint/eslint/pull/15439#issue-806019528) illustrates a case where I would want to use case-sensitive import restrictions.
nzakas: @gfyoung the problem is that your description looks like a theoretical problem and not a real-life use case. What @btmills is asking for is something more concrete. What situation did you run into where this option would be helpful?
gfyoung: > the problem is that your description looks like a theoretical problem and not a real-life use case.

@nzakas: First off, expanding the API for the sake of a theoretical problem would be a waste of time for all of us.  I have been waiting to submit this PR for quite some time, as I had to get commits to `ignore` merged and released first.

Without sharing actual code, I thought the example using `foo` would be minimal and sufficient to explain the situation where this option would be helpful.  However, if you would like to see more realistic import names, here is an example, without sharing actual code that should help:

~~~js
import * as bots from bots;
import * as botUtils from botUtils;   // TODO: all imports should be from `bots`
~~~

In this case, we want all developers to importing from the `bots` file and not any of its constituent `bot[A-Z]*` files, which are in the process of being refactored and moved, but this will take quite some time to complete.
nzakas: @gfyoung please understand, we review a lot of PRs, and not all of them are well thought out. We need to ask followup questions and for more examples in order to figure out which ones are worth pursuing and which don’t provide much value to the project.

Answering our questions helps a lot, and if the PR description was enough, we wouldn’t ask for more info. 
gfyoung: @nzakas: I understand the need to request clarification.  As a maintainer myself, I can relate to the experience of working through PRs that have not been as well thought out as we would like.  That said, suggesting that someone's PR description is a "theoretical problem" before knowing more (e.g., not wanting to divulge actual code) is where some umbrage was taken.  IMO prefer to give contributors benefit of the doubt to prove themselves before coming to a conclusion about the PR.

Anyhow, I'll leave it at that.  Appreciate the feedback so far. 👍

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5d9aa9536..939496ded 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,9 +1,9 @@
 name: CI
 on:
   push:
-    branches: [master, main]
+    branches: [main]
   pull_request:
-    branches: [master, main]
+    branches: [main]
 
 jobs:
   verify_files:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ef362a4b6..60f7922fd 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -13,10 +13,10 @@ name: "CodeQL"
 
 on:
   push:
-    branches: [master, main]
+    branches: [main]
   pull_request:
     # The branches below must be a subset of the branches above
-    branches: [master, main]
+    branches: [main]
   schedule:
     - cron: '28 17 * * 5'
 
diff --git a/README.md b/README.md
index 088e19694..6c6a855ec 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ $ npm install eslint --save-dev
 You should then set up a configuration file:
 
 ```sh
-$ ./node_modules/.bin/eslint --init
+$ npm init @eslint/config
 ```
 
 After that, you can run ESLint on any file or directory like this:
@@ -65,7 +65,7 @@ $ ./node_modules/.bin/eslint yourfile.js
 
 ## <a name="configuration"></a>Configuration
 
-After running `eslint --init`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
+After running `npm init @eslint/config`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
 
 ```json
 {
@@ -294,7 +294,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
 <p><a href="https://contra.com"><img src="https://images.opencollective.com/contra1/c70f93f/logo.png" alt="Contra" height="96"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
+<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/bin/eslint.js b/bin/eslint.js
index 6b05356b9..d00a870c0 100755
--- a/bin/eslint.js
+++ b/bin/eslint.js
@@ -124,7 +124,13 @@ ${message}`);
 
     // Call the config initializer if `--init` is present.
     if (process.argv.includes("--init")) {
-        await require("../lib/init/config-initializer").initializeConfig();
+
+        // `eslint --init` has been moved to `@eslint/create-config`
+        console.warn("You can also run this command directly using 'npm init @eslint/config'.");
+
+        const spawn = require("cross-spawn");
+
+        spawn.sync("npm", ["init", "@eslint/config"], { encoding: "utf8", stdio: "inherit" });
         return;
     }
 
diff --git a/docs/developer-guide/architecture.md b/docs/developer-guide/architecture.md
index 6531c2839..37261abcc 100644
--- a/docs/developer-guide/architecture.md
+++ b/docs/developer-guide/architecture.md
@@ -7,7 +7,6 @@ At a high level, there are a few key parts to ESLint:
 * `bin/eslint.js` - this is the file that actually gets executed with the command line utility. It's a dumb wrapper that does nothing more than bootstrap ESLint, passing the command line arguments to `cli`. This is intentionally small so as not to require heavy testing.
 * `lib/api.js` - this is the entry point of `require("eslint")`. This file exposes an object that contains public classes `Linter`, `ESLint`, `RuleTester`, and `SourceCode`.
 * `lib/cli.js` - this is the heart of the ESLint CLI. It takes an array of arguments and then uses `eslint` to execute the commands. By keeping this as a separate utility, it allows others to effectively call ESLint from within another Node.js program as if it were done on the command line. The main call is `cli.execute()`. This is also the part that does all the file reading, directory traversing, input, and output.
-* `lib/init/` - this module contains `--init` functionality that set up a configuration file for end users.
 * `lib/cli-engine/` - this module is `CLIEngine` class that finds source code files and configuration files then does code verifying with the `Linter` class. This includes the loading logic of configuration files, parsers, plugins, and formatters.
 * `lib/linter/` - this module is the core `Linter` class that does code verifying based on configuration options. This file does no file I/O and does not interact with the `console` at all. For other Node.js programs that have JavaScript text to verify, they would be able to use this interface directly.
 * `lib/rule-tester/` - this module is `RuleTester` class that is a wrapper around Mocha so that rules can be unit tested. This class lets us write consistently formatted tests for each rule that is implemented and be confident that each of the rules work. The RuleTester interface was modeled after Mocha and works with Mocha's global testing methods. RuleTester can also be modified to work with other testing frameworks.
diff --git a/docs/developer-guide/contributing/pull-requests.md b/docs/developer-guide/contributing/pull-requests.md
index 58fe6f9c0..f1d62e1e9 100644
--- a/docs/developer-guide/contributing/pull-requests.md
+++ b/docs/developer-guide/contributing/pull-requests.md
@@ -30,7 +30,7 @@ Details about each step are found below.
 
 The first step to sending a pull request is to create a new branch in your ESLint fork. Give the branch a descriptive name that describes what it is you're fixing, such as:
 
-```sh
+```shell
 $ git checkout -b issue1234
 ```
 
@@ -42,7 +42,7 @@ You should do all of your development for the issue in this branch.
 
 Make the changes to the code and tests, following the [code conventions](../code-conventions.md) as you go. Once you have finished, commit the changes to your branch:
 
-```sh
+```shell
 $ git add -A
 $ git commit
 ```
@@ -91,7 +91,7 @@ The commit message format is important because these messages are used to create
 
 Before you send the pull request, be sure to rebase onto the upstream source. This ensures your code is running on the latest available code.
 
-```sh
+```shell
 git fetch upstream
 git rebase upstream/main
 ```
@@ -100,7 +100,7 @@ git rebase upstream/main
 
 After rebasing, be sure to run all of the tests once again to make sure nothing broke:
 
-```sh
+```shell
 npm test
 ```
 
@@ -123,13 +123,13 @@ With your code ready to go, this is a good time to double-check your submission
 
 Next, push your changes to your clone:
 
-```sh
+```shell
 git push origin issue1234
 ```
 
 If you are unable to push because some references are old, do a forced push instead:
 
-```sh
+```shell
 git push -f origin issue1234
 ```
 
@@ -149,13 +149,13 @@ Once your pull request is sent, it's time for the team to review it. As such, pl
 
 If your commit message is in the incorrect format, you'll be asked to update it. You can do so via:
 
-```sh
+```shell
 $ git commit --amend
 ```
 
 This will open up your editor so you can make changes. After that, you'll need to do a forced push to your branch:
 
-```sh
+```shell
 $ git push origin issue1234 -f
 ```
 
@@ -163,7 +163,7 @@ $ git push origin issue1234 -f
 
 If we ask you to make code changes, there's no need to close the pull request and create a new one. Just go back to the branch on your fork and make your changes. Then, when you're ready, you can add your changes into the branch:
 
-```sh
+```shell
 $ git add -A
 $ git commit
 $ git push origin issue1234
@@ -177,13 +177,13 @@ The commit messages in subsequent commits do not need to be in any specific form
 
 If your code is out-of-date, we might ask you to rebase. That means we want you to apply your changes on top of the latest upstream code. Make sure you have set up a [development environment](../development-environment.md) and then you can rebase using these commands:
 
-```sh
+```shell
 $ git fetch upstream
 $ git rebase upstream/main
 ```
 
 You might find that there are merge conflicts when you attempt to rebase. Please [resolve the conflicts](https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/) and then do a forced push to your branch:
 
-```sh
+```shell
 $ git push origin issue1234 -f
 ```
diff --git a/docs/developer-guide/development-environment.md b/docs/developer-guide/development-environment.md
index 4828476aa..5be51bd2c 100644
--- a/docs/developer-guide/development-environment.md
+++ b/docs/developer-guide/development-environment.md
@@ -14,7 +14,7 @@ Go to <https://github.com/eslint/eslint> and click the "Fork" button. Follow the
 
 Once you've cloned the repository, run `npm install` to get all the necessary dependencies:
 
-```sh
+```shell
 $ cd eslint
 $ npm install
 ```
@@ -27,7 +27,7 @@ The *upstream source* is the main ESLint repository where active development hap
 
 To add the upstream source for ESLint, run the following in your repository:
 
-```sh
+```shell
 git remote add upstream git@github.com:eslint/eslint.git
 ```
 
@@ -49,7 +49,7 @@ Please see the [generator documentation](https://github.com/eslint/generator-esl
 
 Running the tests is the best way to ensure you have correctly set up your development environment. Make sure you're in the `eslint` directory and run:
 
-```sh
+```shell
 npm test
 ```
 
diff --git a/docs/rules/keyword-spacing.md b/docs/rules/keyword-spacing.md
index 8ca673937..031873b5e 100644
--- a/docs/rules/keyword-spacing.md
+++ b/docs/rules/keyword-spacing.md
@@ -243,14 +243,15 @@ if(foo) {
 
 ### overrides
 
-Examples of **correct** code for this rule with the `{ "overrides": { "if": { "after": false }, "for": { "after": false }, "while": { "after": false }, "static": { "after": false } } }` option:
+Examples of **correct** code for this rule with the `{ "overrides": { "if": { "after": false }, "for": { "after": false }, "while": { "after": false }, "static": { "after": false }, "as": { "after": false } } }` option:
 
 ```js
 /*eslint keyword-spacing: ["error", { "overrides": {
   "if": { "after": false },
   "for": { "after": false },
   "while": { "after": false },
-  "static": { "after": false }
+  "static": { "after": false },
+  "as": { "after": false }
 } }]*/
 
 if(foo) {
@@ -272,6 +273,8 @@ class C {
         //...
     }
 }
+
+export { C as"my class" };
 ```
 
 ## When Not To Use It
diff --git a/docs/rules/no-mixed-operators.md b/docs/rules/no-mixed-operators.md
index 1dca581e8..d1eac5494 100644
--- a/docs/rules/no-mixed-operators.md
+++ b/docs/rules/no-mixed-operators.md
@@ -20,7 +20,7 @@ var foo = a && b || c || d;
 
 will generate
 
-```sh
+```shell
 1:13  Unexpected mix of '&&' and '||'. (no-mixed-operators)
 1:18  Unexpected mix of '&&' and '||'. (no-mixed-operators)
 ```
@@ -31,7 +31,7 @@ var foo = a && b ? c : d;
 
 will generate
 
-```sh
+```shell
 1:13  Unexpected mix of '&&' and '?:'. (no-mixed-operators)
 1:18  Unexpected mix of '&&' and '?:'. (no-mixed-operators)
 ```
diff --git a/docs/rules/no-restricted-exports.md b/docs/rules/no-restricted-exports.md
index 29938579d..667a9c3fd 100644
--- a/docs/rules/no-restricted-exports.md
+++ b/docs/rules/no-restricted-exports.md
@@ -18,7 +18,7 @@ Examples of **incorrect** code for this rule:
 
 ```js
 /*eslint no-restricted-exports: ["error", {
-    "restrictedNamedExports": ["foo", "bar", "Baz", "a", "b", "c", "d"]
+    "restrictedNamedExports": ["foo", "bar", "Baz", "a", "b", "c", "d", "e", "👍"]
 }]*/
 
 export const foo = 1;
@@ -33,16 +33,20 @@ export { a };
 function someFunction() {}
 export { someFunction as b };
 
-export { c } from 'some_module';
+export { c } from "some_module";
 
-export { something as d } from 'some_module';
+export { "d" } from "some_module";
+
+export { something as e } from "some_module";
+
+export { "👍" } from "some_module";
 ```
 
 Examples of **correct** code for this rule:
 
 ```js
 /*eslint no-restricted-exports: ["error", {
-    "restrictedNamedExports": ["foo", "bar", "Baz", "a", "b", "c", "d"]
+    "restrictedNamedExports": ["foo", "bar", "Baz", "a", "b", "c", "d", "e", "👍"]
 }]*/
 
 export const quux = 1;
@@ -57,9 +61,13 @@ export { a as myObject };
 function someFunction() {}
 export { someFunction };
 
-export { c as someName } from 'some_module';
+export { c as someName } from "some_module";
+
+export { "d" as " d " } from "some_module";
+
+export { something } from "some_module";
 
-export { something } from 'some_module';
+export { "👍" as thumbsUp } from "some_module";
 ```
 
 ### Default exports
@@ -79,7 +87,7 @@ export { foo as default };
 ```js
 /*eslint no-restricted-exports: ["error", { "restrictedNamedExports": ["default"] }]*/
 
-export { default } from 'some_module';
+export { default } from "some_module";
 ```
 
 Examples of additional **correct** code for this rule:
@@ -102,5 +110,5 @@ export function foo() {}
 //----- my_module.js -----
 /*eslint no-restricted-exports: ["error", { "restrictedNamedExports": ["foo"] }]*/
 
-export * from 'some_module'; // allowed, although this declaration exports "foo" from my_module
+export * from "some_module"; // allowed, although this declaration exports "foo" from my_module
 ```
diff --git a/docs/rules/no-restricted-imports.md b/docs/rules/no-restricted-imports.md
index d8e06101b..3a88fabca 100644
--- a/docs/rules/no-restricted-imports.md
+++ b/docs/rules/no-restricted-imports.md
@@ -91,6 +91,17 @@ or like this if you want to apply a custom message to pattern matches:
 
 The custom message will be appended to the default error message.
 
+Pattern matches can also be configured to be case-sensitive:
+
+```json
+"no-restricted-imports": ["error", {
+    "patterns": [{
+      "group": ["import1/private/prefix[A-Z]*"],
+      "caseSensitive": true
+    }]
+}]
+```
+
 To restrict the use of all Node.js core imports (via <https://github.com/nodejs/node/tree/master/lib>):
 
 ```json
@@ -150,7 +161,11 @@ import DisallowedObject from "foo";
     message: "Please import 'DisallowedObject' from '/bar/baz/' instead."
 }]}]*/
 
+import { DisallowedObject } from "foo";
+
 import { DisallowedObject as AllowedObject } from "foo";
+
+import { "DisallowedObject" as AllowedObject } from "foo";
 ```
 
 ```js
@@ -172,6 +187,15 @@ import * as Foo from "foo";
 import pick from 'lodash/pick';
 ```
 
+```js
+/*eslint no-restricted-imports: ["error", { patterns: [{
+    group: ["foo[A-Z]*"],
+    caseSensitive: true
+}]}]*/
+
+import pick from 'fooBar';
+```
+
 Examples of **correct** code for this rule:
 
 ```js
@@ -214,6 +238,15 @@ import { AllowedObject as DisallowedObject } from "foo";
 import lodash from 'lodash';
 ```
 
+```js
+/*eslint no-restricted-imports: ["error", { patterns: [{
+    group: ["foo[A-Z]*"],
+    caseSensitive: true
+}]}]*/
+
+import pick from 'food';
+```
+
 ## When Not To Use It
 
 Don't use this rule or don't include a module in the list for this rule if you want to be able to import a module in your project without an ESLint error or warning.
diff --git a/docs/rules/no-useless-rename.md b/docs/rules/no-useless-rename.md
index fba312332..1a827288c 100644
--- a/docs/rules/no-useless-rename.md
+++ b/docs/rules/no-useless-rename.md
@@ -52,8 +52,11 @@ Examples of **incorrect** code for this rule by default:
 /*eslint no-useless-rename: "error"*/
 
 import { foo as foo } from "bar";
+import { "foo" as foo } from "bar";
 export { foo as foo };
+export { foo as "foo" };
 export { foo as foo } from "bar";
+export { "foo" as "foo" } from "bar";
 let { foo: foo } = bar;
 let { 'foo': foo } = bar;
 function foo({ bar: bar }) {}
@@ -68,10 +71,13 @@ Examples of **correct** code for this rule by default:
 import * as foo from "foo";
 import { foo } from "bar";
 import { foo as bar } from "baz";
+import { "foo" as bar } from "baz";
 
 export { foo };
 export { foo as bar };
+export { foo as "bar" };
 export { foo as bar } from "foo";
+export { "foo" as "bar" } from "foo";
 
 let { foo } = bar;
 let { foo: bar } = baz;
diff --git a/docs/user-guide/command-line-interface.md b/docs/user-guide/command-line-interface.md
index 6f350d485..e5b941040 100644
--- a/docs/user-guide/command-line-interface.md
+++ b/docs/user-guide/command-line-interface.md
@@ -1,30 +1,34 @@
 # Command Line Interface
 
-To run ESLint on Node.js, you must have npm installed. If npm is not installed, follow the instructions here: <https://www.npmjs.com/>
+ESLint requires Node.js for installation. Follow the instructions in the [Getting Started Guide](https://eslint.org/docs/user-guide/getting-started) to install ESLint.
 
-Once npm is installed, run the following
+Most users use [`npx`](https://docs.npmjs.com/cli/v8/commands/npx) to run ESLint on the command line like this:
 
-    npm i -g eslint
-
-This installs the ESLint CLI from the npm repository. To run ESLint, use the following format:
-
-    eslint [options] [file|dir|glob]*
+```shell
+npx eslint [options] [file|dir|glob]*
+```
 
 Such as:
 
-    eslint file1.js file2.js
-
-or:
+```shell
+# Run on two files
+npx eslint file1.js file2.js
 
-    eslint lib/**
+# Run on multiples files
+npx eslint lib/**
+```
 
 Please note that when passing a glob as a parameter, it will be expanded by your shell. The results of the expansion can vary depending on your shell, and its configuration. If you want to use node `glob` syntax, you have to quote your parameter (using double quotes if you need it to run in Windows), as follows:
 
-    eslint "lib/**"
+```shell
+npx eslint "lib/**"
+```
+
+**Note:** You can also use alternative package managers such as [Yarn](https://yarnpkg.com/) or [pnpm](https://pnpm.io/) to run ESLint. Please refer to your package manager's documentation for the correct syntax.
 
 ## Options
 
-The command line utility has several options. You can view the options by running `eslint -h`.
+The command line utility has several options. You can view the options by running `npx eslint -h`.
 
 ```text
 eslint [options] file.js [file.js] [dir]
@@ -92,9 +96,9 @@ Options that accept array values can be specified by repeating the option or wit
 
 Example:
 
-    eslint --ext .jsx --ext .js lib/
+    npx eslint --ext .jsx --ext .js lib/
 
-    eslint --ext .jsx,.js lib/
+    npx eslint --ext .jsx,.js lib/
 
 ### Basic configuration
 
@@ -104,7 +108,7 @@ Disables use of configuration from `.eslintrc.*` and `package.json` files.
 
 Example:
 
-    eslint --no-eslintrc file.js
+    npx eslint --no-eslintrc file.js
 
 #### `-c`, `--config`
 
@@ -112,7 +116,7 @@ This option allows you to specify an additional configuration file for ESLint (s
 
 Example:
 
-    eslint -c ~/my-eslint.json file.js
+    npx eslint -c ~/my-eslint.json file.js
 
 This example uses the configuration file at `~/my-eslint.json`.
 
@@ -124,8 +128,8 @@ This option enables specific environments. Details about the global variables de
 
 Examples:
 
-    eslint --env browser,node file.js
-    eslint --env browser --env node file.js
+    npx eslint --env browser,node file.js
+    npx eslint --env browser --env node file.js
 
 #### `--ext`
 
@@ -135,17 +139,17 @@ By default, ESLint lints `*.js` files and the files that match the `overrides` e
 Examples:
 
     # Use only .ts extension
-    eslint . --ext .ts
+    npx eslint . --ext .ts
 
     # Use both .js and .ts
-    eslint . --ext .js --ext .ts
+    npx eslint . --ext .js --ext .ts
 
     # Also use both .js and .ts
-    eslint . --ext .js,.ts
+    npx eslint . --ext .js,.ts
 
 **Note:** `--ext` is only used when the arguments are directories. If you use glob patterns or file names, then `--ext` is ignored.
 
-For example, `eslint lib/* --ext .js` will match all files within the `lib/` directory, regardless of extension.
+For example, `npx eslint lib/* --ext .js` will match all files within the `lib/` directory, regardless of extension.
 
 #### `--global`
 
@@ -153,8 +157,8 @@ This option defines global variables so that they will not be flagged as undefin
 
 Examples:
 
-    eslint --global require,exports:true file.js
-    eslint --global require --global exports:true
+    npx eslint --global require,exports:true file.js
+    npx eslint --global require --global exports:true
 
 #### `--parser`
 
@@ -166,8 +170,8 @@ This option allows you to specify parser options to be used by ESLint. Note that
 
 Examples:
 
-    echo '3 ** 4' | eslint --stdin --parser-options=ecmaVersion:6 # will fail with a parsing error
-    echo '3 ** 4' | eslint --stdin --parser-options=ecmaVersion:7 # succeeds, yay!
+    echo '3 ** 4' | npx eslint --stdin --parser-options=ecmaVersion:6 # will fail with a parsing error
+    echo '3 ** 4' | npx eslint --stdin --parser-options=ecmaVersion:7 # succeeds, yay!
 
 #### `--resolve-plugins-relative-to`
 
@@ -186,8 +190,8 @@ Before using the plugin, you have to install it using npm.
 
 Examples:
 
-    eslint --plugin jquery file.js
-    eslint --plugin eslint-plugin-mocha file.js
+    npx eslint --plugin jquery file.js
+    npx eslint --plugin eslint-plugin-mocha file.js
 
 #### `--rule`
 
@@ -197,9 +201,9 @@ If the rule is defined within a plugin, you have to prefix the rule ID with the
 
 Examples:
 
-    eslint --rule 'quotes: [error, double]'
-    eslint --rule 'guard-for-in: error' --rule 'brace-style: [error, 1tbs]'
-    eslint --rule 'jquery/dollar-sign: error'
+    npx eslint --rule 'quotes: [error, double]'
+    npx eslint --rule 'guard-for-in: error' --rule 'brace-style: [error, 1tbs]'
+    npx eslint --rule 'jquery/dollar-sign: error'
 
 #### `--rulesdir`
 
@@ -209,11 +213,11 @@ This option allows you to specify another directory from which to load rules fil
 
 Example:
 
-    eslint --rulesdir my-rules/ file.js
+    npx eslint --rulesdir my-rules/ file.js
 
 The rules in your custom rules directory must follow the same format as bundled rules to work properly. You can also specify multiple locations for custom rules by including multiple `--rulesdir` options:
 
-    eslint --rulesdir my-rules/ --rulesdir my-other-rules/ file.js
+    npx eslint --rulesdir my-rules/ --rulesdir my-other-rules/ file.js
 
 Note that, as with core rules and plugin rules, you still need to enable the rules in configuration or via the `--rule` CLI option in order to actually run those rules during linting. Specifying a rules directory with `--rulesdir` does not automatically enable the rules within that directory.
 
@@ -234,8 +238,8 @@ This option has the same effect as `--fix` with one difference: the fixes are no
 
 Because the default formatter does not output the fixed code, you'll have to use another one (e.g. `json`) to get the fixes. Here's an example of this pattern:
 
-```sh
-getSomeText | eslint --stdin --fix-dry-run --format=json
+```shell
+getSomeText | npx eslint --stdin --fix-dry-run --format=json
 ```
 
 This flag can be useful for integrations (e.g. editor plugins) which need to autofix text from the command line without saving it to the filesystem.
@@ -251,10 +255,10 @@ This option allows you to specify the type of fixes to apply when using either `
 
 You can specify one or more fix type on the command line. Here are some examples:
 
-```sh
-eslint --fix --fix-type suggestion .
-eslint --fix --fix-type suggestion --fix-type problem .
-eslint --fix --fix-type suggestion,layout .
+```shell
+npx eslint --fix --fix-type suggestion .
+npx eslint --fix --fix-type suggestion --fix-type problem .
+npx eslint --fix --fix-type suggestion,layout .
 ```
 
 This option is helpful if you are using another program to format your code but you would still like ESLint to apply other types of fixes.
@@ -267,8 +271,8 @@ This option allows you to specify the file to use as your `.eslintignore`. By de
 
 Example:
 
-    eslint --ignore-path tmp/.eslintignore file.js
-    eslint --ignore-path .gitignore file.js
+    npx eslint --ignore-path tmp/.eslintignore file.js
+    npx eslint --ignore-path .gitignore file.js
 
 #### `--no-ignore`
 
@@ -276,7 +280,7 @@ Disables excluding of files from `.eslintignore`, `--ignore-path`, `--ignore-pat
 
 Example:
 
-    eslint --no-ignore file.js
+    npx eslint --no-ignore file.js
 
 #### `--ignore-pattern`
 
@@ -284,7 +288,7 @@ This option allows you to specify patterns of files to ignore (in addition to th
 
 Example:
 
-    eslint --ignore-pattern '/lib/' --ignore-pattern '/src/vendor/*' .
+    npx eslint --ignore-pattern '/lib/' --ignore-pattern '/src/vendor/*' .
 
 ### Using stdin
 
@@ -294,7 +298,7 @@ This option tells ESLint to read and lint source code from STDIN instead of from
 
 Example:
 
-    cat myfile.js | eslint --stdin
+    cat myfile.js | npx eslint --stdin
 
 #### `--stdin-filename`
 
@@ -302,7 +306,7 @@ This option allows you to specify a filename to process STDIN as. This is useful
 
 Example
 
-    cat myfile.js | eslint --stdin --stdin-filename=myfile.js
+    cat myfile.js | npx eslint --stdin --stdin-filename=myfile.js
 
 ### Handling warnings
 
@@ -312,7 +316,7 @@ This option allows you to disable reporting on warnings. If you enable this opti
 
 Example:
 
-    eslint --quiet file.js
+    npx eslint --quiet file.js
 
 #### `--max-warnings`
 
@@ -322,7 +326,7 @@ Normally, if ESLint runs and finds no errors (only warnings), it will exit with
 
 Example:
 
-    eslint --max-warnings 10 file.js
+    npx eslint --max-warnings 10 file.js
 
 ### Output
 
@@ -332,7 +336,7 @@ Enable report to be written to a file.
 
 Example:
 
-    eslint -o ./test/test.html
+    npx eslint -o ./test/test.html
 
 When specified, the given format is output into the provided file name.
 
@@ -353,13 +357,13 @@ This option specifies the output format for the console. Possible formats are:
 
 Example:
 
-    eslint -f compact file.js
+    npx eslint -f compact file.js
 
 You can also use a custom formatter from the command line by specifying a path to the custom formatter file.
 
 Example:
 
-    eslint -f ./customformat.js file.js
+    npx eslint -f ./customformat.js file.js
 
 An npm-installed formatter is resolved with or without `eslint-formatter-` prefix.
 
@@ -367,14 +371,14 @@ Example:
 
     npm install eslint-formatter-pretty
 
-    eslint -f pretty file.js
+    npx eslint -f pretty file.js
 
     // equivalent:
-    eslint -f eslint-formatter-pretty file.js
+    npx eslint -f eslint-formatter-pretty file.js
 
 When specified, the given format is output to the console. If you'd like to save that output into a file, you can do so on the command line like so:
 
-    eslint -f compact file.js > results.txt
+    npx eslint -f compact file.js > results.txt
 
 This saves the output into the `results.txt` file.
 
@@ -384,8 +388,8 @@ This option forces the enabling/disabling of colorized output. You can use this
 
 Examples:
 
-    eslint --color file.js | cat
-    eslint --no-color file.js
+    npx eslint --color file.js | cat
+    npx eslint --no-color file.js
 
 ### Inline configuration comments
 
@@ -405,7 +409,7 @@ config without files modifying it. All inline config comments are ignored, e.g.:
 
 Example:
 
-    eslint --no-inline-config file.js
+    npx eslint --no-inline-config file.js
 
 #### `--report-unused-disable-directives`
 
@@ -415,7 +419,7 @@ This option causes ESLint to report directive comments like `// eslint-disable-l
 
 Example:
 
-    eslint --report-unused-disable-directives file.js
+    npx eslint --report-unused-disable-directives file.js
 
 ### Caching
 
@@ -441,7 +445,7 @@ If a directory is specified, a cache file will be created inside the specified f
 
 Example:
 
-    eslint "src/**/*.js" --cache --cache-location "/Users/user/.eslintcache/"
+    npx eslint "src/**/*.js" --cache --cache-location "/Users/user/.eslintcache/"
 
 #### `--cache-strategy`
 
@@ -451,13 +455,13 @@ The `content` strategy can be useful in cases where the modification time of you
 
 Example:
 
-    eslint "src/**/*.js" --cache --cache-strategy content
+    npx eslint "src/**/*.js" --cache --cache-strategy content
 
 ### Miscellaneous
 
 #### `--init`
 
-This option will start config initialization wizard. It's designed to help new users quickly create .eslintrc file by answering a few questions, choosing a popular style guide, or inspecting your source files and attempting to automatically generate a suitable configuration.
+This option will run `npm init @eslint/config` to start config initialization wizard. It's designed to help new users quickly create .eslintrc file by answering a few questions, choosing a popular style guide.
 
 The resulting configuration file will be created in the current directory.
 
@@ -476,7 +480,7 @@ This option causes ESLint to exit with exit code 2 if one or more fatal parsing
 #### `--debug`
 
 This option outputs debugging information to the console. This information is useful when you're seeing a problem and having a hard time pinpointing it. The ESLint team may ask for this debugging information to help solve bugs.
-Add this flag to an ESLint command line invocation in order to get extra debug information as the command is run (e.g. `eslint --debug test.js` and `eslint test.js --debug` are equivalent)
+Add this flag to an ESLint command line invocation in order to get extra debug information as the command is run (e.g. `npx eslint --debug test.js` and `npx eslint test.js --debug` are equivalent)
 
 #### `-h`, `--help`
 
@@ -492,7 +496,7 @@ This option outputs the configuration to be used for the file passed. When prese
 
 Example:
 
-    eslint --print-config file.js
+    npx eslint --print-config file.js
 
 ## Ignoring files from linting
 
diff --git a/docs/user-guide/configuring/configuration-files.md b/docs/user-guide/configuring/configuration-files.md
index 3156a99e3..cc1d5bf3c 100644
--- a/docs/user-guide/configuring/configuration-files.md
+++ b/docs/user-guide/configuring/configuration-files.md
@@ -232,7 +232,7 @@ A [sharable configuration](https://eslint.org/docs/developer-guide/shareable-con
 
 The `extends` property value can omit the `eslint-config-` prefix of the package name.
 
-The `eslint --init` command can create a configuration so you can extend a popular style guide (for example, `eslint-config-standard`).
+The `npm init @eslint/config` command can create a configuration so you can extend a popular style guide (for example, `eslint-config-standard`).
 
 Example of a configuration file in YAML format:
 
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index cf808ddc0..eb0f34d65 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -12,7 +12,7 @@ Prerequisites: [Node.js](https://nodejs.org/en/) (`^12.22.0`, `^14.17.0`, or `>=
 
 You can install ESLint using npm or yarn:
 
-```sh
+```shell
 npm install eslint --save-dev
 
 # or
@@ -20,21 +20,21 @@ npm install eslint --save-dev
 yarn add eslint --dev
 ```
 
-You should then set up a configuration file, and the easiest way to do that is to use the `--init` flag:
+You should then set up a configuration file, and the easiest way to do that is:
 
-```sh
-$ npx eslint --init
+```shell
+$ npm init @eslint/config
 
 # or
 
-$ yarn run eslint --init
+$ yarn create @eslint/config
 ```
 
-**Note:** `--init` assumes you have a `package.json` file already. If you don't, make sure to run `npm init` or `yarn init` beforehand.
+**Note:** `npm init @eslint/config` assumes you have a `package.json` file already. If you don't, make sure to run `npm init` or `yarn init` beforehand.
 
 After that, you can run ESLint on any file or directory like this:
 
-```sh
+```shell
 $ npx eslint yourfile.js
 
 # or
@@ -48,7 +48,7 @@ It is also possible to install ESLint globally rather than locally (using `npm i
 
 **Note:** If you are coming from a version before 1.0.0 please see the [migration guide](migrating-to-1.0.0.md).
 
-After running `eslint --init`, you'll have a `.eslintrc.{js,yml,json}` file in your directory. In it, you'll see some rules configured like this:
+After running `npm init @eslint/config`, you'll have a `.eslintrc.{js,yml,json}` file in your directory. In it, you'll see some rules configured like this:
 
 ```json
 {
diff --git a/docs/user-guide/migrating-from-jscs.md b/docs/user-guide/migrating-from-jscs.md
index e05ee70d6..7c79486e5 100644
--- a/docs/user-guide/migrating-from-jscs.md
+++ b/docs/user-guide/migrating-from-jscs.md
@@ -15,7 +15,7 @@ Before beginning the process of migrating to ESLint, it's helpful to understand
 
 To install Polyjuice:
 
-```sh
+```shell
 $ npm install -g polyjuice
 ```
 
@@ -23,7 +23,7 @@ Polyjuice works with JSON configuration files, so if you're using a JavaScript o
 
 To convert your configuration file, pass in the location of your `.jscs.json` file using the `--jscs` flag:
 
-```sh
+```shell
 $ polyjuice --jscs .jscsrc.json > .eslintrc.json
 ```
 
@@ -31,7 +31,7 @@ This creates a `.eslintrc.json` with the equivalent rules from `.jscsrc.json`.
 
 If you have multiple `.jscsrc.json` files, you can pass them all and Polyjuice will combine them into one `.eslintrc.json` file:
 
-```sh
+```shell
 $ polyjuice --jscs .jscsrc.json ./foo/.jscsrc.json > .eslintrc.json
 ```
 
@@ -41,8 +41,8 @@ $ polyjuice --jscs .jscsrc.json ./foo/.jscsrc.json > .eslintrc.json
 
 If you don't want to convert your JSCS configuration directly into an ESLint configuration, then you can use ESLint's built-in wizard to get you started. Just run:
 
-```sh
-$ eslint --init
+```shell
+$ npm init @eslint/config
 ```
 
 You'll be guided through a series of questions that will help you setup a basic configuration file to get you started.
@@ -74,7 +74,7 @@ As an example, suppose that you are using the `airbnb` preset, so your `.jscsrc`
 
 In order to get the same functionality in ESLint, you would first need to install the `eslint-config-airbnb` shareable config package:
 
-```sh
+```shell
 $ npm install eslint-config-airbnb-base --save-dev
 ```
 
@@ -110,13 +110,13 @@ Both JSCS and ESLint have command line arguments corresponding to many of their
 
 JSCS uses the `--fix` option to apply automatic fixes to code:
 
-```sh
+```shell
 $ jscs --fix file.js
 ```
 
 ESLint has the same option:
 
-```sh
+```shell
 $ eslint --fix file.js
 ```
 
@@ -124,13 +124,13 @@ $ eslint --fix file.js
 
 The JSCS `--auto-configure` option created a configuration based on what it found in a given file:
 
-```sh
+```shell
 $ jscs --auto-configure file.js
 ```
 
 In ESLint, there's a similar option when you use `--init`. Just select "Inspect your JavaScript file(s)":
 
-```sh
+```shell
 $ eslint --init
 ? How would you like to configure ESLint? (Use arrow keys)
 > Answer questions about your style
@@ -142,14 +142,14 @@ $ eslint --init
 
 JSCS allows you to specify a configuration file to use on the command line using either `--config` or `-c`, such as:
 
-```sh
+```shell
 $ jscs --config myconfig.json file.js
 $ jscs -c myconfig.json file.js
 ```
 
 Both flags are also supported by ESLint:
 
-```sh
+```shell
 $ eslint --config myconfig.json file.js
 $ eslint -c myconfig.json file.js
 ```
@@ -158,12 +158,12 @@ $ eslint -c myconfig.json file.js
 
 In JSCS, you can pipe code in like this:
 
-```sh
+```shell
 $ cat file.js | jscs
 ```
 
 In ESLint, you can also pipe in code, but you need to use the `--stdin` flag:
 
-```sh
+```shell
 $ cat file.js | eslint --stdin
 ```
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index e3647018d..0aff182f0 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -92,6 +92,7 @@ const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]);
  * @property {string} filePath The path to the file that was linted.
  * @property {LintMessage[]} messages All of the messages for the result.
  * @property {number} errorCount Number of errors for the result.
+ * @property {number} fatalErrorCount Number of fatal errors for the result.
  * @property {number} warningCount Number of warnings for the result.
  * @property {number} fixableErrorCount Number of fixable errors for the result.
  * @property {number} fixableWarningCount Number of fixable warnings for the result.
@@ -104,6 +105,7 @@ const validFixTypes = new Set(["directive", "problem", "suggestion", "layout"]);
  * @typedef {Object} LintReport
  * @property {LintResult[]} results All of the result.
  * @property {number} errorCount Number of errors for the result.
+ * @property {number} fatalErrorCount Number of fatal errors for the result.
  * @property {number} warningCount Number of warnings for the result.
  * @property {number} fixableErrorCount Number of fixable errors for the result.
  * @property {number} fixableWarningCount Number of fixable warnings for the result.
@@ -308,6 +310,7 @@ function createIgnoreResult(filePath, baseDir) {
             }
         ],
         errorCount: 0,
+        fatalErrorCount: 0,
         warningCount: 1,
         fixableErrorCount: 0,
         fixableWarningCount: 0
@@ -408,7 +411,7 @@ function isErrorMessage(message) {
  * a directory or looks like a directory (ends in `path.sep`), in which case the file
  * name will be the `cacheFile/.cache_hashOfCWD`
  *
- * if cacheFile points to a file or looks like a file then in will just use that file
+ * if cacheFile points to a file or looks like a file then it will just use that file
  * @param {string} cacheFile The name of file to be used to store the cache
  * @param {string} cwd Current working directory
  * @returns {string} the resolved path to the cache file
diff --git a/lib/eslint/eslint.js b/lib/eslint/eslint.js
index 6274772ad..ee6b2ef45 100644
--- a/lib/eslint/eslint.js
+++ b/lib/eslint/eslint.js
@@ -79,6 +79,7 @@ const { version } = require("../../package.json");
  * @property {string} filePath The path to the file that was linted.
  * @property {LintMessage[]} messages All of the messages for the result.
  * @property {number} errorCount Number of errors for the result.
+ * @property {number} fatalErrorCount Number of fatal errors for the result.
  * @property {number} warningCount Number of warnings for the result.
  * @property {number} fixableErrorCount Number of fixable errors for the result.
  * @property {number} fixableWarningCount Number of fixable warnings for the result.
diff --git a/lib/init/autoconfig.js b/lib/init/autoconfig.js
deleted file mode 100644
index ea2523421..000000000
--- a/lib/init/autoconfig.js
+++ /dev/null
@@ -1,351 +0,0 @@
-/**
- * @fileoverview Used for creating a suggested configuration based on project code.
- * @author Ian VanSchooten
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const equal = require("fast-deep-equal"),
-    recConfig = require("../../conf/eslint-recommended"),
-    {
-        Legacy: {
-            ConfigOps
-        }
-    } = require("@eslint/eslintrc"),
-    { Linter } = require("../linter"),
-    configRule = require("./config-rule");
-
-const debug = require("debug")("eslint:autoconfig");
-const linter = new Linter();
-
-//------------------------------------------------------------------------------
-// Data
-//------------------------------------------------------------------------------
-
-const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
-    RECOMMENDED_CONFIG_NAME = "eslint:recommended";
-
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
-
-/**
- * Information about a rule configuration, in the context of a Registry.
- * @typedef {Object}     registryItem
- * @property {ruleConfig} config A valid configuration for the rule
- * @property {number} specificity The number of elements in the ruleConfig array
- * @property {number} errorCount The number of errors encountered when linting with the config
- */
-
-/**
- * This callback is used to measure execution status in a progress bar
- * @callback progressCallback
- * @param {number} The total number of times the callback will be called.
- */
-
-/**
- * Create registryItems for rules
- * @param {rulesConfig} rulesConfig Hash of rule names and arrays of ruleConfig items
- * @returns {Object} registryItems for each rule in provided rulesConfig
- */
-function makeRegistryItems(rulesConfig) {
-    return Object.keys(rulesConfig).reduce((accumulator, ruleId) => {
-        accumulator[ruleId] = rulesConfig[ruleId].map(config => ({
-            config,
-            specificity: config.length || 1,
-            errorCount: void 0
-        }));
-        return accumulator;
-    }, {});
-}
-
-/**
- * Creates an object in which to store rule configs and error counts
- *
- * Unless a rulesConfig is provided at construction, the registry will not contain
- * any rules, only methods.  This will be useful for building up registries manually.
- *
- * Registry class
- */
-class Registry {
-
-    /**
-     * @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations
-     */
-    constructor(rulesConfig) {
-        this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {};
-    }
-
-    /**
-     * Populate the registry with core rule configs.
-     *
-     * It will set the registry's `rule` property to an object having rule names
-     * as keys and an array of registryItems as values.
-     * @returns {void}
-     */
-    populateFromCoreRules() {
-        const rulesConfig = configRule.createCoreRuleConfigs(/* noDeprecated = */ true);
-
-        this.rules = makeRegistryItems(rulesConfig);
-    }
-
-    /**
-     * Creates sets of rule configurations which can be used for linting
-     * and initializes registry errors to zero for those configurations (side effect).
-     *
-     * This combines as many rules together as possible, such that the first sets
-     * in the array will have the highest number of rules configured, and later sets
-     * will have fewer and fewer, as not all rules have the same number of possible
-     * configurations.
-     *
-     * The length of the returned array will be <= MAX_CONFIG_COMBINATIONS.
-     * @returns {Object[]} "rules" configurations to use for linting
-     */
-    buildRuleSets() {
-        let idx = 0;
-        const ruleIds = Object.keys(this.rules),
-            ruleSets = [];
-
-        /**
-         * Add a rule configuration from the registry to the ruleSets
-         *
-         * This is broken out into its own function so that it doesn't need to be
-         * created inside of the while loop.
-         * @param {string} rule The ruleId to add.
-         * @returns {void}
-         */
-        const addRuleToRuleSet = function(rule) {
-
-            /*
-             * This check ensures that there is a rule configuration and that
-             * it has fewer than the max combinations allowed.
-             * If it has too many configs, we will only use the most basic of
-             * the possible configurations.
-             */
-            const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS);
-
-            if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) {
-
-                /*
-                 * If the rule has too many possible combinations, only take
-                 * simple ones, avoiding objects.
-                 */
-                if (!hasFewCombos && typeof this.rules[rule][idx].config[1] === "object") {
-                    return;
-                }
-
-                ruleSets[idx] = ruleSets[idx] || {};
-                ruleSets[idx][rule] = this.rules[rule][idx].config;
-
-                /*
-                 * Initialize errorCount to zero, since this is a config which
-                 * will be linted.
-                 */
-                this.rules[rule][idx].errorCount = 0;
-            }
-        }.bind(this);
-
-        while (ruleSets.length === idx) {
-            ruleIds.forEach(addRuleToRuleSet);
-            idx += 1;
-        }
-
-        return ruleSets;
-    }
-
-    /**
-     * Remove all items from the registry with a non-zero number of errors
-     *
-     * Note: this also removes rule configurations which were not linted
-     * (meaning, they have an undefined errorCount).
-     * @returns {void}
-     */
-    stripFailingConfigs() {
-        const ruleIds = Object.keys(this.rules),
-            newRegistry = new Registry();
-
-        newRegistry.rules = Object.assign({}, this.rules);
-        ruleIds.forEach(ruleId => {
-            const errorFreeItems = newRegistry.rules[ruleId].filter(registryItem => (registryItem.errorCount === 0));
-
-            if (errorFreeItems.length > 0) {
-                newRegistry.rules[ruleId] = errorFreeItems;
-            } else {
-                delete newRegistry.rules[ruleId];
-            }
-        });
-
-        return newRegistry;
-    }
-
-    /**
-     * Removes rule configurations which were not included in a ruleSet
-     * @returns {void}
-     */
-    stripExtraConfigs() {
-        const ruleIds = Object.keys(this.rules),
-            newRegistry = new Registry();
-
-        newRegistry.rules = Object.assign({}, this.rules);
-        ruleIds.forEach(ruleId => {
-            newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(registryItem => (typeof registryItem.errorCount !== "undefined"));
-        });
-
-        return newRegistry;
-    }
-
-    /**
-     * Creates a registry of rules which had no error-free configs.
-     * The new registry is intended to be analyzed to determine whether its rules
-     * should be disabled or set to warning.
-     * @returns {Registry} A registry of failing rules.
-     */
-    getFailingRulesRegistry() {
-        const ruleIds = Object.keys(this.rules),
-            failingRegistry = new Registry();
-
-        ruleIds.forEach(ruleId => {
-            const failingConfigs = this.rules[ruleId].filter(registryItem => (registryItem.errorCount > 0));
-
-            if (failingConfigs && failingConfigs.length === this.rules[ruleId].length) {
-                failingRegistry.rules[ruleId] = failingConfigs;
-            }
-        });
-
-        return failingRegistry;
-    }
-
-    /**
-     * Create an eslint config for any rules which only have one configuration
-     * in the registry.
-     * @returns {Object} An eslint config with rules section populated
-     */
-    createConfig() {
-        const ruleIds = Object.keys(this.rules),
-            config = { rules: {} };
-
-        ruleIds.forEach(ruleId => {
-            if (this.rules[ruleId].length === 1) {
-                config.rules[ruleId] = this.rules[ruleId][0].config;
-            }
-        });
-
-        return config;
-    }
-
-    /**
-     * Return a cloned registry containing only configs with a desired specificity
-     * @param {number} specificity Only keep configs with this specificity
-     * @returns {Registry} A registry of rules
-     */
-    filterBySpecificity(specificity) {
-        const ruleIds = Object.keys(this.rules),
-            newRegistry = new Registry();
-
-        newRegistry.rules = Object.assign({}, this.rules);
-        ruleIds.forEach(ruleId => {
-            newRegistry.rules[ruleId] = this.rules[ruleId].filter(registryItem => (registryItem.specificity === specificity));
-        });
-
-        return newRegistry;
-    }
-
-    /**
-     * Lint SourceCodes against all configurations in the registry, and record results
-     * @param {Object[]} sourceCodes SourceCode objects for each filename
-     * @param {Object} config ESLint config object
-     * @param {progressCallback} [cb] Optional callback for reporting execution status
-     * @returns {Registry} New registry with errorCount populated
-     */
-    lintSourceCode(sourceCodes, config, cb) {
-        let lintedRegistry = new Registry();
-
-        lintedRegistry.rules = Object.assign({}, this.rules);
-
-        const ruleSets = lintedRegistry.buildRuleSets();
-
-        lintedRegistry = lintedRegistry.stripExtraConfigs();
-
-        debug("Linting with all possible rule combinations");
-
-        const filenames = Object.keys(sourceCodes);
-        const totalFilesLinting = filenames.length * ruleSets.length;
-
-        filenames.forEach(filename => {
-            debug(`Linting file: ${filename}`);
-
-            let ruleSetIdx = 0;
-
-            ruleSets.forEach(ruleSet => {
-                const lintConfig = Object.assign({}, config, { rules: ruleSet });
-                const lintResults = linter.verify(sourceCodes[filename], lintConfig);
-
-                lintResults.forEach(result => {
-
-                    /*
-                     * It is possible that the error is from a configuration comment
-                     * in a linted file, in which case there may not be a config
-                     * set in this ruleSetIdx.
-                     * (https://github.com/eslint/eslint/issues/5992)
-                     * (https://github.com/eslint/eslint/issues/7860)
-                     */
-                    if (
-                        lintedRegistry.rules[result.ruleId] &&
-                        lintedRegistry.rules[result.ruleId][ruleSetIdx]
-                    ) {
-                        lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1;
-                    }
-                });
-
-                ruleSetIdx += 1;
-
-                if (cb) {
-                    cb(totalFilesLinting); // eslint-disable-line node/callback-return -- End of function
-                }
-            });
-
-            // Deallocate for GC
-            sourceCodes[filename] = null;
-        });
-
-        return lintedRegistry;
-    }
-}
-
-/**
- * Extract rule configuration into eslint:recommended where possible.
- *
- * This will return a new config with `["extends": [ ..., "eslint:recommended"]` and
- * only the rules which have configurations different from the recommended config.
- * @param {Object} config config object
- * @returns {Object} config object using `"extends": ["eslint:recommended"]`
- */
-function extendFromRecommended(config) {
-    const newConfig = Object.assign({}, config);
-
-    ConfigOps.normalizeToStrings(newConfig);
-
-    const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
-
-    recRules.forEach(ruleId => {
-        if (equal(recConfig.rules[ruleId], newConfig.rules[ruleId])) {
-            delete newConfig.rules[ruleId];
-        }
-    });
-    newConfig.extends.unshift(RECOMMENDED_CONFIG_NAME);
-    return newConfig;
-}
-
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-module.exports = {
-    Registry,
-    extendFromRecommended
-};
diff --git a/lib/init/config-file.js b/lib/init/config-file.js
deleted file mode 100644
index 9eb10fab3..000000000
--- a/lib/init/config-file.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * @fileoverview Helper to locate and load configuration files.
- * @author Nicholas C. Zakas
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const fs = require("fs"),
-    path = require("path"),
-    stringify = require("json-stable-stringify-without-jsonify");
-
-const debug = require("debug")("eslint:config-file");
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Determines sort order for object keys for json-stable-stringify
- *
- * see: https://github.com/samn/json-stable-stringify#cmp
- * @param {Object} a The first comparison object ({key: akey, value: avalue})
- * @param {Object} b The second comparison object ({key: bkey, value: bvalue})
- * @returns {number} 1 or -1, used in stringify cmp method
- */
-function sortByKey(a, b) {
-    return a.key > b.key ? 1 : -1;
-}
-
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
-
-/**
- * Writes a configuration file in JSON format.
- * @param {Object} config The configuration object to write.
- * @param {string} filePath The filename to write to.
- * @returns {void}
- * @private
- */
-function writeJSONConfigFile(config, filePath) {
-    debug(`Writing JSON config file: ${filePath}`);
-
-    const content = `${stringify(config, { cmp: sortByKey, space: 4 })}\n`;
-
-    fs.writeFileSync(filePath, content, "utf8");
-}
-
-/**
- * Writes a configuration file in YAML format.
- * @param {Object} config The configuration object to write.
- * @param {string} filePath The filename to write to.
- * @returns {void}
- * @private
- */
-function writeYAMLConfigFile(config, filePath) {
-    debug(`Writing YAML config file: ${filePath}`);
-
-    // lazy load YAML to improve performance when not used
-    const yaml = require("js-yaml");
-
-    const content = yaml.dump(config, { sortKeys: true });
-
-    fs.writeFileSync(filePath, content, "utf8");
-}
-
-/**
- * Writes a configuration file in JavaScript format.
- * @param {Object} config The configuration object to write.
- * @param {string} filePath The filename to write to.
- * @throws {Error} If an error occurs linting the config file contents.
- * @returns {void}
- * @private
- */
-function writeJSConfigFile(config, filePath) {
-    debug(`Writing JS config file: ${filePath}`);
-
-    let contentToWrite;
-    const stringifiedContent = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};\n`;
-
-    try {
-        const { CLIEngine } = require("../cli-engine");
-        const linter = new CLIEngine({
-            baseConfig: config,
-            fix: true,
-            useEslintrc: false
-        });
-        const report = linter.executeOnText(stringifiedContent);
-
-        contentToWrite = report.results[0].output || stringifiedContent;
-    } catch (e) {
-        debug("Error linting JavaScript config file, writing unlinted version");
-        const errorMessage = e.message;
-
-        contentToWrite = stringifiedContent;
-        e.message = "An error occurred while generating your JavaScript config file. ";
-        e.message += "A config file was still generated, but the config file itself may not follow your linting rules.";
-        e.message += `\nError: ${errorMessage}`;
-        throw e;
-    } finally {
-        fs.writeFileSync(filePath, contentToWrite, "utf8");
-    }
-}
-
-/**
- * Writes a configuration file.
- * @param {Object} config The configuration object to write.
- * @param {string} filePath The filename to write to.
- * @returns {void}
- * @throws {Error} When an unknown file type is specified.
- * @private
- */
-function write(config, filePath) {
-    switch (path.extname(filePath)) {
-        case ".js":
-        case ".cjs":
-            writeJSConfigFile(config, filePath);
-            break;
-
-        case ".json":
-            writeJSONConfigFile(config, filePath);
-            break;
-
-        case ".yaml":
-        case ".yml":
-            writeYAMLConfigFile(config, filePath);
-            break;
-
-        default:
-            throw new Error("Can't write to unknown file type.");
-    }
-}
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-module.exports = {
-    write
-};
diff --git a/lib/init/config-initializer.js b/lib/init/config-initializer.js
deleted file mode 100644
index 3c244b7bc..000000000
--- a/lib/init/config-initializer.js
+++ /dev/null
@@ -1,709 +0,0 @@
-/**
- * @fileoverview Config initialization wizard.
- * @author Ilya Volodin
- */
-
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const util = require("util"),
-    path = require("path"),
-    fs = require("fs"),
-    enquirer = require("enquirer"),
-    ProgressBar = require("progress"),
-    semver = require("semver"),
-    espree = require("espree"),
-    recConfig = require("../../conf/eslint-recommended"),
-    {
-        Legacy: {
-            ConfigOps,
-            naming
-        }
-    } = require("@eslint/eslintrc"),
-    log = require("../shared/logging"),
-    ModuleResolver = require("../shared/relative-module-resolver"),
-    autoconfig = require("./autoconfig.js"),
-    ConfigFile = require("./config-file"),
-    npmUtils = require("./npm-utils"),
-    { getSourceCodeOfFiles } = require("./source-code-utils");
-
-const debug = require("debug")("eslint:config-initializer");
-
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
-
-/* istanbul ignore next: hard to test fs function */
-/**
- * Create .eslintrc file in the current working directory
- * @param {Object} config object that contains user's answers
- * @param {string} format The file format to write to.
- * @returns {void}
- */
-function writeFile(config, format) {
-
-    // default is .js
-    let extname = ".js";
-
-    if (format === "YAML") {
-        extname = ".yml";
-    } else if (format === "JSON") {
-        extname = ".json";
-    } else if (format === "JavaScript") {
-        const pkgJSONPath = npmUtils.findPackageJson();
-
-        if (pkgJSONPath) {
-            const pkgJSONContents = JSON.parse(fs.readFileSync(pkgJSONPath, "utf8"));
-
-            if (pkgJSONContents.type === "module") {
-                extname = ".cjs";
-            }
-        }
-    }
-
-    const installedESLint = config.installedESLint;
-
-    delete config.installedESLint;
-
-    ConfigFile.write(config, `./.eslintrc${extname}`);
-    log.info(`Successfully created .eslintrc${extname} file in ${process.cwd()}`);
-
-    if (installedESLint) {
-        log.info("ESLint was installed locally. We recommend using this local copy instead of your globally-installed copy.");
-    }
-}
-
-/**
- * Get the peer dependencies of the given module.
- * This adds the gotten value to cache at the first time, then reuses it.
- * In a process, this function is called twice, but `npmUtils.fetchPeerDependencies` needs to access network which is relatively slow.
- * @param {string} moduleName The module name to get.
- * @returns {Object} The peer dependencies of the given module.
- * This object is the object of `peerDependencies` field of `package.json`.
- * Returns null if npm was not found.
- */
-function getPeerDependencies(moduleName) {
-    let result = getPeerDependencies.cache.get(moduleName);
-
-    if (!result) {
-        log.info(`Checking peerDependencies of ${moduleName}`);
-
-        result = npmUtils.fetchPeerDependencies(moduleName);
-        getPeerDependencies.cache.set(moduleName, result);
-    }
-
-    return result;
-}
-getPeerDependencies.cache = new Map();
-
-/**
- * Return necessary plugins, configs, parsers, etc. based on the config
- * @param {Object} config config object
- * @param {boolean} [installESLint=true] If `false` is given, it does not install eslint.
- * @returns {string[]} An array of modules to be installed.
- */
-function getModulesList(config, installESLint) {
-    const modules = {};
-
-    // Create a list of modules which should be installed based on config
-    if (config.plugins) {
-        for (const plugin of config.plugins) {
-            const moduleName = naming.normalizePackageName(plugin, "eslint-plugin");
-
-            modules[moduleName] = "latest";
-        }
-    }
-    if (config.extends) {
-        const extendList = Array.isArray(config.extends) ? config.extends : [config.extends];
-
-        for (const extend of extendList) {
-            if (extend.startsWith("eslint:") || extend.startsWith("plugin:")) {
-                continue;
-            }
-            const moduleName = naming.normalizePackageName(extend, "eslint-config");
-
-            modules[moduleName] = "latest";
-            Object.assign(
-                modules,
-                getPeerDependencies(`${moduleName}@latest`)
-            );
-        }
-    }
-
-    const parser = config.parser || (config.parserOptions && config.parserOptions.parser);
-
-    if (parser) {
-        modules[parser] = "latest";
-    }
-
-    if (installESLint === false) {
-        delete modules.eslint;
-    } else {
-        const installStatus = npmUtils.checkDevDeps(["eslint"]);
-
-        // Mark to show messages if it's new installation of eslint.
-        if (installStatus.eslint === false) {
-            log.info("Local ESLint installation not found.");
-            modules.eslint = modules.eslint || "latest";
-            config.installedESLint = true;
-        }
-    }
-
-    return Object.keys(modules).map(name => `${name}@${modules[name]}`);
-}
-
-/**
- * Set the `rules` of a config by examining a user's source code
- *
- * Note: This clones the config object and returns a new config to avoid mutating
- * the original config parameter.
- * @param {Object} answers answers received from enquirer
- * @param {Object} config config object
- * @throws {Error} If source code retrieval fails or source code file count is 0.
- * @returns {Object} config object with configured rules
- */
-function configureRules(answers, config) {
-    const BAR_TOTAL = 20,
-        BAR_SOURCE_CODE_TOTAL = 4,
-        newConfig = Object.assign({}, config),
-        disabledConfigs = {};
-    let sourceCodes,
-        registry;
-
-    // Set up a progress bar, as this process can take a long time
-    const bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", {
-        width: 30,
-        total: BAR_TOTAL
-    });
-
-    bar.tick(0); // Shows the progress bar
-
-    // Get the SourceCode of all chosen files
-    const patterns = answers.patterns.split(/[\s]+/u);
-
-    try {
-        sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, total => {
-            bar.tick((BAR_SOURCE_CODE_TOTAL / total));
-        });
-    } catch (e) {
-        log.info("\n");
-        throw e;
-    }
-    const fileQty = Object.keys(sourceCodes).length;
-
-    if (fileQty === 0) {
-        log.info("\n");
-        throw new Error("Automatic Configuration failed.  No files were able to be parsed.");
-    }
-
-    // Create a registry of rule configs
-    registry = new autoconfig.Registry();
-    registry.populateFromCoreRules();
-
-    // Lint all files with each rule config in the registry
-    registry = registry.lintSourceCode(sourceCodes, newConfig, total => {
-        bar.tick((BAR_TOTAL - BAR_SOURCE_CODE_TOTAL) / total); // Subtract out ticks used at beginning
-    });
-    debug(`\nRegistry: ${util.inspect(registry.rules, { depth: null })}`);
-
-    // Create a list of recommended rules, because we don't want to disable them
-    const recRules = Object.keys(recConfig.rules).filter(ruleId => ConfigOps.isErrorSeverity(recConfig.rules[ruleId]));
-
-    // Find and disable rules which had no error-free configuration
-    const failingRegistry = registry.getFailingRulesRegistry();
-
-    Object.keys(failingRegistry.rules).forEach(ruleId => {
-
-        // If the rule is recommended, set it to error, otherwise disable it
-        disabledConfigs[ruleId] = (recRules.indexOf(ruleId) !== -1) ? 2 : 0;
-    });
-
-    // Now that we know which rules to disable, strip out configs with errors
-    registry = registry.stripFailingConfigs();
-
-    /*
-     * If there is only one config that results in no errors for a rule, we should use it.
-     * createConfig will only add rules that have one configuration in the registry.
-     */
-    const singleConfigs = registry.createConfig().rules;
-
-    /*
-     * The "sweet spot" for number of options in a config seems to be two (severity plus one option).
-     * Very often, a third option (usually an object) is available to address
-     * edge cases, exceptions, or unique situations. We will prefer to use a config with
-     * specificity of two.
-     */
-    const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
-
-    // Maybe a specific combination using all three options works
-    const specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules;
-
-    // If all else fails, try to use the default (severity only)
-    const defaultConfigs = registry.filterBySpecificity(1).createConfig().rules;
-
-    // Combine configs in reverse priority order (later take precedence)
-    newConfig.rules = Object.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs);
-
-    // Make sure progress bar has finished (floating point rounding)
-    bar.update(BAR_TOTAL);
-
-    // Log out some stats to let the user know what happened
-    const finalRuleIds = Object.keys(newConfig.rules);
-    const totalRules = finalRuleIds.length;
-    const enabledRules = finalRuleIds.filter(ruleId => (newConfig.rules[ruleId] !== 0)).length;
-    const resultMessage = [
-        `\nEnabled ${enabledRules} out of ${totalRules}`,
-        `rules based on ${fileQty}`,
-        `file${(fileQty === 1) ? "." : "s."}`
-    ].join(" ");
-
-    log.info(resultMessage);
-
-    ConfigOps.normalizeToStrings(newConfig);
-    return newConfig;
-}
-
-/**
- * process user's answers and create config object
- * @param {Object} answers answers received from enquirer
- * @returns {Object} config object
- */
-function processAnswers(answers) {
-    let config = {
-        rules: {},
-        env: {},
-        parserOptions: {},
-        extends: []
-    };
-
-    config.parserOptions.ecmaVersion = espree.latestEcmaVersion;
-    config.env.es2021 = true;
-
-    // set the module type
-    if (answers.moduleType === "esm") {
-        config.parserOptions.sourceType = "module";
-    } else if (answers.moduleType === "commonjs") {
-        config.env.commonjs = true;
-    }
-
-    // add in browser and node environments if necessary
-    answers.env.forEach(env => {
-        config.env[env] = true;
-    });
-
-    // add in library information
-    if (answers.framework === "react") {
-        config.parserOptions.ecmaFeatures = {
-            jsx: true
-        };
-        config.plugins = ["react"];
-        config.extends.push("plugin:react/recommended");
-    } else if (answers.framework === "vue") {
-        config.plugins = ["vue"];
-        config.extends.push("plugin:vue/essential");
-    }
-
-    if (answers.typescript) {
-        if (answers.framework === "vue") {
-            config.parserOptions.parser = "@typescript-eslint/parser";
-        } else {
-            config.parser = "@typescript-eslint/parser";
-        }
-
-        if (Array.isArray(config.plugins)) {
-            config.plugins.push("@typescript-eslint");
-        } else {
-            config.plugins = ["@typescript-eslint"];
-        }
-    }
-
-    // setup rules based on problems/style enforcement preferences
-    if (answers.purpose === "problems") {
-        config.extends.unshift("eslint:recommended");
-    } else if (answers.purpose === "style") {
-        if (answers.source === "prompt") {
-            config.extends.unshift("eslint:recommended");
-            config.rules.indent = ["error", answers.indent];
-            config.rules.quotes = ["error", answers.quotes];
-            config.rules["linebreak-style"] = ["error", answers.linebreak];
-            config.rules.semi = ["error", answers.semi ? "always" : "never"];
-        } else if (answers.source === "auto") {
-            config = configureRules(answers, config);
-            config = autoconfig.extendFromRecommended(config);
-        }
-    }
-    if (answers.typescript && config.extends.includes("eslint:recommended")) {
-        config.extends.push("plugin:@typescript-eslint/recommended");
-    }
-
-    // normalize extends
-    if (config.extends.length === 0) {
-        delete config.extends;
-    } else if (config.extends.length === 1) {
-        config.extends = config.extends[0];
-    }
-
-    ConfigOps.normalizeToStrings(config);
-    return config;
-}
-
-/**
- * Get the version of the local ESLint.
- * @returns {string|null} The version. If the local ESLint was not found, returns null.
- */
-function getLocalESLintVersion() {
-    try {
-        const eslintPath = ModuleResolver.resolve("eslint", path.join(process.cwd(), "__placeholder__.js"));
-        const eslint = require(eslintPath);
-
-        return eslint.linter.version || null;
-    } catch {
-        return null;
-    }
-}
-
-/**
- * Get the shareable config name of the chosen style guide.
- * @param {Object} answers The answers object.
- * @returns {string} The shareable config name.
- */
-function getStyleGuideName(answers) {
-    if (answers.styleguide === "airbnb" && answers.framework !== "react") {
-        return "airbnb-base";
-    }
-    return answers.styleguide;
-}
-
-/**
- * Check whether the local ESLint version conflicts with the required version of the chosen shareable config.
- * @param {Object} answers The answers object.
- * @returns {boolean} `true` if the local ESLint is found then it conflicts with the required version of the chosen shareable config.
- */
-function hasESLintVersionConflict(answers) {
-
-    // Get the local ESLint version.
-    const localESLintVersion = getLocalESLintVersion();
-
-    if (!localESLintVersion) {
-        return false;
-    }
-
-    // Get the required range of ESLint version.
-    const configName = getStyleGuideName(answers);
-    const moduleName = `eslint-config-${configName}@latest`;
-    const peerDependencies = getPeerDependencies(moduleName) || {};
-    const requiredESLintVersionRange = peerDependencies.eslint;
-
-    if (!requiredESLintVersionRange) {
-        return false;
-    }
-
-    answers.localESLintVersion = localESLintVersion;
-    answers.requiredESLintVersionRange = requiredESLintVersionRange;
-
-    // Check the version.
-    if (semver.satisfies(localESLintVersion, requiredESLintVersionRange)) {
-        answers.installESLint = false;
-        return false;
-    }
-
-    return true;
-}
-
-/**
- * Install modules.
- * @param {string[]} modules Modules to be installed.
- * @returns {void}
- */
-function installModules(modules) {
-    log.info(`Installing ${modules.join(", ")}`);
-    npmUtils.installSyncSaveDev(modules);
-}
-
-/* istanbul ignore next: no need to test enquirer */
-/**
- * Ask user to install modules.
- * @param {string[]} modules Array of modules to be installed.
- * @param {boolean} packageJsonExists Indicates if package.json is existed.
- * @returns {Promise<void>} Answer that indicates if user wants to install.
- */
-function askInstallModules(modules, packageJsonExists) {
-
-    // If no modules, do nothing.
-    if (modules.length === 0) {
-        return Promise.resolve();
-    }
-
-    log.info("The config that you've selected requires the following dependencies:\n");
-    log.info(modules.join(" "));
-    return enquirer.prompt([
-        {
-            type: "toggle",
-            name: "executeInstallation",
-            message: "Would you like to install them now with npm?",
-            enabled: "Yes",
-            disabled: "No",
-            initial: 1,
-            skip() {
-                return !(modules.length && packageJsonExists);
-            },
-            result(input) {
-                return this.skipped ? null : input;
-            }
-        }
-    ]).then(({ executeInstallation }) => {
-        if (executeInstallation) {
-            installModules(modules);
-        }
-    });
-}
-
-/* istanbul ignore next: no need to test enquirer */
-/**
- * Ask use a few questions on command prompt
- * @returns {Promise<void>} The promise with the result of the prompt
- */
-function promptUser() {
-
-    return enquirer.prompt([
-        {
-            type: "select",
-            name: "purpose",
-            message: "How would you like to use ESLint?",
-
-            // The returned number matches the name value of nth in the choices array.
-            initial: 1,
-            choices: [
-                { message: "To check syntax only", name: "syntax" },
-                { message: "To check syntax and find problems", name: "problems" },
-                { message: "To check syntax, find problems, and enforce code style", name: "style" }
-            ]
-        },
-        {
-            type: "select",
-            name: "moduleType",
-            message: "What type of modules does your project use?",
-            initial: 0,
-            choices: [
-                { message: "JavaScript modules (import/export)", name: "esm" },
-                { message: "CommonJS (require/exports)", name: "commonjs" },
-                { message: "None of these", name: "none" }
-            ]
-        },
-        {
-            type: "select",
-            name: "framework",
-            message: "Which framework does your project use?",
-            initial: 0,
-            choices: [
-                { message: "React", name: "react" },
-                { message: "Vue.js", name: "vue" },
-                { message: "None of these", name: "none" }
-            ]
-        },
-        {
-            type: "toggle",
-            name: "typescript",
-            message: "Does your project use TypeScript?",
-            enabled: "Yes",
-            disabled: "No",
-            initial: 0
-        },
-        {
-            type: "multiselect",
-            name: "env",
-            message: "Where does your code run?",
-            hint: "(Press <space> to select, <a> to toggle all, <i> to invert selection)",
-            initial: 0,
-            choices: [
-                { message: "Browser", name: "browser" },
-                { message: "Node", name: "node" }
-            ]
-        },
-        {
-            type: "select",
-            name: "source",
-            message: "How would you like to define a style for your project?",
-            choices: [
-                { message: "Use a popular style guide", name: "guide" },
-                { message: "Answer questions about your style", name: "prompt" },
-                { message: "Inspect your JavaScript file(s)", name: "auto" }
-            ],
-            skip() {
-                return this.state.answers.purpose !== "style";
-            },
-            result(input) {
-                return this.skipped ? null : input;
-            }
-        },
-        {
-            type: "select",
-            name: "styleguide",
-            message: "Which style guide do you want to follow?",
-            choices: [
-                { message: "Airbnb: https://github.com/airbnb/javascript", name: "airbnb" },
-                { message: "Standard: https://github.com/standard/standard", name: "standard" },
-                { message: "Google: https://github.com/google/eslint-config-google", name: "google" },
-                { message: "XO: https://github.com/xojs/eslint-config-xo", name: "xo" }
-            ],
-            skip() {
-                this.state.answers.packageJsonExists = npmUtils.checkPackageJson();
-                return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists);
-            },
-            result(input) {
-                return this.skipped ? null : input;
-            }
-        },
-        {
-            type: "input",
-            name: "patterns",
-            message: "Which file(s), path(s), or glob(s) should be examined?",
-            skip() {
-                return this.state.answers.source !== "auto";
-            },
-            validate(input) {
-                if (!this.skipped && input.trim().length === 0 && input.trim() !== ",") {
-                    return "You must tell us what code to examine. Try again.";
-                }
-                return true;
-            }
-        },
-        {
-            type: "select",
-            name: "format",
-            message: "What format do you want your config file to be in?",
-            initial: 0,
-            choices: ["JavaScript", "YAML", "JSON"]
-        },
-        {
-            type: "toggle",
-            name: "installESLint",
-            message() {
-                const { answers } = this.state;
-                const verb = semver.ltr(answers.localESLintVersion, answers.requiredESLintVersionRange)
-                    ? "upgrade"
-                    : "downgrade";
-
-                return `The style guide "${answers.styleguide}" requires eslint@${answers.requiredESLintVersionRange}. You are currently using eslint@${answers.localESLintVersion}.\n  Do you want to ${verb}?`;
-            },
-            enabled: "Yes",
-            disabled: "No",
-            initial: 1,
-            skip() {
-                return !(this.state.answers.source === "guide" && this.state.answers.packageJsonExists && hasESLintVersionConflict(this.state.answers));
-            },
-            result(input) {
-                return this.skipped ? null : input;
-            }
-        }
-    ]).then(earlyAnswers => {
-
-        // early exit if no style guide is necessary
-        if (earlyAnswers.purpose !== "style") {
-            const config = processAnswers(earlyAnswers);
-            const modules = getModulesList(config);
-
-            return askInstallModules(modules, earlyAnswers.packageJsonExists)
-                .then(() => writeFile(config, earlyAnswers.format));
-        }
-
-        // early exit if you are using a style guide
-        if (earlyAnswers.source === "guide") {
-            if (!earlyAnswers.packageJsonExists) {
-                log.info("A package.json is necessary to install plugins such as style guides. Run `npm init` to create a package.json file and try again.");
-                return void 0;
-            }
-            if (earlyAnswers.installESLint === false && !semver.satisfies(earlyAnswers.localESLintVersion, earlyAnswers.requiredESLintVersionRange)) {
-                log.info(`Note: it might not work since ESLint's version is mismatched with the ${earlyAnswers.styleguide} config.`);
-            }
-            if (earlyAnswers.styleguide === "airbnb" && earlyAnswers.framework !== "react") {
-                earlyAnswers.styleguide = "airbnb-base";
-            }
-
-            const config = processAnswers(earlyAnswers);
-
-            if (Array.isArray(config.extends)) {
-                config.extends.push(earlyAnswers.styleguide);
-            } else if (config.extends) {
-                config.extends = [config.extends, earlyAnswers.styleguide];
-            } else {
-                config.extends = [earlyAnswers.styleguide];
-            }
-
-            const modules = getModulesList(config);
-
-            return askInstallModules(modules, earlyAnswers.packageJsonExists)
-                .then(() => writeFile(config, earlyAnswers.format));
-
-        }
-
-        if (earlyAnswers.source === "auto") {
-            const combinedAnswers = Object.assign({}, earlyAnswers);
-            const config = processAnswers(combinedAnswers);
-            const modules = getModulesList(config);
-
-            return askInstallModules(modules).then(() => writeFile(config, earlyAnswers.format));
-        }
-
-        // continue with the style questions otherwise...
-        return enquirer.prompt([
-            {
-                type: "select",
-                name: "indent",
-                message: "What style of indentation do you use?",
-                initial: 0,
-                choices: [{ message: "Tabs", name: "tab" }, { message: "Spaces", name: 4 }]
-            },
-            {
-                type: "select",
-                name: "quotes",
-                message: "What quotes do you use for strings?",
-                initial: 0,
-                choices: [{ message: "Double", name: "double" }, { message: "Single", name: "single" }]
-            },
-            {
-                type: "select",
-                name: "linebreak",
-                message: "What line endings do you use?",
-                initial: 0,
-                choices: [{ message: "Unix", name: "unix" }, { message: "Windows", name: "windows" }]
-            },
-            {
-                type: "toggle",
-                name: "semi",
-                message: "Do you require semicolons?",
-                enabled: "Yes",
-                disabled: "No",
-                initial: 1
-            }
-        ]).then(answers => {
-            const totalAnswers = Object.assign({}, earlyAnswers, answers);
-
-            const config = processAnswers(totalAnswers);
-            const modules = getModulesList(config);
-
-            return askInstallModules(modules).then(() => writeFile(config, earlyAnswers.format));
-        });
-    });
-}
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-const init = {
-    getModulesList,
-    hasESLintVersionConflict,
-    installModules,
-    processAnswers,
-    writeFile,
-    /* istanbul ignore next */initializeConfig() {
-        return promptUser();
-    }
-};
-
-module.exports = init;
diff --git a/lib/init/npm-utils.js b/lib/init/npm-utils.js
deleted file mode 100644
index 4a8efe964..000000000
--- a/lib/init/npm-utils.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * @fileoverview Utility for executing npm commands.
- * @author Ian VanSchooten
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const fs = require("fs"),
-    spawn = require("cross-spawn"),
-    path = require("path"),
-    log = require("../shared/logging");
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Find the closest package.json file, starting at process.cwd (by default),
- * and working up to root.
- * @param {string} [startDir=process.cwd()] Starting directory
- * @returns {string} Absolute path to closest package.json file
- */
-function findPackageJson(startDir) {
-    let dir = path.resolve(startDir || process.cwd());
-
-    do {
-        const pkgFile = path.join(dir, "package.json");
-
-        if (!fs.existsSync(pkgFile) || !fs.statSync(pkgFile).isFile()) {
-            dir = path.join(dir, "..");
-            continue;
-        }
-        return pkgFile;
-    } while (dir !== path.resolve(dir, ".."));
-    return null;
-}
-
-//------------------------------------------------------------------------------
-// Private
-//------------------------------------------------------------------------------
-
-/**
- * Install node modules synchronously and save to devDependencies in package.json
- * @param {string|string[]} packages Node module or modules to install
- * @returns {void}
- */
-function installSyncSaveDev(packages) {
-    const packageList = Array.isArray(packages) ? packages : [packages];
-    const npmProcess = spawn.sync("npm", ["i", "--save-dev"].concat(packageList), { stdio: "inherit" });
-    const error = npmProcess.error;
-
-    if (error && error.code === "ENOENT") {
-        const pluralS = packageList.length > 1 ? "s" : "";
-
-        log.error(`Could not execute npm. Please install the following package${pluralS} with a package manager of your choice: ${packageList.join(", ")}`);
-    }
-}
-
-/**
- * Fetch `peerDependencies` of the given package by `npm show` command.
- * @param {string} packageName The package name to fetch peerDependencies.
- * @returns {Object} Gotten peerDependencies. Returns null if npm was not found.
- */
-function fetchPeerDependencies(packageName) {
-    const npmProcess = spawn.sync(
-        "npm",
-        ["show", "--json", packageName, "peerDependencies"],
-        { encoding: "utf8" }
-    );
-
-    const error = npmProcess.error;
-
-    if (error && error.code === "ENOENT") {
-        return null;
-    }
-    const fetchedText = npmProcess.stdout.trim();
-
-    return JSON.parse(fetchedText || "{}");
-
-
-}
-
-/**
- * Check whether node modules are include in a project's package.json.
- * @param {string[]} packages Array of node module names
- * @param {Object} opt Options Object
- * @param {boolean} opt.dependencies Set to true to check for direct dependencies
- * @param {boolean} opt.devDependencies Set to true to check for development dependencies
- * @param {boolean} opt.startdir Directory to begin searching from
- * @throws {Error} If cannot find valid `package.json` file.
- * @returns {Object} An object whose keys are the module names
- *                                        and values are booleans indicating installation.
- */
-function check(packages, opt) {
-    const deps = new Set();
-    const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson();
-    let fileJson;
-
-    if (!pkgJson) {
-        throw new Error("Could not find a package.json file. Run 'npm init' to create one.");
-    }
-
-    try {
-        fileJson = JSON.parse(fs.readFileSync(pkgJson, "utf8"));
-    } catch (e) {
-        const error = new Error(e);
-
-        error.messageTemplate = "failed-to-read-json";
-        error.messageData = {
-            path: pkgJson,
-            message: e.message
-        };
-        throw error;
-    }
-
-    ["dependencies", "devDependencies"].forEach(key => {
-        if (opt[key] && typeof fileJson[key] === "object") {
-            Object.keys(fileJson[key]).forEach(dep => deps.add(dep));
-        }
-    });
-
-    return packages.reduce((status, pkg) => {
-        status[pkg] = deps.has(pkg);
-        return status;
-    }, {});
-}
-
-/**
- * Check whether node modules are included in the dependencies of a project's
- * package.json.
- *
- * Convenience wrapper around check().
- * @param {string[]} packages Array of node modules to check.
- * @param {string} rootDir The directory containing a package.json
- * @returns {Object} An object whose keys are the module names
- *                               and values are booleans indicating installation.
- */
-function checkDeps(packages, rootDir) {
-    return check(packages, { dependencies: true, startDir: rootDir });
-}
-
-/**
- * Check whether node modules are included in the devDependencies of a project's
- * package.json.
- *
- * Convenience wrapper around check().
- * @param {string[]} packages Array of node modules to check.
- * @returns {Object} An object whose keys are the module names
- *                               and values are booleans indicating installation.
- */
-function checkDevDeps(packages) {
-    return check(packages, { devDependencies: true });
-}
-
-/**
- * Check whether package.json is found in current path.
- * @param {string} [startDir] Starting directory
- * @returns {boolean} Whether a package.json is found in current path.
- */
-function checkPackageJson(startDir) {
-    return !!findPackageJson(startDir);
-}
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-module.exports = {
-    installSyncSaveDev,
-    fetchPeerDependencies,
-    findPackageJson,
-    checkDeps,
-    checkDevDeps,
-    checkPackageJson
-};
diff --git a/lib/init/source-code-utils.js b/lib/init/source-code-utils.js
deleted file mode 100644
index 08c20e5d5..000000000
--- a/lib/init/source-code-utils.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * @fileoverview Tools for obtaining SourceCode objects.
- * @author Ian VanSchooten
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const { CLIEngine } = require("../cli-engine");
-
-/*
- * This is used for:
- *
- * 1. Enumerate target file because we have not expose such a API on `CLIEngine`
- *    (https://github.com/eslint/eslint/issues/11222).
- * 2. Create `SourceCode` instances. Because we don't have any function which
- *    instantiate `SourceCode` so it needs to take the created `SourceCode`
- *    instance out after linting.
- *
- * TODO1: Expose the API that enumerates target files.
- * TODO2: Extract the creation logic of `SourceCode` from `Linter` class.
- */
-const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line node/no-restricted-require -- Todo
-
-const debug = require("debug")("eslint:source-code-utils");
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Get the SourceCode object for a single file
- * @param {string} filename The fully resolved filename to get SourceCode from.
- * @param {Object} engine A CLIEngine.
- * @throws {Error} Upon fatal errors from execution.
- * @returns {Array} Array of the SourceCode object representing the file
- *                                and fatal error message.
- */
-function getSourceCodeOfFile(filename, engine) {
-    debug("getting sourceCode of", filename);
-    const results = engine.executeOnFiles([filename]);
-
-    if (results && results.results[0] && results.results[0].messages[0] && results.results[0].messages[0].fatal) {
-        const msg = results.results[0].messages[0];
-
-        throw new Error(`(${filename}:${msg.line}:${msg.column}) ${msg.message}`);
-    }
-
-    // TODO: extract the logic that creates source code objects to `SourceCode#parse(text, options)` or something like.
-    const { linter } = getCLIEngineInternalSlots(engine);
-    const sourceCode = linter.getSourceCode();
-
-    return sourceCode;
-}
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-
-/**
- * This callback is used to measure execution status in a progress bar
- * @callback progressCallback
- * @param {number} The total number of times the callback will be called.
- */
-
-/**
- * Gets the SourceCode of a single file, or set of files.
- * @param {string[]|string} patterns A filename, directory name, or glob, or an array of them
- * @param {Object} options A CLIEngine options object. If not provided, the default cli options will be used.
- * @param {progressCallback} callback Callback for reporting execution status
- * @returns {Object} The SourceCode of all processed files.
- */
-function getSourceCodeOfFiles(patterns, options, callback) {
-    const sourceCodes = {};
-    const globPatternsList = typeof patterns === "string" ? [patterns] : patterns;
-    const engine = new CLIEngine({ ...options, rules: {} });
-
-    // TODO: make file iteration as a public API and use it.
-    const { fileEnumerator } = getCLIEngineInternalSlots(engine);
-    const filenames =
-        Array.from(fileEnumerator.iterateFiles(globPatternsList))
-            .filter(entry => !entry.ignored)
-            .map(entry => entry.filePath);
-
-    if (filenames.length === 0) {
-        debug(`Did not find any files matching pattern(s): ${globPatternsList}`);
-    }
-
-    filenames.forEach(filename => {
-        const sourceCode = getSourceCodeOfFile(filename, engine);
-
-        if (sourceCode) {
-            debug("got sourceCode of", filename);
-            sourceCodes[filename] = sourceCode;
-        }
-        if (callback) {
-            callback(filenames.length); // eslint-disable-line node/callback-return -- End of function
-        }
-    });
-
-    return sourceCodes;
-}
-
-module.exports = {
-    getSourceCodeOfFiles
-};
diff --git a/lib/rules/camelcase.js b/lib/rules/camelcase.js
index 61dd062ed..6bb1838a7 100644
--- a/lib/rules/camelcase.js
+++ b/lib/rules/camelcase.js
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -165,7 +171,7 @@ module.exports = {
                 case "ImportSpecifier":
                     return (
                         parent.local === node &&
-                        parent.imported.name === localName
+                        astUtils.getModuleExportName(parent.imported) === localName
                     );
 
                 default:
diff --git a/lib/rules/id-match.js b/lib/rules/id-match.js
index 977e66a26..8713a5f9f 100644
--- a/lib/rules/id-match.js
+++ b/lib/rules/id-match.js
@@ -250,7 +250,7 @@ module.exports = {
                     }
 
                     // never check properties or always ignore destructuring
-                    if (!checkProperties || (ignoreDestructuring && isInsideObjectPattern(node))) {
+                    if ((!checkProperties && !parent.computed) || (ignoreDestructuring && isInsideObjectPattern(node))) {
                         return;
                     }
 
diff --git a/lib/rules/keyword-spacing.js b/lib/rules/keyword-spacing.js
index 956fc4265..16a65d786 100644
--- a/lib/rules/keyword-spacing.js
+++ b/lib/rules/keyword-spacing.js
@@ -469,6 +469,7 @@ module.exports = {
                 const asToken = sourceCode.getTokenBefore(node.exported);
 
                 checkSpacingBefore(asToken, PREV_TOKEN_M);
+                checkSpacingAfter(asToken, NEXT_TOKEN_M);
             }
 
             if (node.source) {
@@ -479,6 +480,35 @@ module.exports = {
             }
         }
 
+        /**
+         * Reports `as` keyword of a given node if usage of spacing around this
+         * keyword is invalid.
+         * @param {ASTNode} node An `ImportSpecifier` node to check.
+         * @returns {void}
+         */
+        function checkSpacingForImportSpecifier(node) {
+            if (node.imported.range[0] !== node.local.range[0]) {
+                const asToken = sourceCode.getTokenBefore(node.local);
+
+                checkSpacingBefore(asToken, PREV_TOKEN_M);
+            }
+        }
+
+        /**
+         * Reports `as` keyword of a given node if usage of spacing around this
+         * keyword is invalid.
+         * @param {ASTNode} node An `ExportSpecifier` node to check.
+         * @returns {void}
+         */
+        function checkSpacingForExportSpecifier(node) {
+            if (node.local.range[0] !== node.exported.range[0]) {
+                const asToken = sourceCode.getTokenBefore(node.exported);
+
+                checkSpacingBefore(asToken, PREV_TOKEN_M);
+                checkSpacingAfter(asToken, NEXT_TOKEN_M);
+            }
+        }
+
         /**
          * Reports `as` keyword of a given node if usage of spacing around this
          * keyword is invalid.
@@ -588,6 +618,8 @@ module.exports = {
             YieldExpression: checkSpacingBeforeFirstToken,
 
             // Others
+            ImportSpecifier: checkSpacingForImportSpecifier,
+            ExportSpecifier: checkSpacingForExportSpecifier,
             ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier,
             MethodDefinition: checkSpacingForProperty,
             PropertyDefinition: checkSpacingForProperty,
diff --git a/lib/rules/no-constant-condition.js b/lib/rules/no-constant-condition.js
index 0bcb31931..8adc9bca4 100644
--- a/lib/rules/no-constant-condition.js
+++ b/lib/rules/no-constant-condition.js
@@ -124,7 +124,8 @@ module.exports = {
          * Checks if a node has a constant truthiness value.
          * @param {ASTNode} node The AST node to check.
          * @param {boolean} inBooleanPosition `false` if checking branch of a condition.
-         *  `true` in all other cases
+         *  `true` in all other cases. When `false`, checks if -- for both string and
+         *  number -- if coerced to that type, the value will be constant.
          * @returns {Bool} true when node's truthiness is constant
          * @private
          */
@@ -138,15 +139,31 @@ module.exports = {
                 case "Literal":
                 case "ArrowFunctionExpression":
                 case "FunctionExpression":
-                case "ObjectExpression":
+                    return true;
                 case "ClassExpression":
+                case "ObjectExpression":
+
+                    /**
+                     * In theory objects like:
+                     *
+                     * `{toString: () => a}`
+                     * `{valueOf: () => a}`
+                     *
+                     * Or a classes like:
+                     *
+                     * `class { static toString() { return a } }`
+                     * `class { static valueOf() { return a } }`
+                     *
+                     * Are not constant verifiably when `inBooleanPosition` is
+                     * false, but it's an edge case we've opted not to handle.
+                     */
                     return true;
                 case "TemplateLiteral":
                     return (inBooleanPosition && node.quasis.some(quasi => quasi.value.cooked.length)) ||
-                        node.expressions.every(exp => isConstant(exp, inBooleanPosition));
+                        node.expressions.every(exp => isConstant(exp, false));
 
                 case "ArrayExpression": {
-                    if (node.parent.type === "BinaryExpression" && node.parent.operator === "+") {
+                    if (!inBooleanPosition) {
                         return node.elements.every(element => isConstant(element, false));
                     }
                     return true;
@@ -196,6 +213,8 @@ module.exports = {
 
                 case "SequenceExpression":
                     return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
+                case "SpreadElement":
+                    return isConstant(node.argument, inBooleanPosition);
 
                 // no default
             }
diff --git a/lib/rules/no-restricted-exports.js b/lib/rules/no-restricted-exports.js
index 775e505d8..5166cecae 100644
--- a/lib/rules/no-restricted-exports.js
+++ b/lib/rules/no-restricted-exports.js
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -44,12 +50,12 @@ module.exports = {
         const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
 
         /**
-         * Checks and reports given exported identifier.
-         * @param {ASTNode} node exported `Identifier` node to check.
+         * Checks and reports given exported name.
+         * @param {ASTNode} node exported `Identifier` or string `Literal` node to check.
          * @returns {void}
          */
         function checkExportedName(node) {
-            const name = node.name;
+            const name = astUtils.getModuleExportName(node);
 
             if (restrictedNames.has(name)) {
                 context.report({
diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js
index 6813037f1..3bb45d715 100644
--- a/lib/rules/no-restricted-imports.js
+++ b/lib/rules/no-restricted-imports.js
@@ -4,6 +4,12 @@
  */
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -63,6 +69,9 @@ const arrayOfStringsOrObjectPatterns = {
                     message: {
                         type: "string",
                         minLength: 1
+                    },
+                    caseSensitive: {
+                        type: "boolean"
                     }
                 },
                 additionalProperties: false,
@@ -142,10 +151,18 @@ module.exports = {
         }, {});
 
         // Handle patterns too, either as strings or groups
-        const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
-        const restrictedPatternGroups = restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string"
-            ? [{ matcher: ignore().add(restrictedPatterns) }]
-            : restrictedPatterns.map(({ group, message }) => ({ matcher: ignore().add(group), customMessage: message }));
+        let restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
+
+        // standardize to array of objects if we have an array of strings
+        if (restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string") {
+            restrictedPatterns = [{ group: restrictedPatterns }];
+        }
+
+        // relative paths are supported for this rule
+        const restrictedPatternGroups = restrictedPatterns.map(({ group, message, caseSensitive }) => ({
+            matcher: ignore({ allowRelativePaths: true, ignorecase: !caseSensitive }).add(group),
+            customMessage: message
+        }));
 
         // if no imports are restricted we don't need to check
         if (Object.keys(restrictedPaths).length === 0 && restrictedPatternGroups.length === 0) {
@@ -269,12 +286,12 @@ module.exports = {
                     } else if (specifier.type === "ImportNamespaceSpecifier") {
                         name = "*";
                     } else if (specifier.imported) {
-                        name = specifier.imported.name;
+                        name = astUtils.getModuleExportName(specifier.imported);
                     } else if (specifier.local) {
-                        name = specifier.local.name;
+                        name = astUtils.getModuleExportName(specifier.local);
                     }
 
-                    if (name) {
+                    if (typeof name === "string") {
                         if (importNames.has(name)) {
                             importNames.get(name).push(specifierData);
                         } else {
diff --git a/lib/rules/no-restricted-modules.js b/lib/rules/no-restricted-modules.js
index 26e75ef81..d92aa7a86 100644
--- a/lib/rules/no-restricted-modules.js
+++ b/lib/rules/no-restricted-modules.js
@@ -103,7 +103,8 @@ module.exports = {
             return {};
         }
 
-        const ig = ignore().add(restrictedPatterns);
+        // relative paths are supported for this rule
+        const ig = ignore({ allowRelativePaths: true }).add(restrictedPatterns);
 
 
         /**
diff --git a/lib/rules/no-useless-rename.js b/lib/rules/no-useless-rename.js
index 616ec2a43..2489f57bc 100644
--- a/lib/rules/no-useless-rename.js
+++ b/lib/rules/no-useless-rename.js
@@ -132,8 +132,10 @@ module.exports = {
                 return;
             }
 
-            if (node.imported.name === node.local.name &&
-                    node.imported.range[0] !== node.local.range[0]) {
+            if (
+                node.imported.range[0] !== node.local.range[0] &&
+                astUtils.getModuleExportName(node.imported) === node.local.name
+            ) {
                 reportError(node, node.imported, "Import");
             }
         }
@@ -148,8 +150,10 @@ module.exports = {
                 return;
             }
 
-            if (node.local.name === node.exported.name &&
-                    node.local.range[0] !== node.exported.range[0]) {
+            if (
+                node.local.range[0] !== node.exported.range[0] &&
+                astUtils.getModuleExportName(node.local) === astUtils.getModuleExportName(node.exported)
+            ) {
                 reportError(node, node.local, "Export");
             }
 
diff --git a/lib/rules/quotes.js b/lib/rules/quotes.js
index a9960961e..41bff3c4e 100644
--- a/lib/rules/quotes.js
+++ b/lib/rules/quotes.js
@@ -223,9 +223,20 @@ module.exports = {
                 // ModuleSpecifier.
                 case "ImportDeclaration":
                 case "ExportNamedDeclaration":
-                case "ExportAllDeclaration":
                     return parent.source === node;
 
+                // ModuleExportName or ModuleSpecifier.
+                case "ExportAllDeclaration":
+                    return parent.exported === node || parent.source === node;
+
+                // ModuleExportName.
+                case "ImportSpecifier":
+                    return parent.imported === node;
+
+                // ModuleExportName.
+                case "ExportSpecifier":
+                    return parent.local === node || parent.exported === node;
+
                 // Others don't allow.
                 default:
                     return false;
diff --git a/lib/rules/utils/ast-utils.js b/lib/rules/utils/ast-utils.js
index 16d7b8115..ecde099fa 100644
--- a/lib/rules/utils/ast-utils.js
+++ b/lib/rules/utils/ast-utils.js
@@ -769,6 +769,25 @@ function getSwitchCaseColonToken(node, sourceCode) {
     return sourceCode.getFirstToken(node, 1);
 }
 
+/**
+ * Gets ESM module export name represented by the given node.
+ * @param {ASTNode} node `Identifier` or string `Literal` node in a position
+ * that represents a module export name:
+ *   - `ImportSpecifier#imported`
+ *   - `ExportSpecifier#local` (if it is a re-export from another module)
+ *   - `ExportSpecifier#exported`
+ *   - `ExportAllDeclaration#exported`
+ * @returns {string} The module export name.
+ */
+function getModuleExportName(node) {
+    if (node.type === "Identifier") {
+        return node.name;
+    }
+
+    // string literal
+    return node.value;
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
 //------------------------------------------------------------------------------
@@ -1898,5 +1917,6 @@ module.exports = {
     equalLiteralValue,
     isSameReference,
     isLogicalAssignmentOperator,
-    getSwitchCaseColonToken
+    getSwitchCaseColonToken,
+    getModuleExportName
 };
diff --git a/messages/no-config-found.js b/messages/no-config-found.js
index 1042143f9..c2f7ac73b 100644
--- a/messages/no-config-found.js
+++ b/messages/no-config-found.js
@@ -6,7 +6,7 @@ module.exports = function(it) {
     return `
 ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:
 
-    eslint --init
+    npm init @eslint/config
 
 ESLint looked for configuration files in ${directoryPath} and its ancestors. If it found none, it then looked in your home directory.
 
diff --git a/package.json b/package.json
index 948d8d959..d3b87ab64 100644
--- a/package.json
+++ b/package.json
@@ -54,7 +54,6 @@
     "cross-spawn": "^7.0.2",
     "debug": "^4.3.2",
     "doctrine": "^3.0.0",
-    "enquirer": "^2.3.5",
     "escape-string-regexp": "^4.0.0",
     "eslint-scope": "^7.1.0",
     "eslint-utils": "^3.0.0",
@@ -67,7 +66,7 @@
     "functional-red-black-tree": "^1.0.1",
     "glob-parent": "^6.0.1",
     "globals": "^13.6.0",
-    "ignore": "^4.0.6",
+    "ignore": "^5.2.0",
     "import-fresh": "^3.0.0",
     "imurmurhash": "^0.1.4",
     "is-glob": "^4.0.0",
@@ -78,9 +77,7 @@
     "minimatch": "^3.0.4",
     "natural-compare": "^1.4.0",
     "optionator": "^0.9.1",
-    "progress": "^2.0.0",
     "regexpp": "^3.2.0",
-    "semver": "^7.2.1",
     "strip-ansi": "^6.0.1",
     "strip-json-comments": "^3.1.0",
     "text-table": "^0.2.0",
@@ -125,10 +122,12 @@
     "node-polyfill-webpack-plugin": "^1.0.3",
     "npm-license": "^0.3.3",
     "nyc": "^15.0.1",
+    "progress": "^2.0.3",
     "proxyquire": "^2.0.1",
     "puppeteer": "^9.1.1",
     "recast": "^0.20.4",
     "regenerator-runtime": "^0.13.2",
+    "semver": "^7.3.5",
     "shelljs": "^0.8.2",
     "sinon": "^11.0.0",
     "temp": "^0.9.0",
diff --git a/lib/init/config-rule.js b/tools/config-rule.js
similarity index 99%
rename from lib/init/config-rule.js
rename to tools/config-rule.js
index 131e84a60..91e7eaef5 100644
--- a/lib/init/config-rule.js
+++ b/tools/config-rule.js
@@ -9,7 +9,7 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const builtInRules = require("../rules");
+const builtInRules = require("../lib/rules");
 
 //------------------------------------------------------------------------------
 // Helpers
diff --git a/tools/eslint-fuzzer.js b/tools/eslint-fuzzer.js
index 6c5ed9b1b..d951ad337 100644
--- a/tools/eslint-fuzzer.js
+++ b/tools/eslint-fuzzer.js
@@ -13,7 +13,7 @@ const assert = require("assert");
 const eslump = require("eslump");
 const espree = require("espree");
 const SourceCodeFixer = require("../lib/linter/source-code-fixer");
-const ruleConfigs = require("../lib/init/config-rule").createCoreRuleConfigs(true);
+const ruleConfigs = require("./config-rule").createCoreRuleConfigs(true);
 const sampleMinimizer = require("./code-sample-minimizer");
 
 //------------------------------------------------------------------------------


Test patch:
diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js
index fe520a58a..398f21013 100644
--- a/lib/rule-tester/rule-tester.js
+++ b/lib/rule-tester/rule-tester.js
@@ -977,10 +977,10 @@ class RuleTester {
          * This creates a mocha test suite and pipes all supplied info through
          * one of the templates above.
          */
-        RuleTester.describe(ruleName, () => {
-            RuleTester.describe("valid", () => {
+        this.constructor.describe(ruleName, () => {
+            this.constructor.describe("valid", () => {
                 test.valid.forEach(valid => {
-                    RuleTester[valid.only ? "itOnly" : "it"](
+                    this.constructor[valid.only ? "itOnly" : "it"](
                         sanitize(typeof valid === "object" ? valid.name || valid.code : valid),
                         () => {
                             testValidTemplate(valid);
@@ -989,9 +989,9 @@ class RuleTester {
                 });
             });
 
-            RuleTester.describe("invalid", () => {
+            this.constructor.describe("invalid", () => {
                 test.invalid.forEach(invalid => {
-                    RuleTester[invalid.only ? "itOnly" : "it"](
+                    this.constructor[invalid.only ? "itOnly" : "it"](
                         sanitize(invalid.name || invalid.code),
                         () => {
                             testInvalidTemplate(invalid);
diff --git a/tests/fixtures/autoconfig/source-with-comments.js b/tests/fixtures/autoconfig/source-with-comments.js
deleted file mode 100644
index d2e3bf9a6..000000000
--- a/tests/fixtures/autoconfig/source-with-comments.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/* eslint semi: [2, "never"] */
-/* eslint import/extensions: 2 */
-
-var foo = 42;
-var baz = "baz";
-var bar = '"no-escape"';
diff --git a/tests/fixtures/autoconfig/source.js b/tests/fixtures/autoconfig/source.js
deleted file mode 100644
index 0c126ba6d..000000000
--- a/tests/fixtures/autoconfig/source.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var foo = 42;
-var baz = "baz";
-var bar = '"no-escape"';
diff --git a/tests/fixtures/config-initializer/lib/doubleQuotes.js b/tests/fixtures/config-initializer/lib/doubleQuotes.js
deleted file mode 100644
index 1cd4a2abb..000000000
--- a/tests/fixtures/config-initializer/lib/doubleQuotes.js
+++ /dev/null
@@ -1,1 +0,0 @@
-var foo = "doubleQuotes";
diff --git a/tests/fixtures/config-initializer/lib/no-semi.js b/tests/fixtures/config-initializer/lib/no-semi.js
deleted file mode 100644
index bf10b1cfd..000000000
--- a/tests/fixtures/config-initializer/lib/no-semi.js
+++ /dev/null
@@ -1,1 +0,0 @@
-var name = "ESLint"
diff --git a/tests/fixtures/config-initializer/new-es-features/new-es-features.js b/tests/fixtures/config-initializer/new-es-features/new-es-features.js
deleted file mode 100644
index c3e03fc32..000000000
--- a/tests/fixtures/config-initializer/new-es-features/new-es-features.js
+++ /dev/null
@@ -1,3 +0,0 @@
-async function fn() {
-    await Promise.resolve();
-}
diff --git a/tests/fixtures/config-initializer/parse-error/parse-error.js b/tests/fixtures/config-initializer/parse-error/parse-error.js
deleted file mode 100644
index 90bd920ce..000000000
--- a/tests/fixtures/config-initializer/parse-error/parse-error.js
+++ /dev/null
@@ -1,1 +0,0 @@
-+;
diff --git a/tests/fixtures/config-initializer/singleQuotes.js b/tests/fixtures/config-initializer/singleQuotes.js
deleted file mode 100644
index db1e01fed..000000000
--- a/tests/fixtures/config-initializer/singleQuotes.js
+++ /dev/null
@@ -1,1 +0,0 @@
-var foo = 'singleQuotes';
diff --git a/tests/fixtures/config-initializer/tests/console-log.js b/tests/fixtures/config-initializer/tests/console-log.js
deleted file mode 100644
index 929e82a14..000000000
--- a/tests/fixtures/config-initializer/tests/console-log.js
+++ /dev/null
@@ -1,1 +0,0 @@
-console.log("I'm a log");
diff --git a/tests/fixtures/config-initializer/tests/doubleQuotes.js b/tests/fixtures/config-initializer/tests/doubleQuotes.js
deleted file mode 100644
index 1cd4a2abb..000000000
--- a/tests/fixtures/config-initializer/tests/doubleQuotes.js
+++ /dev/null
@@ -1,1 +0,0 @@
-var foo = "doubleQuotes";
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index 2ba4839ba..8871ff86c 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -235,6 +235,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.errorCount, 0);
             assert.strictEqual(report.warningCount, 1);
+            assert.strictEqual(report.fatalErrorCount, 0);
             assert.strictEqual(report.fixableErrorCount, 0);
             assert.strictEqual(report.fixableWarningCount, 0);
             assert.strictEqual(report.results[0].filePath, getFixturePath("passing.js"));
@@ -243,6 +244,7 @@ describe("CLIEngine", () => {
             assert.isUndefined(report.results[0].messages[0].output);
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
             assert.strictEqual(report.results[0].fixableErrorCount, 0);
             assert.strictEqual(report.results[0].fixableWarningCount, 0);
         });
@@ -982,6 +984,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
             assert.strictEqual(report.results[0].fixableErrorCount, 0);
             assert.strictEqual(report.results[0].fixableWarningCount, 0);
             assert.strictEqual(report.results[0].messages[0].message, expectedMsg);
@@ -1045,6 +1048,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
             assert.strictEqual(report.results[0].fixableErrorCount, 0);
             assert.strictEqual(report.results[0].fixableWarningCount, 0);
             assert.strictEqual(report.results[0].messages[0].message, expectedMsg);
@@ -1066,6 +1070,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
             assert.strictEqual(report.results[0].fixableErrorCount, 0);
             assert.strictEqual(report.results[0].fixableWarningCount, 0);
             assert.strictEqual(report.results[0].messages[0].message, expectedMsg);
@@ -1415,6 +1420,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.errorCount, 0);
             assert.strictEqual(report.warningCount, 1);
+            assert.strictEqual(report.fatalErrorCount, 0);
             assert.strictEqual(report.fixableErrorCount, 0);
             assert.strictEqual(report.fixableWarningCount, 0);
             assert.strictEqual(report.results[0].filePath, filePath);
@@ -1422,6 +1428,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results[0].messages[0].message, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
             assert.strictEqual(report.results[0].fixableErrorCount, 0);
             assert.strictEqual(report.results[0].fixableWarningCount, 0);
         });
@@ -4824,12 +4831,14 @@ describe("CLIEngine", () => {
             assert.lengthOf(report.results, 1);
             assert.strictEqual(report.errorCount, 0);
             assert.strictEqual(report.warningCount, 1);
+            assert.strictEqual(report.fatalErrorCount, 0);
             assert.strictEqual(report.fixableErrorCount, 0);
             assert.strictEqual(report.fixableWarningCount, 0);
             assert.strictEqual(report.results[0].errorCount, 0);
             assert.strictEqual(report.results[0].warningCount, 1);
-            assert.strictEqual(report.fixableErrorCount, 0);
-            assert.strictEqual(report.fixableWarningCount, 0);
+            assert.strictEqual(report.results[0].fatalErrorCount, 0);
+            assert.strictEqual(report.results[0].fixableErrorCount, 0);
+            assert.strictEqual(report.results[0].fixableWarningCount, 0);
         });
 
         it("should return source code of file in the `source` property", () => {
diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js
index 4e140f7fe..d77eac5d4 100644
--- a/tests/lib/eslint/eslint.js
+++ b/tests/lib/eslint/eslint.js
@@ -324,6 +324,7 @@ describe("ESLint", () => {
             assert.strictEqual(results[0].messages[0].output, void 0);
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
             assert.strictEqual(results[0].fixableErrorCount, 0);
             assert.strictEqual(results[0].fixableWarningCount, 0);
             assert.strictEqual(results[0].usedDeprecatedRules.length, 0);
@@ -1044,6 +1045,7 @@ describe("ESLint", () => {
             assert.strictEqual(results.length, 1);
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
             assert.strictEqual(results[0].fixableErrorCount, 0);
             assert.strictEqual(results[0].fixableWarningCount, 0);
             assert.strictEqual(results[0].messages[0].message, expectedMsg);
@@ -1105,6 +1107,7 @@ describe("ESLint", () => {
             assert.strictEqual(results.length, 1);
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
             assert.strictEqual(results[0].fixableErrorCount, 0);
             assert.strictEqual(results[0].fixableWarningCount, 0);
             assert.strictEqual(results[0].messages[0].message, expectedMsg);
@@ -1127,6 +1130,7 @@ describe("ESLint", () => {
             assert.strictEqual(results.length, 1);
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
             assert.strictEqual(results[0].fixableErrorCount, 0);
             assert.strictEqual(results[0].fixableWarningCount, 0);
             assert.strictEqual(results[0].messages[0].message, expectedMsg);
@@ -1413,6 +1417,7 @@ describe("ESLint", () => {
             assert.strictEqual(results[0].messages[0].message, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
             assert.strictEqual(results[0].fixableErrorCount, 0);
             assert.strictEqual(results[0].fixableWarningCount, 0);
         });
@@ -4822,6 +4827,9 @@ describe("ESLint", () => {
             assert.strictEqual(results.length, 1);
             assert.strictEqual(results[0].errorCount, 0);
             assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fatalErrorCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
         });
 
         it("should return source code of file in the `source` property", async () => {
diff --git a/tests/lib/init/autoconfig.js b/tests/lib/init/autoconfig.js
deleted file mode 100644
index 3db6a6364..000000000
--- a/tests/lib/init/autoconfig.js
+++ /dev/null
@@ -1,385 +0,0 @@
-/**
- * @fileoverview Used for creating a suggested configuration based on project code.
- * @author Ian VanSchooten
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const assert = require("chai").assert,
-    autoconfig = require("../../../lib/init/autoconfig"),
-    sourceCodeUtils = require("../../../lib/init/source-code-utils"),
-    baseDefaultOptions = require("../../../conf/default-cli-options"),
-    recommendedConfig = require("../../conf/eslint-recommended");
-
-const defaultOptions = Object.assign({}, baseDefaultOptions, { cwd: process.cwd() });
-
-//------------------------------------------------------------------------------
-// Data
-//------------------------------------------------------------------------------
-
-const SOURCE_CODE_FIXTURE_FILENAME = "./tests/fixtures/autoconfig/source.js";
-const CONFIG_COMMENTS_FILENAME = "./tests/fixtures/autoconfig/source-with-comments.js";
-const SEVERITY = 2;
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-const rulesConfig = {
-    semi: [SEVERITY, [SEVERITY, "always"], [SEVERITY, "never"]],
-    "semi-spacing": [SEVERITY,
-        [SEVERITY, { before: true, after: true }],
-        [SEVERITY, { before: true, after: false }],
-        [SEVERITY, { before: false, after: true }],
-        [SEVERITY, { before: false, after: false }]
-    ],
-    quotes: [SEVERITY,
-        [SEVERITY, "single"],
-        [SEVERITY, "double"],
-        [SEVERITY, "backtick"],
-        [SEVERITY, "single", "avoid-escape"],
-        [SEVERITY, "double", "avoid-escape"],
-        [SEVERITY, "backtick", "avoid-escape"]]
-};
-
-const errorRulesConfig = {
-    "no-unused-vars": [SEVERITY],
-    "semi-spacing": [SEVERITY,
-        [SEVERITY, { before: true, after: true }],
-        [SEVERITY, { before: true, after: false }],
-        [SEVERITY, { before: false, after: true }],
-        [SEVERITY, { before: false, after: false }]
-    ]
-};
-
-describe("autoconfig", () => {
-
-    describe("Registry", () => {
-
-        it("should set up a registry for rules in a provided rulesConfig", () => {
-            const expectedRules = Object.keys(rulesConfig);
-            const registry = new autoconfig.Registry(rulesConfig);
-
-            assert.strictEqual(Object.keys(registry.rules).length, 3);
-            assert.sameMembers(Object.keys(registry.rules), expectedRules);
-            assert.isArray(registry.rules.semi);
-            assert.isArray(registry.rules["semi-spacing"]);
-            assert.isArray(registry.rules.quotes);
-            assert.lengthOf(registry.rules.semi, 3);
-            assert.lengthOf(registry.rules["semi-spacing"], 5);
-            assert.lengthOf(registry.rules.quotes, 7);
-        });
-
-        it("should not have any rules if constructed without a config argument", () => {
-            const registry = new autoconfig.Registry();
-
-            assert.isObject(registry.rules);
-            assert.lengthOf(Object.keys(registry.rules), 0);
-        });
-
-        it("should create registryItems for each rule with the proper keys", () => {
-            const registry = new autoconfig.Registry(rulesConfig);
-
-            assert.isObject(registry.rules.semi[0]);
-            assert.isObject(registry.rules["semi-spacing"][0]);
-            assert.isObject(registry.rules.quotes[0]);
-            assert.property(registry.rules.semi[0], "config");
-            assert.property(registry.rules.semi[0], "specificity");
-            assert.property(registry.rules.semi[0], "errorCount");
-        });
-
-        it("should populate the config property correctly", () => {
-            const registry = new autoconfig.Registry(rulesConfig);
-
-            assert.strictEqual(registry.rules.quotes[0].config, SEVERITY);
-            assert.deepStrictEqual(registry.rules.quotes[1].config, [SEVERITY, "single"]);
-            assert.deepStrictEqual(registry.rules.quotes[2].config, [SEVERITY, "double"]);
-            assert.deepStrictEqual(registry.rules.quotes[3].config, [SEVERITY, "backtick"]);
-            assert.deepStrictEqual(registry.rules.quotes[4].config, [SEVERITY, "single", "avoid-escape"]);
-            assert.deepStrictEqual(registry.rules.quotes[5].config, [SEVERITY, "double", "avoid-escape"]);
-            assert.deepStrictEqual(registry.rules.quotes[6].config, [SEVERITY, "backtick", "avoid-escape"]);
-        });
-
-        it("should assign the correct specificity", () => {
-            const registry = new autoconfig.Registry(rulesConfig);
-
-            assert.strictEqual(registry.rules.quotes[0].specificity, 1);
-            assert.strictEqual(registry.rules.quotes[1].specificity, 2);
-            assert.strictEqual(registry.rules.quotes[6].specificity, 3);
-        });
-
-        it("should initially leave the errorCount as undefined", () => {
-            const registry = new autoconfig.Registry(rulesConfig);
-
-            assert.isUndefined(registry.rules.quotes[0].errorCount);
-            assert.isUndefined(registry.rules.quotes[1].errorCount);
-            assert.isUndefined(registry.rules.quotes[6].errorCount);
-        });
-
-        describe("populateFromCoreRules()", () => {
-
-            it("should add core rules to registry", () => {
-                const registry = new autoconfig.Registry();
-
-                registry.populateFromCoreRules();
-                const finalRuleCount = Object.keys(registry.rules).length;
-
-                assert(finalRuleCount > 0);
-                assert.include(Object.keys(registry.rules), "eqeqeq");
-            });
-
-            it("should not add deprecated rules", () => {
-                const registry = new autoconfig.Registry();
-
-                registry.populateFromCoreRules();
-
-                const { rules } = registry;
-
-                assert.notProperty(rules, "id-blacklist");
-                assert.notProperty(rules, "no-negated-in-lhs");
-                assert.notProperty(rules, "no-process-exit");
-                assert.notProperty(rules, "no-spaced-func");
-                assert.notProperty(rules, "prefer-reflect");
-            });
-
-            it("should not add duplicate rules", () => {
-                const registry = new autoconfig.Registry(rulesConfig);
-
-                registry.populateFromCoreRules();
-                const semiCount = Object.keys(registry.rules).filter(ruleId => ruleId === "semi").length;
-
-                assert.strictEqual(semiCount, 1);
-            });
-        });
-
-        describe("buildRuleSets()", () => {
-            let ruleSets;
-
-            beforeEach(() => {
-                const registry = new autoconfig.Registry(rulesConfig);
-
-                ruleSets = registry.buildRuleSets();
-            });
-
-            it("should create an array of rule configuration sets", () => {
-                assert.isArray(ruleSets);
-            });
-
-            it("should include configs for each rule (at least for the first set)", () => {
-                assert.sameMembers(Object.keys(ruleSets[0]), ["semi", "semi-spacing", "quotes"]);
-            });
-
-            it("should create the first set from default rule configs (severity only)", () => {
-                assert.deepStrictEqual(ruleSets[0], { semi: SEVERITY, "semi-spacing": SEVERITY, quotes: SEVERITY });
-            });
-
-            it("should create as many ruleSets as the highest number of configs in a rule", () => {
-
-                // `quotes` has 7 possible configurations
-                assert.lengthOf(ruleSets, 7);
-            });
-        });
-
-        describe("lintSourceCode()", () => {
-            let registry;
-
-            beforeEach(() => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
-
-                registry = new autoconfig.Registry(rulesConfig);
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-            });
-
-            it("should populate the errorCount of all registryItems", () => {
-                const expectedRules = ["semi", "semi-spacing", "quotes"];
-
-                assert.sameMembers(Object.keys(registry.rules), expectedRules);
-                expectedRules.forEach(ruleId => {
-                    assert(registry.rules[ruleId].length > 0);
-                    registry.rules[ruleId].forEach(conf => {
-                        assert.isNumber(conf.errorCount);
-                    });
-                });
-            });
-
-            it("should correctly set the error count of configurations", () => {
-                assert.strictEqual(registry.rules.semi[0].config, SEVERITY);
-                assert.strictEqual(registry.rules.semi[0].errorCount, 0);
-                assert.deepStrictEqual(registry.rules.semi[2].config, [SEVERITY, "never"]);
-                assert.strictEqual(registry.rules.semi[2].errorCount, 3);
-            });
-
-            it("should respect inline eslint config comments (and not crash when they make linting errors)", () => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(CONFIG_COMMENTS_FILENAME, config);
-                const expectedRegistry = [
-                    { config: 2, specificity: 1, errorCount: 3 },
-                    { config: [2, "always"], specificity: 2, errorCount: 3 },
-                    { config: [2, "never"], specificity: 2, errorCount: 3 }
-                ];
-
-                registry = new autoconfig.Registry(rulesConfig);
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-
-                assert.deepStrictEqual(registry.rules.semi, expectedRegistry);
-            });
-        });
-
-        describe("stripFailingConfigs()", () => {
-            let registry;
-
-            beforeEach(() => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
-
-                registry = new autoconfig.Registry(rulesConfig);
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-                registry = registry.stripFailingConfigs();
-            });
-
-            it("should remove all registryItems with a non-zero errorCount", () => {
-                assert.lengthOf(registry.rules.semi, 2);
-                assert.lengthOf(registry.rules["semi-spacing"], 3);
-                assert.lengthOf(registry.rules.quotes, 1);
-                registry.rules.semi.forEach(registryItem => {
-                    assert.strictEqual(registryItem.errorCount, 0);
-                });
-                registry.rules["semi-spacing"].forEach(registryItem => {
-                    assert.strictEqual(registryItem.errorCount, 0);
-                });
-                registry.rules.quotes.forEach(registryItem => {
-                    assert.strictEqual(registryItem.errorCount, 0);
-                });
-            });
-        });
-
-        describe("getFailingRulesRegistry()", () => {
-            let failingRegistry;
-
-            beforeEach(() => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
-                let registry = new autoconfig.Registry(errorRulesConfig);
-
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-                failingRegistry = registry.getFailingRulesRegistry();
-            });
-
-            it("should return a registry with no registryItems with an errorCount of zero", () => {
-                const failingRules = Object.keys(failingRegistry.rules);
-
-                assert.deepStrictEqual(failingRules, ["no-unused-vars"]);
-                assert.lengthOf(failingRegistry.rules["no-unused-vars"], 1);
-                assert(failingRegistry.rules["no-unused-vars"][0].errorCount > 0);
-            });
-        });
-
-        describe("createConfig()", () => {
-            let createdConfig;
-
-            beforeEach(() => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
-                let registry = new autoconfig.Registry(rulesConfig);
-
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-                registry = registry.stripFailingConfigs();
-                createdConfig = registry.createConfig();
-            });
-
-            it("should create a config with a rules property", () => {
-                assert.property(createdConfig, "rules");
-            });
-
-            it("should add rules which have only one registryItem to the config", () => {
-                const configuredRules = Object.keys(createdConfig.rules);
-
-                assert.deepStrictEqual(configuredRules, ["quotes"]);
-            });
-
-            it("should set the configuration of the rule to the registryItem's `config` value", () => {
-                assert.deepStrictEqual(createdConfig.rules.quotes, [2, "double", "avoid-escape"]);
-            });
-
-            it("should not care how many errors the config has", () => {
-                const config = { ignore: false };
-                const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
-                let registry = new autoconfig.Registry(errorRulesConfig);
-
-                registry = registry.lintSourceCode(sourceCode, defaultOptions);
-                const failingRegistry = registry.getFailingRulesRegistry();
-
-                createdConfig = failingRegistry.createConfig();
-                const configuredRules = Object.keys(createdConfig.rules);
-
-                assert.deepStrictEqual(configuredRules, ["no-unused-vars"]);
-            });
-        });
-
-        describe("filterBySpecificity()", () => {
-            let registry;
-
-            beforeEach(() => {
-                registry = new autoconfig.Registry(rulesConfig);
-            });
-
-            it("should return a registry where all configs have a desired specificity", () => {
-                const filteredRegistry1 = registry.filterBySpecificity(1);
-                const filteredRegistry2 = registry.filterBySpecificity(2);
-                const filteredRegistry3 = registry.filterBySpecificity(3);
-
-                assert.lengthOf(filteredRegistry1.rules.semi, 1);
-                assert.lengthOf(filteredRegistry1.rules["semi-spacing"], 1);
-                assert.lengthOf(filteredRegistry1.rules.quotes, 1);
-                assert.lengthOf(filteredRegistry2.rules.semi, 2);
-                assert.lengthOf(filteredRegistry2.rules["semi-spacing"], 4);
-                assert.lengthOf(filteredRegistry2.rules.quotes, 3);
-                assert.lengthOf(filteredRegistry3.rules.quotes, 3);
-            });
-        });
-    });
-
-    describe("extendFromRecommended()", () => {
-        it("should return a configuration which has `extends` key with Array type value", () => {
-            const oldConfig = { extends: [], rules: {} };
-            const newConfig = autoconfig.extendFromRecommended(oldConfig);
-
-            assert.exists(newConfig.extends);
-            assert.isArray(newConfig.extends);
-        });
-
-        it("should return a configuration which has array property `extends`", () => {
-            const oldConfig = { extends: [], rules: {} };
-            const newConfig = autoconfig.extendFromRecommended(oldConfig);
-
-            assert.include(newConfig.extends, "eslint:recommended");
-        });
-
-        it("should return a configuration which preserves the previous extending configurations", () => {
-            const oldConfig = { extends: ["previous:configuration1", "previous:configuration2"], rules: {} };
-            const newConfig = autoconfig.extendFromRecommended(oldConfig);
-
-            assert.includeMembers(newConfig.extends, oldConfig.extends);
-        });
-
-        it("should return a configuration which has `eslint:recommended` at the first of `extends`", () => {
-            const oldConfig = { extends: ["previous:configuration1", "previous:configuration2"], rules: {} };
-            const newConfig = autoconfig.extendFromRecommended(oldConfig);
-            const [firstExtendInNewConfig] = newConfig.extends;
-
-            assert.strictEqual(firstExtendInNewConfig, "eslint:recommended");
-        });
-
-        it("should return a configuration which not includes rules configured in `eslint:recommended`", () => {
-            const oldConfig = { extends: [], rules: { ...recommendedConfig.rules } };
-            const newConfig = autoconfig.extendFromRecommended(oldConfig);
-
-            assert.notInclude(newConfig.rules, oldConfig.rules);
-        });
-    });
-});
diff --git a/tests/lib/init/config-file.js b/tests/lib/init/config-file.js
deleted file mode 100644
index 50a9af1d5..000000000
--- a/tests/lib/init/config-file.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * @fileoverview Tests for ConfigFile
- * @author Nicholas C. Zakas
- */
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const assert = require("chai").assert,
-    sinon = require("sinon"),
-    path = require("path"),
-    yaml = require("js-yaml"),
-    espree = require("espree"),
-    ConfigFile = require("../../../lib/init/config-file"),
-    { CLIEngine } = require("../../../lib/cli-engine");
-
-const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Helper function get easily get a path in the fixtures directory.
- * @param {string} filepath The path to find in the fixtures directory.
- * @returns {string} Full path in the fixtures directory.
- * @private
- */
-function getFixturePath(filepath) {
-    return path.resolve(__dirname, "../../fixtures/config-file", filepath);
-}
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-describe("ConfigFile", () => {
-    describe("write()", () => {
-        let config;
-
-        beforeEach(() => {
-            config = {
-                env: {
-                    browser: true,
-                    node: true
-                },
-                rules: {
-                    quotes: 2,
-                    semi: 1
-                }
-            };
-        });
-
-        afterEach(() => {
-            sinon.verifyAndRestore();
-        });
-
-        [
-            ["JavaScript", "foo.js", espree.parse],
-            ["JSON", "bar.json", JSON.parse],
-            ["YAML", "foo.yaml", yaml.load],
-            ["YML", "foo.yml", yaml.load]
-        ].forEach(([fileType, filename, validate]) => {
-
-            it(`should write a file through fs when a ${fileType} path is passed`, () => {
-                const fakeFS = {
-                    writeFileSync: () => {}
-                };
-
-                sinon.mock(fakeFS).expects("writeFileSync").withExactArgs(
-                    filename,
-                    sinon.match(value => !!validate(value)),
-                    "utf8"
-                );
-
-                const StubbedConfigFile = proxyquire("../../../lib/init/config-file", {
-                    fs: fakeFS
-                });
-
-                StubbedConfigFile.write(config, filename);
-            });
-
-            it("should include a newline character at EOF", () => {
-                const fakeFS = {
-                    writeFileSync: () => {}
-                };
-
-                sinon.mock(fakeFS).expects("writeFileSync").withExactArgs(
-                    filename,
-                    sinon.match(value => value.endsWith("\n")),
-                    "utf8"
-                );
-
-                const StubbedConfigFile = proxyquire("../../../lib/init/config-file", {
-                    fs: fakeFS
-                });
-
-                StubbedConfigFile.write(config, filename);
-            });
-        });
-
-        it("should make sure js config files match linting rules", () => {
-            const fakeFS = {
-                writeFileSync: () => {}
-            };
-
-            const singleQuoteConfig = {
-                rules: {
-                    quotes: [2, "single"]
-                }
-            };
-
-            sinon.mock(fakeFS).expects("writeFileSync").withExactArgs(
-                "test-config.js",
-                sinon.match(value => !value.includes("\"")),
-                "utf8"
-            );
-
-            const StubbedConfigFile = proxyquire("../../../lib/init/config-file", {
-                fs: fakeFS
-            });
-
-            StubbedConfigFile.write(singleQuoteConfig, "test-config.js");
-        });
-
-        it("should still write a js config file even if linting fails", () => {
-            const fakeFS = {
-                writeFileSync: () => {}
-            };
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({
-                baseConfig: config,
-                fix: true,
-                useEslintrc: false
-            }));
-
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnText").throws();
-
-            sinon.mock(fakeFS).expects("writeFileSync").once();
-
-            const StubbedConfigFile = proxyquire("../../../lib/init/config-file", {
-                fs: fakeFS,
-                "../cli-engine": { CLIEngine: fakeCLIEngine }
-            });
-
-            assert.throws(() => {
-                StubbedConfigFile.write(config, "test-config.js");
-            });
-        });
-
-        it("should throw error if file extension is not valid", () => {
-            assert.throws(() => {
-                ConfigFile.write({}, getFixturePath("yaml/.eslintrc.class"));
-            }, /write to unknown file type/u);
-        });
-    });
-});
diff --git a/tests/lib/init/config-initializer.js b/tests/lib/init/config-initializer.js
deleted file mode 100644
index 81e4e52fa..000000000
--- a/tests/lib/init/config-initializer.js
+++ /dev/null
@@ -1,577 +0,0 @@
-/**
- * @fileoverview Tests for configInitializer.
- * @author Ilya Volodin
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const assert = require("chai").assert,
-    fs = require("fs"),
-    path = require("path"),
-    os = require("os"),
-    sinon = require("sinon"),
-    sh = require("shelljs"),
-    espree = require("espree"),
-    autoconfig = require("../../../lib/init/autoconfig"),
-    npmUtils = require("../../../lib/init/npm-utils");
-
-const originalDir = process.cwd();
-const proxyquire = require("proxyquire").noPreserveCache();
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-let answers = {};
-let pkgJSONContents = {};
-let pkgJSONPath = "";
-
-describe("configInitializer", () => {
-
-    let fixtureDir,
-        npmCheckStub,
-        npmInstallStub,
-        npmFetchPeerDependenciesStub,
-        init,
-        localESLintVersion = null;
-
-    const log = {
-        info: sinon.spy(),
-        error: sinon.spy()
-    };
-    const requireStubs = {
-        "../shared/logging": log,
-        "../shared/relative-module-resolver": {
-            resolve() {
-                if (localESLintVersion) {
-                    return `local-eslint-${localESLintVersion}`;
-                }
-                throw new Error("Cannot find module");
-            }
-        },
-        "local-eslint-3.18.0": { linter: { version: "3.18.0" }, "@noCallThru": true },
-        "local-eslint-3.19.0": { linter: { version: "3.19.0" }, "@noCallThru": true },
-        "local-eslint-4.0.0": { linter: { version: "4.0.0" }, "@noCallThru": true }
-    };
-
-    /**
-     * Returns the path inside of the fixture directory.
-     * @param {...string} args file path segments.
-     * @returns {string} The path inside the fixture directory.
-     * @private
-     */
-    function getFixturePath(...args) {
-        const filepath = path.join(fixtureDir, ...args);
-
-        try {
-            return fs.realpathSync(filepath);
-        } catch {
-            return filepath;
-        }
-    }
-
-    // copy into clean area so as not to get "infected" by this project's .eslintrc files
-    before(() => {
-        fixtureDir = path.join(os.tmpdir(), "eslint/fixtures/config-initializer");
-        sh.mkdir("-p", fixtureDir);
-        sh.cp("-r", "./tests/fixtures/config-initializer/.", fixtureDir);
-        fixtureDir = fs.realpathSync(fixtureDir);
-    });
-
-    beforeEach(() => {
-        npmInstallStub = sinon.stub(npmUtils, "installSyncSaveDev");
-        npmCheckStub = sinon.stub(npmUtils, "checkDevDeps").callsFake(packages => packages.reduce((status, pkg) => {
-            status[pkg] = false;
-            return status;
-        }, {}));
-        npmFetchPeerDependenciesStub = sinon
-            .stub(npmUtils, "fetchPeerDependencies")
-            .returns({
-                eslint: "^3.19.0",
-                "eslint-plugin-jsx-a11y": "^5.0.1",
-                "eslint-plugin-import": "^2.2.0",
-                "eslint-plugin-react": "^7.0.1"
-            });
-        init = proxyquire("../../../lib/init/config-initializer", requireStubs);
-    });
-
-    afterEach(() => {
-        log.info.resetHistory();
-        log.error.resetHistory();
-        npmInstallStub.restore();
-        npmCheckStub.restore();
-        npmFetchPeerDependenciesStub.restore();
-    });
-
-    after(() => {
-        sh.rm("-r", fixtureDir);
-    });
-
-    describe("processAnswers()", () => {
-
-        describe("prompt", () => {
-
-            beforeEach(() => {
-                answers = {
-                    purpose: "style",
-                    source: "prompt",
-                    extendDefault: true,
-                    indent: 2,
-                    quotes: "single",
-                    linebreak: "unix",
-                    semi: true,
-                    moduleType: "esm",
-                    es6Globals: true,
-                    env: ["browser"],
-                    format: "JSON"
-                };
-            });
-
-            it("should create default config", () => {
-                const config = init.processAnswers(answers);
-
-                assert.deepStrictEqual(config.rules.indent, ["error", 2]);
-                assert.deepStrictEqual(config.rules.quotes, ["error", "single"]);
-                assert.deepStrictEqual(config.rules["linebreak-style"], ["error", "unix"]);
-                assert.deepStrictEqual(config.rules.semi, ["error", "always"]);
-                assert.strictEqual(config.env.es2021, true);
-                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
-                assert.strictEqual(config.parserOptions.sourceType, "module");
-                assert.strictEqual(config.env.browser, true);
-                assert.strictEqual(config.extends, "eslint:recommended");
-            });
-
-            it("should disable semi", () => {
-                answers.semi = false;
-                const config = init.processAnswers(answers);
-
-                assert.deepStrictEqual(config.rules.semi, ["error", "never"]);
-            });
-
-            it("should enable react plugin", () => {
-                answers.framework = "react";
-                const config = init.processAnswers(answers);
-
-                assert.strictEqual(config.parserOptions.ecmaFeatures.jsx, true);
-                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
-                assert.deepStrictEqual(config.plugins, ["react"]);
-            });
-
-            it("should enable vue plugin", () => {
-                answers.framework = "vue";
-                const config = init.processAnswers(answers);
-
-                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
-                assert.deepStrictEqual(config.plugins, ["vue"]);
-                assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:vue/essential"]);
-            });
-
-            it("should enable typescript parser and plugin", () => {
-                answers.typescript = true;
-                const config = init.processAnswers(answers);
-
-                assert.strictEqual(config.parser, "@typescript-eslint/parser");
-                assert.deepStrictEqual(config.plugins, ["@typescript-eslint"]);
-                assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:@typescript-eslint/recommended"]);
-            });
-
-            it("should enable typescript parser and plugin with vue", () => {
-                answers.framework = "vue";
-                answers.typescript = true;
-                const config = init.processAnswers(answers);
-
-                assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:vue/essential", "plugin:@typescript-eslint/recommended"]);
-                assert.strictEqual(config.parserOptions.parser, "@typescript-eslint/parser");
-                assert.deepStrictEqual(config.plugins, ["vue", "@typescript-eslint"]);
-            });
-
-            it("should extend eslint:recommended", () => {
-                const config = init.processAnswers(answers);
-
-                assert.strictEqual(config.extends, "eslint:recommended");
-            });
-
-            it("should not use commonjs by default", () => {
-                const config = init.processAnswers(answers);
-
-                assert.isUndefined(config.env.commonjs);
-            });
-
-            it("should use commonjs when set", () => {
-                answers.moduleType = "commonjs";
-                const config = init.processAnswers(answers);
-
-                assert.isTrue(config.env.commonjs);
-            });
-        });
-
-        describe("guide", () => {
-            it("should support the google style guide", () => {
-                const config = { extends: "google" };
-                const modules = init.getModulesList(config);
-
-                assert.deepStrictEqual(config, { extends: "google", installedESLint: true });
-                assert.include(modules, "eslint-config-google@latest");
-            });
-
-            it("should support the airbnb style guide", () => {
-                const config = { extends: "airbnb" };
-                const modules = init.getModulesList(config);
-
-                assert.deepStrictEqual(config, { extends: "airbnb", installedESLint: true });
-                assert.include(modules, "eslint-config-airbnb@latest");
-            });
-
-            it("should support the airbnb base style guide", () => {
-                const config = { extends: "airbnb-base" };
-                const modules = init.getModulesList(config);
-
-                assert.deepStrictEqual(config, { extends: "airbnb-base", installedESLint: true });
-                assert.include(modules, "eslint-config-airbnb-base@latest");
-            });
-
-            it("should support the standard style guide", () => {
-                const config = { extends: "standard" };
-                const modules = init.getModulesList(config);
-
-                assert.deepStrictEqual(config, { extends: "standard", installedESLint: true });
-                assert.include(modules, "eslint-config-standard@latest");
-            });
-
-            it("should support the xo style guide", () => {
-                const config = { extends: "xo" };
-                const modules = init.getModulesList(config);
-
-                assert.deepStrictEqual(config, { extends: "xo", installedESLint: true });
-                assert.include(modules, "eslint-config-xo@latest");
-            });
-
-            it("should install required sharable config", () => {
-                const config = { extends: "google" };
-
-                init.installModules(init.getModulesList(config));
-                assert(npmInstallStub.calledOnce);
-                assert(npmInstallStub.firstCall.args[0].some(name => name.startsWith("eslint-config-google@")));
-            });
-
-            it("should install ESLint if not installed locally", () => {
-                const config = { extends: "google" };
-
-                init.installModules(init.getModulesList(config));
-                assert(npmInstallStub.calledOnce);
-                assert(npmInstallStub.firstCall.args[0].some(name => name.startsWith("eslint@")));
-            });
-
-            it("should install peerDependencies of the sharable config", () => {
-                const config = { extends: "airbnb" };
-
-                init.installModules(init.getModulesList(config));
-
-                assert(npmFetchPeerDependenciesStub.calledOnce);
-                assert(npmFetchPeerDependenciesStub.firstCall.args[0] === "eslint-config-airbnb@latest");
-                assert(npmInstallStub.calledOnce);
-                assert.deepStrictEqual(
-                    npmInstallStub.firstCall.args[0],
-                    [
-                        "eslint-config-airbnb@latest",
-                        "eslint@^3.19.0",
-                        "eslint-plugin-jsx-a11y@^5.0.1",
-                        "eslint-plugin-import@^2.2.0",
-                        "eslint-plugin-react@^7.0.1"
-                    ]
-                );
-            });
-
-            describe("hasESLintVersionConflict (Note: peerDependencies always `eslint: \"^3.19.0\"` by stubs)", () => {
-                describe("if local ESLint is not found,", () => {
-                    before(() => {
-                        localESLintVersion = null;
-                    });
-
-                    it("should return false.", () => {
-                        const result = init.hasESLintVersionConflict({ styleguide: "airbnb" });
-
-                        assert.strictEqual(result, false);
-                    });
-                });
-
-                describe("if local ESLint is 3.19.0,", () => {
-                    before(() => {
-                        localESLintVersion = "3.19.0";
-                    });
-
-                    it("should return false.", () => {
-                        const result = init.hasESLintVersionConflict({ styleguide: "airbnb" });
-
-                        assert.strictEqual(result, false);
-                    });
-                });
-
-                describe("if local ESLint is 4.0.0,", () => {
-                    before(() => {
-                        localESLintVersion = "4.0.0";
-                    });
-
-                    it("should return true.", () => {
-                        const result = init.hasESLintVersionConflict({ styleguide: "airbnb" });
-
-                        assert.strictEqual(result, true);
-                    });
-                });
-
-                describe("if local ESLint is 3.18.0,", () => {
-                    before(() => {
-                        localESLintVersion = "3.18.0";
-                    });
-
-                    it("should return true.", () => {
-                        const result = init.hasESLintVersionConflict({ styleguide: "airbnb" });
-
-                        assert.strictEqual(result, true);
-                    });
-                });
-            });
-
-            it("should support the standard style guide with Vue.js", () => {
-                const config = {
-                    plugins: ["vue"],
-                    extends: ["plugin:vue/essential", "standard"]
-                };
-                const modules = init.getModulesList(config);
-
-                assert.include(modules, "eslint-plugin-vue@latest");
-                assert.include(modules, "eslint-config-standard@latest");
-            });
-
-            it("should support custom parser", () => {
-                const config = {
-                    parser: "@typescript-eslint/parser"
-                };
-                const modules = init.getModulesList(config);
-
-                assert.include(modules, "@typescript-eslint/parser@latest");
-            });
-
-            it("should support custom parser with Vue.js", () => {
-                const config = {
-
-                    // We should declare the parser at `parserOptions` when using with `eslint-plugin-vue`.
-                    parserOptions: {
-                        parser: "@typescript-eslint/parser"
-                    }
-                };
-                const modules = init.getModulesList(config);
-
-                assert.include(modules, "@typescript-eslint/parser@latest");
-            });
-        });
-
-        describe("auto", () => {
-            const completeSpy = sinon.spy();
-            let config;
-
-            before(() => {
-                const patterns = [
-                    getFixturePath("lib"),
-                    getFixturePath("tests")
-                ].join(" ");
-
-                answers = {
-                    purpose: "style",
-                    source: "auto",
-                    patterns,
-                    env: ["browser"],
-                    format: "JSON"
-                };
-
-                sinon.stub(console, "log"); // necessary to replace, because of progress bar
-
-                process.chdir(fixtureDir);
-                config = init.processAnswers(answers);
-                sinon.restore();
-            });
-
-            after(() => {
-                sinon.restore();
-            });
-
-            afterEach(() => {
-                process.chdir(originalDir);
-                sinon.restore();
-            });
-
-            it("should create a config", () => {
-                assert.isTrue(completeSpy.notCalled);
-                assert.ok(config);
-            });
-
-            it("should create the config based on examined files", () => {
-                assert.deepStrictEqual(config.rules.quotes, ["error", "double"]);
-                assert.strictEqual(config.rules.semi, "off");
-            });
-
-            it("should extend and not disable recommended rules", () => {
-                assert.strictEqual(config.extends, "eslint:recommended");
-                assert.notProperty(config.rules, "no-debugger");
-            });
-
-            it("should not include deprecated rules", () => {
-                assert.notProperty(config.rules, "id-blacklist");
-                assert.notProperty(config.rules, "no-negated-in-lhs");
-                assert.notProperty(config.rules, "no-process-exit");
-                assert.notProperty(config.rules, "no-spaced-func");
-                assert.notProperty(config.rules, "prefer-reflect");
-            });
-
-            it("should support new ES features if using later ES version", () => {
-                const filename = getFixturePath("new-es-features");
-
-                answers.patterns = filename;
-                answers.ecmaVersion = 2017;
-                process.chdir(fixtureDir);
-                config = init.processAnswers(answers);
-            });
-
-            it("should throw on fatal parsing error", () => {
-                const filename = getFixturePath("parse-error");
-
-                sinon.stub(autoconfig, "extendFromRecommended");
-                answers.patterns = filename;
-                process.chdir(fixtureDir);
-                assert.throws(() => {
-                    config = init.processAnswers(answers);
-                }, "Parsing error: Unexpected token ;");
-            });
-
-            it("should throw if no files are matched from patterns", () => {
-                sinon.stub(autoconfig, "extendFromRecommended");
-                answers.patterns = "not-a-real-filename";
-                process.chdir(fixtureDir);
-                assert.throws(() => {
-                    config = init.processAnswers(answers);
-                }, "No files matching 'not-a-real-filename' were found.");
-            });
-        });
-    });
-
-    describe("writeFile()", () => {
-
-        beforeEach(() => {
-            answers = {
-                purpose: "style",
-                source: "prompt",
-                extendDefault: true,
-                indent: 2,
-                quotes: "single",
-                linebreak: "unix",
-                semi: true,
-                moduleType: "esm",
-                es6Globals: true,
-                env: ["browser"],
-                format: "JSON"
-            };
-
-            pkgJSONContents = {
-                name: "config-initializer",
-                version: "1.0.0"
-            };
-
-            process.chdir(fixtureDir);
-
-            pkgJSONPath = path.resolve(fixtureDir, "package.json");
-        });
-
-        afterEach(() => {
-            process.chdir(originalDir);
-        });
-
-        it("should create .eslintrc.json", () => {
-            const config = init.processAnswers(answers);
-            const filePath = path.resolve(fixtureDir, ".eslintrc.json");
-
-            fs.writeFileSync(pkgJSONPath, JSON.stringify(pkgJSONContents));
-
-            init.writeFile(config, answers.format);
-
-            assert.isTrue(fs.existsSync(filePath));
-
-            fs.unlinkSync(filePath);
-            fs.unlinkSync(pkgJSONPath);
-        });
-
-        it("should create .eslintrc.js", () => {
-            answers.format = "JavaScript";
-
-            const config = init.processAnswers(answers);
-            const filePath = path.resolve(fixtureDir, ".eslintrc.js");
-
-            fs.writeFileSync(pkgJSONPath, JSON.stringify(pkgJSONContents));
-
-            init.writeFile(config, answers.format);
-
-            assert.isTrue(fs.existsSync(filePath));
-
-            fs.unlinkSync(filePath);
-            fs.unlinkSync(pkgJSONPath);
-        });
-
-        it("should create .eslintrc.yml", () => {
-            answers.format = "YAML";
-
-            const config = init.processAnswers(answers);
-            const filePath = path.resolve(fixtureDir, ".eslintrc.yml");
-
-            fs.writeFileSync(pkgJSONPath, JSON.stringify(pkgJSONContents));
-
-            init.writeFile(config, answers.format);
-
-            assert.isTrue(fs.existsSync(filePath));
-
-            fs.unlinkSync(filePath);
-            fs.unlinkSync(pkgJSONPath);
-        });
-
-        // For https://github.com/eslint/eslint/issues/14137
-        it("should create .eslintrc.cjs", () => {
-            answers.format = "JavaScript";
-
-            // create package.json with "type": "module"
-            pkgJSONContents.type = "module";
-
-            fs.writeFileSync(pkgJSONPath, JSON.stringify(pkgJSONContents));
-
-            const config = init.processAnswers(answers);
-            const filePath = path.resolve(fixtureDir, ".eslintrc.cjs");
-
-            init.writeFile(config, answers.format);
-
-            assert.isTrue(fs.existsSync(filePath));
-
-            fs.unlinkSync(filePath);
-            fs.unlinkSync(pkgJSONPath);
-        });
-
-        it("should create .eslintrc.json even with type: 'module'", () => {
-            answers.format = "JSON";
-
-            // create package.json with "type": "module"
-            pkgJSONContents.type = "module";
-
-            fs.writeFileSync(pkgJSONPath, JSON.stringify(pkgJSONContents));
-
-            const config = init.processAnswers(answers);
-            const filePath = path.resolve(fixtureDir, ".eslintrc.json");
-
-            init.writeFile(config, answers.format);
-
-            assert.isTrue(fs.existsSync(filePath));
-
-            fs.unlinkSync(filePath);
-            fs.unlinkSync(pkgJSONPath);
-        });
-    });
-});
diff --git a/tests/lib/init/npm-utils.js b/tests/lib/init/npm-utils.js
deleted file mode 100644
index 8465796a3..000000000
--- a/tests/lib/init/npm-utils.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/**
- * @fileoverview Tests for rule fixer.
- * @author Ian VanSchooten
- */
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const
-    assert = require("chai").assert,
-    spawn = require("cross-spawn"),
-    sinon = require("sinon"),
-    npmUtils = require("../../../lib/init/npm-utils"),
-    log = require("../../../lib/shared/logging"),
-    { defineInMemoryFs } = require("../../_utils");
-
-const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Import `npm-utils` with the in-memory file system.
- * @param {Object} files The file definitions.
- * @returns {Object} `npm-utils`.
- */
-function requireNpmUtilsWithInMemoryFileSystem(files) {
-    const fs = defineInMemoryFs({ files });
-
-    return proxyquire("../../../lib/init/npm-utils", { fs });
-}
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-describe("npmUtils", () => {
-    afterEach(() => {
-        sinon.verifyAndRestore();
-    });
-
-    describe("checkDevDeps()", () => {
-        let installStatus;
-
-        before(() => {
-            installStatus = npmUtils.checkDevDeps(["debug", "mocha", "notarealpackage", "jshint"]);
-        });
-
-        it("should not find a direct dependency of the project", () => {
-            assert.isFalse(installStatus.debug);
-        });
-
-        it("should find a dev dependency of the project", () => {
-            assert.isTrue(installStatus.mocha);
-        });
-
-        it("should not find non-dependencies", () => {
-            assert.isFalse(installStatus.notarealpackage);
-        });
-
-        it("should not find nested dependencies", () => {
-            assert.isFalse(installStatus.jshint);
-        });
-
-        it("should return false for a single, non-existent package", () => {
-            installStatus = npmUtils.checkDevDeps(["notarealpackage"]);
-            assert.isFalse(installStatus.notarealpackage);
-        });
-
-        it("should handle missing devDependencies key", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({
-                "package.json": JSON.stringify({ private: true, dependencies: {} })
-            });
-
-            // Should not throw.
-            stubbedNpmUtils.checkDevDeps(["some-package"]);
-        });
-
-        it("should throw with message when parsing invalid package.json", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({
-                "package.json": "{ \"not: \"valid json\" }"
-            });
-
-            assert.throws(() => {
-                try {
-                    stubbedNpmUtils.checkDevDeps(["some-package"]);
-                } catch (error) {
-                    assert.strictEqual(error.messageTemplate, "failed-to-read-json");
-                    throw error;
-                }
-            }, "SyntaxError: Unexpected token v");
-        });
-    });
-
-    describe("checkDeps()", () => {
-        let installStatus;
-
-        before(() => {
-            installStatus = npmUtils.checkDeps(["debug", "mocha", "notarealpackage", "jshint"]);
-        });
-
-        it("should find a direct dependency of the project", () => {
-            assert.isTrue(installStatus.debug);
-        });
-
-        it("should not find a dev dependency of the project", () => {
-            assert.isFalse(installStatus.mocha);
-        });
-
-        it("should not find non-dependencies", () => {
-            assert.isFalse(installStatus.notarealpackage);
-        });
-
-        it("should not find nested dependencies", () => {
-            assert.isFalse(installStatus.jshint);
-        });
-
-        it("should return false for a single, non-existent package", () => {
-            installStatus = npmUtils.checkDeps(["notarealpackage"]);
-            assert.isFalse(installStatus.notarealpackage);
-        });
-
-        it("should throw if no package.json can be found", () => {
-            assert.throws(() => {
-                installStatus = npmUtils.checkDeps(["notarealpackage"], "/fakepath");
-            }, "Could not find a package.json file");
-        });
-
-        it("should handle missing dependencies key", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({
-                "package.json": JSON.stringify({ private: true, devDependencies: {} })
-            });
-
-            // Should not throw.
-            stubbedNpmUtils.checkDeps(["some-package"]);
-        });
-
-        it("should throw with message when parsing invalid package.json", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({
-                "package.json": "{ \"not: \"valid json\" }"
-            });
-
-            assert.throws(() => {
-                try {
-                    stubbedNpmUtils.checkDeps(["some-package"]);
-                } catch (error) {
-                    assert.strictEqual(error.messageTemplate, "failed-to-read-json");
-                    throw error;
-                }
-            }, "SyntaxError: Unexpected token v");
-        });
-    });
-
-    describe("checkPackageJson()", () => {
-        it("should return true if package.json exists", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({
-                "package.json": "{ \"file\": \"contents\" }"
-            });
-
-            assert.strictEqual(stubbedNpmUtils.checkPackageJson(), true);
-        });
-
-        it("should return false if package.json does not exist", () => {
-            const stubbedNpmUtils = requireNpmUtilsWithInMemoryFileSystem({});
-
-            assert.strictEqual(stubbedNpmUtils.checkPackageJson(), false);
-        });
-    });
-
-    describe("installSyncSaveDev()", () => {
-        it("should invoke npm to install a single desired package", () => {
-            const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });
-
-            npmUtils.installSyncSaveDev("desired-package");
-            assert(stub.calledOnce);
-            assert.strictEqual(stub.firstCall.args[0], "npm");
-            assert.deepStrictEqual(stub.firstCall.args[1], ["i", "--save-dev", "desired-package"]);
-            stub.restore();
-        });
-
-        it("should accept an array of packages to install", () => {
-            const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });
-
-            npmUtils.installSyncSaveDev(["first-package", "second-package"]);
-            assert(stub.calledOnce);
-            assert.strictEqual(stub.firstCall.args[0], "npm");
-            assert.deepStrictEqual(stub.firstCall.args[1], ["i", "--save-dev", "first-package", "second-package"]);
-            stub.restore();
-        });
-
-        it("should log an error message if npm throws ENOENT error", () => {
-            const logErrorStub = sinon.stub(log, "error");
-            const npmUtilsStub = sinon.stub(spawn, "sync").returns({ error: { code: "ENOENT" } });
-
-            npmUtils.installSyncSaveDev("some-package");
-
-            assert(logErrorStub.calledOnce);
-
-            logErrorStub.restore();
-            npmUtilsStub.restore();
-        });
-    });
-
-    describe("fetchPeerDependencies()", () => {
-        it("should execute 'npm show --json <packageName> peerDependencies' command", () => {
-            const stub = sinon.stub(spawn, "sync").returns({ stdout: "" });
-
-            npmUtils.fetchPeerDependencies("desired-package");
-            assert(stub.calledOnce);
-            assert.strictEqual(stub.firstCall.args[0], "npm");
-            assert.deepStrictEqual(stub.firstCall.args[1], ["show", "--json", "desired-package", "peerDependencies"]);
-            stub.restore();
-        });
-
-        it("should return null if npm throws ENOENT error", () => {
-            const stub = sinon.stub(spawn, "sync").returns({ error: { code: "ENOENT" } });
-
-            const peerDependencies = npmUtils.fetchPeerDependencies("desired-package");
-
-            assert.isNull(peerDependencies);
-
-            stub.restore();
-        });
-    });
-});
diff --git a/tests/lib/init/source-code-utils.js b/tests/lib/init/source-code-utils.js
deleted file mode 100644
index 994d23d31..000000000
--- a/tests/lib/init/source-code-utils.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * @fileoverview Tests for source-code-util.
- * @author Ian VanSchooten
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const path = require("path"),
-    fs = require("fs"),
-    os = require("os"),
-    assert = require("chai").assert,
-    sinon = require("sinon"),
-    sh = require("shelljs"),
-    { SourceCode } = require("../../../lib/source-code");
-
-const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
-const originalDir = process.cwd();
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-describe("SourceCodeUtil", () => {
-
-    let fixtureDir,
-        getSourceCodeOfFiles;
-
-    /**
-     * Returns the path inside of the fixture directory.
-     * @param {...string} args file path segments.
-     * @returns {string} The path inside the fixture directory.
-     * @private
-     */
-    function getFixturePath(...args) {
-        let filepath = path.join(fixtureDir, ...args);
-
-        try {
-            filepath = fs.realpathSync(filepath);
-            return filepath;
-        } catch {
-            return filepath;
-        }
-    }
-
-    const log = {
-        info: sinon.spy(),
-        error: sinon.spy()
-    };
-    const requireStubs = {
-        "../logging": log
-    };
-
-    // copy into clean area so as not to get "infected" by this project's .eslintrc files
-    before(() => {
-        fixtureDir = `${os.tmpdir()}/eslint/fixtures/source-code-util`;
-        sh.mkdir("-p", fixtureDir);
-        sh.cp("-r", "./tests/fixtures/source-code-util/.", fixtureDir);
-        fixtureDir = fs.realpathSync(fixtureDir);
-    });
-
-    beforeEach(() => {
-        getSourceCodeOfFiles = proxyquire("../../../lib/init/source-code-utils", requireStubs).getSourceCodeOfFiles;
-    });
-
-    afterEach(() => {
-        log.info.resetHistory();
-        log.error.resetHistory();
-    });
-
-    after(() => {
-        sh.rm("-r", fixtureDir);
-    });
-
-    describe("getSourceCodeOfFiles()", () => {
-
-        it("should handle single string filename arguments", () => {
-            const filename = getFixturePath("foo.js");
-            const sourceCode = getSourceCodeOfFiles(filename, { cwd: fixtureDir });
-
-            assert.isObject(sourceCode);
-        });
-
-        it("should accept an array of string filenames", () => {
-            const fooFilename = getFixturePath("foo.js");
-            const barFilename = getFixturePath("bar.js");
-            const sourceCode = getSourceCodeOfFiles([fooFilename, barFilename], { cwd: fixtureDir });
-
-            assert.isObject(sourceCode);
-        });
-
-        it("should accept a glob argument", () => {
-            const glob = getFixturePath("*.js");
-            const filename = getFixturePath("foo.js");
-            const sourceCode = getSourceCodeOfFiles(glob, { cwd: fixtureDir });
-
-            assert.isObject(sourceCode);
-            assert.property(sourceCode, filename);
-        });
-
-        it("should accept a relative filename", () => {
-            const filename = "foo.js";
-            const sourceCode = getSourceCodeOfFiles(filename, { cwd: fixtureDir });
-
-            assert.isObject(sourceCode);
-            assert.property(sourceCode, getFixturePath(filename));
-        });
-
-        it("should accept a relative path to a file in a parent directory", () => {
-            const filename = "../foo.js";
-            const sourceCode = getSourceCodeOfFiles(filename, { cwd: getFixturePath("nested") });
-
-            assert.isObject(sourceCode);
-            assert.property(sourceCode, getFixturePath("foo.js"));
-        });
-
-        it("should accept a callback", () => {
-            const filename = getFixturePath("foo.js");
-            const spy = sinon.spy();
-
-            process.chdir(fixtureDir);
-            getSourceCodeOfFiles(filename, {}, spy);
-            process.chdir(originalDir);
-            assert(spy.calledOnce);
-        });
-
-        it("should call the callback with total number of files being processed", () => {
-            const filename = getFixturePath("foo.js");
-            const spy = sinon.spy();
-
-            process.chdir(fixtureDir);
-            getSourceCodeOfFiles(filename, {}, spy);
-            process.chdir(originalDir);
-            assert.strictEqual(spy.firstCall.args[0], 1);
-        });
-
-        it("should create an object with located filenames as keys", () => {
-            const fooFilename = getFixturePath("foo.js");
-            const barFilename = getFixturePath("bar.js");
-            const sourceCode = getSourceCodeOfFiles([fooFilename, barFilename], { cwd: fixtureDir });
-
-            assert.property(sourceCode, fooFilename);
-            assert.property(sourceCode, barFilename);
-        });
-
-        it("should should not include non-existent filenames in results", () => {
-            const filename = getFixturePath("missing.js");
-
-            assert.throws(() => {
-                getSourceCodeOfFiles(filename, { cwd: fixtureDir });
-            }, `No files matching '${filename}' were found.`);
-        });
-
-        it("should throw for files with parsing errors", () => {
-            const filename = getFixturePath("parse-error", "parse-error.js");
-
-            assert.throw(() => {
-                getSourceCodeOfFiles(filename, { cwd: fixtureDir });
-            }, /Parsing error: Unexpected token ;/u);
-
-        });
-
-        it("should obtain the sourceCode of a file", () => {
-            const filename = getFixturePath("foo.js");
-            const sourceCode = getSourceCodeOfFiles(filename, { cwd: fixtureDir });
-
-            assert.isObject(sourceCode);
-            assert.instanceOf(sourceCode[filename], SourceCode);
-        });
-
-        it("should obtain the sourceCode of JSX files", () => {
-            const filename = getFixturePath("jsx", "foo.jsx");
-            const options = {
-                cwd: fixtureDir,
-                parserOptions: {
-                    ecmaFeatures: {
-                        jsx: true
-                    }
-                }
-            };
-            const sourceCode = getSourceCodeOfFiles(filename, options);
-
-            assert.isObject(sourceCode);
-            assert.instanceOf(sourceCode[filename], SourceCode);
-        });
-
-        it("should honor .eslintignore files by default", () => {
-            const glob = getFixturePath("*.js");
-            const unignoredFilename = getFixturePath("foo.js");
-            const ignoredFilename = getFixturePath("ignored.js");
-            const sourceCode = getSourceCodeOfFiles(glob, { cwd: fixtureDir });
-
-            assert.property(sourceCode, unignoredFilename);
-            assert.notProperty(sourceCode, ignoredFilename);
-        });
-
-        it("should obtain the sourceCode of all files in a specified folder", () => {
-            const folder = getFixturePath("nested");
-            const fooFile = getFixturePath("nested/foo.js");
-            const barFile = getFixturePath("nested/bar.js");
-            const sourceCode = getSourceCodeOfFiles(folder, { cwd: fixtureDir });
-
-            assert.strictEqual(Object.keys(sourceCode).length, 2);
-            assert.instanceOf(sourceCode[fooFile], SourceCode);
-            assert.instanceOf(sourceCode[barFile], SourceCode);
-        });
-
-        it("should accept cli options", () => {
-            const pattern = getFixturePath("ext");
-            const abcFile = getFixturePath("ext/foo.abc");
-            const cliOptions = { extensions: [".abc"], cwd: fixtureDir };
-            const sourceCode = getSourceCodeOfFiles(pattern, cliOptions);
-
-            assert.strictEqual(Object.keys(sourceCode).length, 1);
-            assert.instanceOf(sourceCode[abcFile], SourceCode);
-        });
-
-        it("should execute the callback function, if provided", () => {
-            const callback = sinon.spy();
-            const filename = getFixturePath("foo.js");
-
-            getSourceCodeOfFiles(filename, { cwd: fixtureDir }, callback);
-            assert(callback.calledOnce);
-        });
-
-        it("should execute callback function once per file", () => {
-            const callback = sinon.spy();
-            const fooFilename = getFixturePath("foo.js");
-            const barFilename = getFixturePath("bar.js");
-
-            getSourceCodeOfFiles([fooFilename, barFilename], { cwd: fixtureDir }, callback);
-            assert.strictEqual(callback.callCount, 2);
-        });
-
-        it("should call callback function with total number of files with sourceCode", () => {
-            const callback = sinon.spy();
-            const firstFn = getFixturePath("foo.js");
-            const secondFn = getFixturePath("bar.js");
-            const thirdFn = getFixturePath("nested/foo.js");
-
-            getSourceCodeOfFiles([firstFn, secondFn, thirdFn], { cwd: fixtureDir }, callback);
-            assert(callback.calledWith(3));
-        });
-
-    });
-
-});
diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js
index c6383837d..39ebddcfd 100644
--- a/tests/lib/rule-tester/rule-tester.js
+++ b/tests/lib/rule-tester/rule-tester.js
@@ -2295,27 +2295,27 @@ describe("RuleTester", () => {
         });
     });
 
-    describe("naming test cases", () => {
-
-        /**
-         * Asserts that a particular value will be emitted from an EventEmitter.
-         * @param {EventEmitter} emitter The emitter that should emit a value
-         * @param {string} emitType The type of emission to listen for
-         * @param {any} expectedValue The value that should be emitted
-         * @returns {Promise<void>} A Promise that fulfills if the value is emitted, and rejects if something else is emitted.
-         * The Promise will be indefinitely pending if no value is emitted.
-         */
-        function assertEmitted(emitter, emitType, expectedValue) {
-            return new Promise((resolve, reject) => {
-                emitter.once(emitType, emittedValue => {
-                    if (emittedValue === expectedValue) {
-                        resolve();
-                    } else {
-                        reject(new Error(`Expected ${expectedValue} to be emitted but ${emittedValue} was emitted instead.`));
-                    }
-                });
+    /**
+     * Asserts that a particular value will be emitted from an EventEmitter.
+     * @param {EventEmitter} emitter The emitter that should emit a value
+     * @param {string} emitType The type of emission to listen for
+     * @param {any} expectedValue The value that should be emitted
+     * @returns {Promise<void>} A Promise that fulfills if the value is emitted, and rejects if something else is emitted.
+     * The Promise will be indefinitely pending if no value is emitted.
+     */
+    function assertEmitted(emitter, emitType, expectedValue) {
+        return new Promise((resolve, reject) => {
+            emitter.once(emitType, emittedValue => {
+                if (emittedValue === expectedValue) {
+                    resolve();
+                } else {
+                    reject(new Error(`Expected ${expectedValue} to be emitted but ${emittedValue} was emitted instead.`));
+                }
             });
-        }
+        });
+    }
+
+    describe("naming test cases", () => {
 
         it("should use the first argument as the name of the test suite", () => {
             const assertion = assertEmitted(ruleTesterTestEmitter, "describe", "this-is-a-rule-name");
@@ -2628,4 +2628,45 @@ describe("RuleTester", () => {
         });
     });
 
+    it("should allow subclasses to set the describe/it/itOnly statics and should correctly use those values", () => {
+        const assertionDescribe = assertEmitted(ruleTesterTestEmitter, "custom describe", "this-is-a-rule-name");
+        const assertionIt = assertEmitted(ruleTesterTestEmitter, "custom it", "valid(code);");
+        const assertionItOnly = assertEmitted(ruleTesterTestEmitter, "custom itOnly", "validOnly(code);");
+
+        /**
+         * Subclass for testing
+         */
+        class RuleTesterSubclass extends RuleTester { }
+        RuleTesterSubclass.describe = function(text, method) {
+            ruleTesterTestEmitter.emit("custom describe", text, method);
+            return method.call(this);
+        };
+        RuleTesterSubclass.it = function(text, method) {
+            ruleTesterTestEmitter.emit("custom it", text, method);
+            return method.call(this);
+        };
+        RuleTesterSubclass.itOnly = function(text, method) {
+            ruleTesterTestEmitter.emit("custom itOnly", text, method);
+            return method.call(this);
+        };
+
+        const ruleTesterSubclass = new RuleTesterSubclass();
+
+        ruleTesterSubclass.run("this-is-a-rule-name", require("../../fixtures/testers/rule-tester/no-var"), {
+            valid: [
+                "valid(code);",
+                {
+                    code: "validOnly(code);",
+                    only: true
+                }
+            ],
+            invalid: []
+        });
+
+        return Promise.all([
+            assertionDescribe,
+            assertionIt,
+            assertionItOnly
+        ]);
+    });
 });
diff --git a/tests/lib/rules/camelcase.js b/tests/lib/rules/camelcase.js
index 514eb85d2..3a47a1b4b 100644
--- a/tests/lib/rules/camelcase.js
+++ b/tests/lib/rules/camelcase.js
@@ -164,11 +164,32 @@ ruleTester.run("camelcase", rule, {
             options: [{ ignoreImports: true }],
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
         },
+        {
+            code: "import { snake_cased as snake_cased } from 'mod'",
+            options: [{ ignoreImports: true }],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" }
+        },
+        {
+            code: "import { 'snake_cased' as snake_cased } from 'mod'",
+            options: [{ ignoreImports: true }],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" }
+        },
         {
             code: "import { camelCased } from 'mod'",
             options: [{ ignoreImports: false }],
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
         },
+
+        // this rule doesn't apply to quoted module export names, as it doesn't apply to quoted property names.
+        {
+            code: "export { a as 'snake_cased' } from 'mod'",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" }
+        },
+        {
+            code: "export * as 'snake_cased' from 'mod'",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" }
+        },
+
         {
             code: "var _camelCased = aGlobalVariable",
             options: [{ ignoreGlobals: false }],
@@ -668,6 +689,29 @@ ruleTester.run("camelcase", rule, {
                 }
             ]
         },
+        {
+            code: "import { 'snake_cased' as snake_cased } from 'mod'",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: [
+                {
+                    messageId: "notCamelCase",
+                    data: { name: "snake_cased" },
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "import { 'snake_cased' as another_snake_cased } from 'mod'",
+            options: [{ ignoreImports: true }],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: [
+                {
+                    messageId: "notCamelCase",
+                    data: { name: "another_snake_cased" },
+                    type: "Identifier"
+                }
+            ]
+        },
         {
             code: "import { camelCased, no_camelcased } from \"external-module\";",
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
diff --git a/tests/lib/rules/id-match.js b/tests/lib/rules/id-match.js
index de66d8b8d..7e469bd4d 100644
--- a/tests/lib/rules/id-match.js
+++ b/tests/lib/rules/id-match.js
@@ -894,6 +894,26 @@ ruleTester.run("id-match", rule, {
                     type: "Identifier"
                 }
             ]
+        },
+
+        // https://github.com/eslint/eslint/issues/15443
+        {
+            code: `
+            const foo = {
+                [a]: 1,
+            };
+            `,
+            options: ["^[^a]", {
+                properties: false,
+                onlyDeclarations: false
+            }],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                {
+                    message: "Identifier 'a' does not match the pattern '^[^a]'.",
+                    type: "Identifier"
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/keyword-spacing.js b/tests/lib/rules/keyword-spacing.js
index 35c8a06e4..97d198f56 100644
--- a/tests/lib/rules/keyword-spacing.js
+++ b/tests/lib/rules/keyword-spacing.js
@@ -126,14 +126,53 @@ ruleTester.run("keyword-spacing", rule, {
         // as
         //----------------------------------------------------------------------
 
+        // import { a as b }
+        { code: "import { a } from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "import { a as b } from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "import { \"a\" as b } from \"foo\"", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "import{ a }from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "import{ a as b }from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "import{ \"a\"as b }from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "import{ \"a\" as b }from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "import { a as b } from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "import { \"a\"as b } from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+
+        // export { a as b }
+        { code: "let a; export { a };", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export { \"a\" } from \"foo\";", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a; export { a as b };", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "let a; export { a as \"b\" };", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\" as b } from \"foo\";", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\" as \"b\" } from \"foo\";", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a; export{ a };", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export{ \"a\" }from\"foo\";", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a; export{ a as b };", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "let a; export{ a as\"b\" };", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export{ \"a\"as b }from\"foo\";", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export{ \"a\"as\"b\" }from\"foo\";", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a; export{ a as \"b\" };", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export{ \"a\" as b }from\"foo\";", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export{ \"a\" as \"b\" }from\"foo\";", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a; export { a as b };", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "let a; export { a as\"b\" };", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\"as b } from \"foo\";", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\"as\"b\" } from \"foo\";", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+
+        // import * as a
         { code: "import * as a from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "import*as a from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "import* as a from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "import *as a from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+
+        // export * as a
         { code: "export * as a from \"foo\"", parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export * as \"a\" from \"foo\"", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "export*as a from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export*as\"a\"from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "export* as a from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export* as \"a\"from\"foo\"", options: [override("as", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "export *as a from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export *as\"a\" from \"foo\"", options: [override("as", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
 
         //----------------------------------------------------------------------
         // async
@@ -654,15 +693,21 @@ ruleTester.run("keyword-spacing", rule, {
         { code: "import {foo} from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export {foo} from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export * from \"foo\"", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export * as \"x\" from \"foo\"", parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "import{foo}from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export{foo}from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export*from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export*as x from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export*as\"x\"from\"foo\"", options: [NEITHER], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "import{foo} from \"foo\"", options: [override("from", BOTH)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export{foo} from \"foo\"", options: [override("from", BOTH)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export* from \"foo\"", options: [override("from", BOTH)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export*as\"x\" from \"foo\"", options: [override("from", BOTH)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
         { code: "import {foo}from\"foo\"", options: [override("from", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export {foo}from\"foo\"", options: [override("from", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export *from\"foo\"", options: [override("from", NEITHER)], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
+        { code: "export * as x from\"foo\"", options: [override("from", NEITHER)], parserOptions: { ecmaVersion: 2020, sourceType: "module" } },
+        { code: "export * as \"x\"from\"foo\"", options: [override("from", NEITHER)], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
 
         //----------------------------------------------------------------------
         // function
@@ -1469,6 +1514,119 @@ ruleTester.run("keyword-spacing", rule, {
         // as
         //----------------------------------------------------------------------
 
+        // import { a as b }
+        {
+            code: "import { \"a\"as b } from \"foo\"",
+            output: "import { \"a\" as b } from \"foo\"",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBefore("as")
+        },
+        {
+            code: "import{ \"a\" as b }from\"foo\"",
+            output: "import{ \"a\"as b }from\"foo\"",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBefore("as")
+        },
+        {
+            code: "import{ \"a\"as b }from\"foo\"",
+            output: "import{ \"a\" as b }from\"foo\"",
+            options: [override("as", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBefore("as")
+        },
+        {
+            code: "import { \"a\" as b } from \"foo\"",
+            output: "import { \"a\"as b } from \"foo\"",
+            options: [override("as", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBefore("as")
+        },
+
+        // export { a as b }
+        {
+            code: "let a; export { a as\"b\" };",
+            output: "let a; export { a as \"b\" };",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedAfter("as")
+        },
+        {
+            code: "export { \"a\"as b } from \"foo\";",
+            output: "export { \"a\" as b } from \"foo\";",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBefore("as")
+        },
+        {
+            code: "export { \"a\"as\"b\" } from \"foo\";",
+            output: "export { \"a\" as \"b\" } from \"foo\";",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("as")
+        },
+        {
+            code: "let a; export{ a as \"b\" };",
+            output: "let a; export{ a as\"b\" };",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedAfter("as")
+        },
+        {
+            code: "export{ \"a\" as b }from\"foo\";",
+            output: "export{ \"a\"as b }from\"foo\";",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBefore("as")
+        },
+        {
+            code: "export{ \"a\" as \"b\" }from\"foo\";",
+            output: "export{ \"a\"as\"b\" }from\"foo\";",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("as")
+        },
+        {
+            code: "let a; export{ a as\"b\" };",
+            output: "let a; export{ a as \"b\" };",
+            options: [override("as", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedAfter("as")
+        },
+        {
+            code: "export{ \"a\"as b }from\"foo\";",
+            output: "export{ \"a\" as b }from\"foo\";",
+            options: [override("as", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBefore("as")
+        },
+        {
+            code: "export{ \"a\"as\"b\" }from\"foo\";",
+            output: "export{ \"a\" as \"b\" }from\"foo\";",
+            options: [override("as", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("as")
+        },
+        {
+            code: "let a; export { a as \"b\" };",
+            output: "let a; export { a as\"b\" };",
+            options: [override("as", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedAfter("as")
+        },
+        {
+            code: "export { \"a\" as b } from \"foo\";",
+            output: "export { \"a\"as b } from \"foo\";",
+            options: [override("as", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBefore("as")
+        },
+        {
+            code: "export { \"a\" as \"b\" } from \"foo\";",
+            output: "export { \"a\"as\"b\" } from \"foo\";",
+            options: [override("as", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("as")
+        },
+
+        // import * as a
         {
             code: "import *as a from \"foo\"",
             output: "import * as a from \"foo\"",
@@ -1524,12 +1682,20 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
             errors: unexpectedBefore("as")
         },
+
+        // export * as a
         {
             code: "export *as a from \"foo\"",
             output: "export * as a from \"foo\"",
             parserOptions: { ecmaVersion: 2020, sourceType: "module" },
             errors: expectedBefore("as")
         },
+        {
+            code: "export *as\"a\" from \"foo\"",
+            output: "export * as \"a\" from \"foo\"",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("as")
+        },
         {
             code: "export* as a from\"foo\"",
             output: "export*as a from\"foo\"",
@@ -1537,6 +1703,13 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 2020, sourceType: "module" },
             errors: unexpectedBefore("as")
         },
+        {
+            code: "export* as \"a\"from\"foo\"",
+            output: "export*as\"a\"from\"foo\"",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("as")
+        },
         {
             code: "export*as a from\"foo\"",
             output: "export* as a from\"foo\"",
@@ -1544,6 +1717,13 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 2020, sourceType: "module" },
             errors: expectedBefore("as")
         },
+        {
+            code: "export*as\"a\"from\"foo\"",
+            output: "export* as \"a\"from\"foo\"",
+            options: [override("as", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("as")
+        },
         {
             code: "export * as a from \"foo\"",
             output: "export *as a from \"foo\"",
@@ -1551,6 +1731,13 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 2020, sourceType: "module" },
             errors: unexpectedBefore("as")
         },
+        {
+            code: "export * as \"a\" from \"foo\"",
+            output: "export *as\"a\" from \"foo\"",
+            options: [override("as", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("as")
+        },
 
         //----------------------------------------------------------------------
         // async
@@ -2399,6 +2586,12 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
             errors: expectedBeforeAndAfter("from")
         },
+        {
+            code: "export * as \"a\"from\"foo\"",
+            output: "export * as \"a\" from \"foo\"",
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("from")
+        },
         {
             code: "import{foo} from \"foo\"",
             output: "import{foo}from\"foo\"",
@@ -2420,6 +2613,20 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
             errors: unexpectedBeforeAndAfter("from")
         },
+        {
+            code: "export*as x from \"foo\"",
+            output: "export*as x from\"foo\"",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2020, sourceType: "module" },
+            errors: unexpectedAfter("from")
+        },
+        {
+            code: "export*as\"x\" from \"foo\"",
+            output: "export*as\"x\"from\"foo\"",
+            options: [NEITHER],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("from")
+        },
         {
             code: "import{foo}from\"foo\"",
             output: "import{foo} from \"foo\"",
@@ -2441,6 +2648,13 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
             errors: expectedBeforeAndAfter("from")
         },
+        {
+            code: "export*as\"x\"from\"foo\"",
+            output: "export*as\"x\" from \"foo\"",
+            options: [override("from", BOTH)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: expectedBeforeAndAfter("from")
+        },
         {
             code: "import {foo} from \"foo\"",
             output: "import {foo}from\"foo\"",
@@ -2462,6 +2676,20 @@ ruleTester.run("keyword-spacing", rule, {
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
             errors: unexpectedBeforeAndAfter("from")
         },
+        {
+            code: "export * as x from \"foo\"",
+            output: "export * as x from\"foo\"",
+            options: [override("from", NEITHER)],
+            parserOptions: { ecmaVersion: 2020, sourceType: "module" },
+            errors: unexpectedAfter("from")
+        },
+        {
+            code: "export * as \"x\" from \"foo\"",
+            output: "export * as \"x\"from\"foo\"",
+            options: [override("from", NEITHER)],
+            parserOptions: { ecmaVersion: 2022, sourceType: "module" },
+            errors: unexpectedBeforeAndAfter("from")
+        },
 
         //----------------------------------------------------------------------
         // function
diff --git a/tests/lib/rules/no-constant-condition.js b/tests/lib/rules/no-constant-condition.js
index 0b5f3c5a1..9cca27b90 100644
--- a/tests/lib/rules/no-constant-condition.js
+++ b/tests/lib/rules/no-constant-condition.js
@@ -175,7 +175,17 @@ ruleTester.run("no-constant-condition", rule, {
         "function* foo() {while (true) {function* foo() {yield;}yield;}}",
         "function* foo() { for (let x = yield; x < 10; x++) {yield;}yield;}",
         "function* foo() { for (let x = yield; ; x++) { yield; }}",
-        "if (new Number(x) + 1 === 2) {}"
+        "if (new Number(x) + 1 === 2) {}",
+
+        // #15467
+        "if([a]==[b]) {}",
+        "if (+[...a]) {}",
+        "if (+[...[...a]]) {}",
+        "if (`${[...a]}`) {}",
+        "if (`${[a]}`) {}",
+        "if (+[a]) {}",
+        "if (0 - [a]) {}",
+        "if (1 * [a]) {}"
     ],
     invalid: [
         { code: "for(;true;);", errors: [{ messageId: "unexpected", type: "Literal" }] },
@@ -262,8 +272,6 @@ ruleTester.run("no-constant-condition", rule, {
 
         // #5228 , typeof conditions
         { code: "if(typeof x){}", errors: [{ messageId: "unexpected", type: "UnaryExpression" }] },
-        { code: "if(`${typeof x}`){}", errors: [{ messageId: "unexpected", type: "TemplateLiteral" }] },
-        { code: "if(`${''}${typeof x}`){}", errors: [{ messageId: "unexpected", type: "TemplateLiteral" }] },
         { code: "if(typeof 'abc' === 'string'){}", errors: [{ messageId: "unexpected", type: "BinaryExpression" }] },
         { code: "if(a = typeof b){}", errors: [{ messageId: "unexpected", type: "AssignmentExpression" }] },
         { code: "if(a, typeof b){}", errors: [{ messageId: "unexpected", type: "SequenceExpression" }] },
@@ -358,18 +366,6 @@ ruleTester.run("no-constant-condition", rule, {
             code: "if(''+[]) {}",
             errors: [{ messageId: "unexpected", type: "BinaryExpression" }]
         },
-        {
-            code: "if([a]==[a]) {}",
-            errors: [{ messageId: "unexpected", type: "BinaryExpression" }]
-        },
-        {
-            code: "if([a] - '') {}",
-            errors: [{ messageId: "unexpected", type: "BinaryExpression" }]
-        },
-        {
-            code: "if(+[a]) {}",
-            errors: [{ messageId: "unexpected", type: "UnaryExpression" }]
-        },
         {
             code: "if(+1) {}",
             errors: [{ messageId: "unexpected", type: "UnaryExpression" }]
@@ -397,7 +393,9 @@ ruleTester.run("no-constant-condition", rule, {
         // Boxed primitives are always truthy
         { code: "if(new Boolean(foo)) {}", errors: [{ messageId: "unexpected" }] },
         { code: "if(new String(foo)) {}", errors: [{ messageId: "unexpected" }] },
-        { code: "if(new Number(foo)) {}", errors: [{ messageId: "unexpected" }] }
+        { code: "if(new Number(foo)) {}", errors: [{ messageId: "unexpected" }] },
 
+        // Spreading a constant array
+        { code: "if(`${[...['a']]}`) {}", errors: [{ messageId: "unexpected" }] }
     ]
 });
diff --git a/tests/lib/rules/no-restricted-exports.js b/tests/lib/rules/no-restricted-exports.js
index ac0602a25..6cde65810 100644
--- a/tests/lib/rules/no-restricted-exports.js
+++ b/tests/lib/rules/no-restricted-exports.js
@@ -16,7 +16,7 @@ const { RuleTester } = require("../../../lib/rule-tester");
 // Tests
 //------------------------------------------------------------------------------
 
-const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020, sourceType: "module" } });
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2022, sourceType: "module" } });
 
 ruleTester.run("no-restricted-exports", rule, {
     valid: [
@@ -57,8 +57,12 @@ ruleTester.run("no-restricted-exports", rule, {
         { code: "var b; export { b as a };", options: [{ restrictedNamedExports: ["x"] }] },
         { code: "export { a } from 'foo';", options: [{ restrictedNamedExports: ["x"] }] },
         { code: "export { b as a } from 'foo';", options: [{ restrictedNamedExports: ["x"] }] },
+        { code: "export { '' } from 'foo';", options: [{ restrictedNamedExports: ["undefined"] }] },
+        { code: "export { '' } from 'foo';", options: [{ restrictedNamedExports: [" "] }] },
+        { code: "export { ' ' } from 'foo';", options: [{ restrictedNamedExports: [""] }] },
+        { code: "export { ' a', 'a ' } from 'foo';", options: [{ restrictedNamedExports: ["a"] }] },
 
-        // does not mistakenly disallow non-exported identifiers that appear in named export declarations
+        // does not mistakenly disallow non-exported names that appear in named export declarations
         { code: "export var b = a;", options: [{ restrictedNamedExports: ["a"] }] },
         { code: "export let [b = a] = [];", options: [{ restrictedNamedExports: ["a"] }] },
         { code: "export const [b] = [a];", options: [{ restrictedNamedExports: ["a"] }] },
@@ -69,7 +73,10 @@ ruleTester.run("no-restricted-exports", rule, {
         { code: "export class A { a(){} }", options: [{ restrictedNamedExports: ["a"] }] },
         { code: "export class A extends B {}", options: [{ restrictedNamedExports: ["B"] }] },
         { code: "var a; export { a as b };", options: [{ restrictedNamedExports: ["a"] }] },
+        { code: "var a; export { a as 'a ' };", options: [{ restrictedNamedExports: ["a"] }] },
         { code: "export { a as b } from 'foo';", options: [{ restrictedNamedExports: ["a"] }] },
+        { code: "export { a as 'a ' } from 'foo';", options: [{ restrictedNamedExports: ["a"] }] },
+        { code: "export { 'a' as 'a ' } from 'foo';", options: [{ restrictedNamedExports: ["a"] }] },
 
         // does not check source in re-export declarations
         { code: "export { b } from 'a';", options: [{ restrictedNamedExports: ["a"] }] },
@@ -188,6 +195,59 @@ ruleTester.run("no-restricted-exports", rule, {
             errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Identifier" }]
         },
 
+        // string literals
+        {
+            code: "let a; export { a as 'a' };",
+            options: [{ restrictedNamedExports: ["a"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Literal", column: 22 }]
+        },
+        {
+            code: "let a; export { a as 'b' };",
+            options: [{ restrictedNamedExports: ["b"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "b" }, type: "Literal", column: 22 }]
+        },
+        {
+            code: "let a; export { a as ' b ' };",
+            options: [{ restrictedNamedExports: [" b "] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: " b " }, type: "Literal", column: 22 }]
+        },
+        {
+            code: "let a; export { a as '👍' };",
+            options: [{ restrictedNamedExports: ["👍"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "👍" }, type: "Literal", column: 22 }]
+        },
+        {
+            code: "export { 'a' } from 'foo';",
+            options: [{ restrictedNamedExports: ["a"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Literal" }]
+        },
+        {
+            code: "export { '' } from 'foo';",
+            options: [{ restrictedNamedExports: [""] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "" }, type: "Literal" }]
+        },
+        {
+            code: "export { ' ' } from 'foo';",
+            options: [{ restrictedNamedExports: [" "] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: " " }, type: "Literal" }]
+        },
+        {
+            code: "export { b as 'a' } from 'foo';",
+            options: [{ restrictedNamedExports: ["a"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Literal" }]
+        },
+        {
+            code: "export { b as '\\u0061' } from 'foo';",
+            options: [{ restrictedNamedExports: ["a"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Literal" }]
+        },
+        {
+            code: "export * as 'a' from 'foo';",
+            options: [{ restrictedNamedExports: ["a"] }],
+            errors: [{ messageId: "restrictedNamed", data: { name: "a" }, type: "Literal" }]
+        },
+
+
         // destructuring
         {
             code: "export var [a] = [];",
diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js
index c86e67ecf..643c87ede 100644
--- a/tests/lib/rules/no-restricted-imports.js
+++ b/tests/lib/rules/no-restricted-imports.js
@@ -16,7 +16,7 @@ const rule = require("../../../lib/rules/no-restricted-imports"),
 // Tests
 //------------------------------------------------------------------------------
 
-const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2020, sourceType: "module" } });
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2022, sourceType: "module" } });
 
 ruleTester.run("no-restricted-imports", rule, {
     valid: [
@@ -54,6 +54,16 @@ ruleTester.run("no-restricted-imports", rule, {
             code: "import withPatterns from \"foo/bar\";",
             options: [{ patterns: [{ group: ["foo/*", "!foo/bar"], message: "foo is forbidden, use bar instead" }] }]
         },
+        {
+            code: "import withPatternsCaseSensitive from 'foo';",
+            options: [{
+                patterns: [{
+                    group: ["FOO"],
+                    message: "foo is forbidden, use bar instead",
+                    caseSensitive: true
+                }]
+            }]
+        },
         {
             code: "import AllowedObject from \"foo\";",
             options: [{
@@ -92,6 +102,34 @@ ruleTester.run("no-restricted-imports", rule, {
                 }]
             }]
         },
+        {
+            code: "import { 'AllowedObject' as bar } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: ["DisallowedObject"],
+                    message: "Please import 'DisallowedObject' from /bar/ instead."
+                }]
+            }]
+        },
+        {
+            code: "import { ' ' as bar } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: [""]
+                }]
+            }]
+        },
+        {
+            code: "import { '' as bar } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: [" "]
+                }]
+            }]
+        },
         {
             code: "import { DisallowedObject } from \"foo\";",
             options: [{
@@ -112,6 +150,16 @@ ruleTester.run("no-restricted-imports", rule, {
                 }]
             }]
         },
+        {
+            code: "import { 'AllowedObject' as DisallowedObject } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: ["DisallowedObject"],
+                    message: "Please import 'DisallowedObject' from /bar/ instead."
+                }]
+            }]
+        },
         {
             code: "import { AllowedObject, AllowedObjectTwo } from \"foo\";",
             options: [{
@@ -196,6 +244,24 @@ ruleTester.run("no-restricted-imports", rule, {
                 name: "bar",
                 importNames: ["DisallowedObject"]
             }]
+        },
+        {
+            code: "export { 'AllowedObject' } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: ["DisallowedObject"]
+                }]
+            }]
+        },
+        {
+            code: "export { 'AllowedObject' as DisallowedObject } from \"foo\";",
+            options: [{
+                paths: [{
+                    name: "foo",
+                    importNames: ["DisallowedObject"]
+                }]
+            }]
         }
     ],
     invalid: [{
@@ -288,6 +354,16 @@ ruleTester.run("no-restricted-imports", rule, {
             column: 1,
             endColumn: 36
         }]
+    }, {
+        code: "import withPatternsCaseInsensitive from 'foo';",
+        options: [{ patterns: [{ group: ["FOO"] }] }],
+        errors: [{
+            message: "'foo' import is restricted from being used by a pattern.",
+            type: "ImportDeclaration",
+            line: 1,
+            column: 1,
+            endColumn: 47
+        }]
     }, {
         code: "import withGitignores from \"foo/bar\";",
         options: [{ patterns: ["foo/*", "!foo/baz"] }],
@@ -344,6 +420,70 @@ ruleTester.run("no-restricted-imports", rule, {
             column: 9,
             endColumn: 17
         }]
+    }, {
+        code: "export {'foo' as b} from \"fs\";",
+        options: [{
+            paths: [{
+                name: "fs",
+                importNames: ["foo"],
+                message: "Don't import 'foo'."
+            }]
+        }],
+        errors: [{
+            message: "'foo' import from 'fs' is restricted. Don't import 'foo'.",
+            type: "ExportNamedDeclaration",
+            line: 1,
+            column: 9,
+            endColumn: 19
+        }]
+    }, {
+        code: "export {'foo'} from \"fs\";",
+        options: [{
+            paths: [{
+                name: "fs",
+                importNames: ["foo"],
+                message: "Don't import 'foo'."
+            }]
+        }],
+        errors: [{
+            message: "'foo' import from 'fs' is restricted. Don't import 'foo'.",
+            type: "ExportNamedDeclaration",
+            line: 1,
+            column: 9,
+            endColumn: 14
+        }]
+    }, {
+        code: "export {'👍'} from \"fs\";",
+        options: [{
+            paths: [{
+                name: "fs",
+                importNames: ["👍"],
+                message: "Don't import '👍'."
+            }]
+        }],
+        errors: [{
+            message: "'👍' import from 'fs' is restricted. Don't import '👍'.",
+            type: "ExportNamedDeclaration",
+            line: 1,
+            column: 9,
+            endColumn: 13
+        }]
+    }, {
+        code: "export {''} from \"fs\";",
+        options: [{
+            paths: [{
+                name: "fs",
+                importNames: [""],
+                message: "Don't import ''."
+            }]
+        }],
+        errors: [{
+            message: "'' import from 'fs' is restricted. Don't import ''.",
+            type: "ExportNamedDeclaration",
+            line: 1,
+            column: 9,
+            endColumn: 11
+        }]
     }, {
         code: "export * as ns from \"fs\";",
         options: [{
@@ -505,6 +645,55 @@ ruleTester.run("no-restricted-imports", rule, {
             endColumn: 43
         }]
     },
+    {
+        code: "import { 'DisallowedObject' as AllowedObject } from \"foo\";",
+        options: [{
+            paths: [{
+                name: "foo",
+                importNames: ["DisallowedObject"],
+                message: "Please import 'DisallowedObject' from /bar/ instead."
+            }]
+        }],
+        errors: [{
+            message: "'DisallowedObject' import from 'foo' is restricted. Please import 'DisallowedObject' from /bar/ instead.",
+            type: "ImportDeclaration",
+            line: 1,
+            column: 10,
+            endColumn: 45
+        }]
+    },
+    {
+        code: "import { '👍' as bar } from \"foo\";",
+        options: [{
+            paths: [{
+                name: "foo",
+                importNames: ["👍"]
+            }]
+        }],
+        errors: [{
+            message: "'👍' import from 'foo' is restricted.",
+            type: "ImportDeclaration",
+            line: 1,
+            column: 10,
+            endColumn: 21
+        }]
+    },
+    {
+        code: "import { '' as bar } from \"foo\";",
+        options: [{
+            paths: [{
+                name: "foo",
+                importNames: [""]
+            }]
+        }],
+        errors: [{
+            message: "'' import from 'foo' is restricted.",
+            type: "ImportDeclaration",
+            line: 1,
+            column: 10,
+            endColumn: 19
+        }]
+    },
     {
         code: "import { AllowedObject, DisallowedObject } from \"foo\";",
         options: [{
diff --git a/tests/lib/rules/no-useless-rename.js b/tests/lib/rules/no-useless-rename.js
index 66077f2b4..262cf2cc5 100644
--- a/tests/lib/rules/no-useless-rename.js
+++ b/tests/lib/rules/no-useless-rename.js
@@ -47,11 +47,43 @@ ruleTester.run("no-useless-rename", rule, {
         "import {foo} from 'foo';",
         "import {foo as bar} from 'foo';",
         "import {foo as bar, baz as qux} from 'foo';",
+        {
+            code: "import {'foo' as bar} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
         "export {foo} from 'foo';",
         "var foo = 0;export {foo as bar};",
         "var foo = 0; var baz = 0; export {foo as bar, baz as qux};",
         "export {foo as bar} from 'foo';",
         "export {foo as bar, baz as qux} from 'foo';",
+        {
+            code: "var foo = 0; export {foo as 'bar'};",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {foo as 'bar'} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {'foo' as bar} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {'foo' as 'bar'} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {'' as ' '} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {' ' as ''} from 'baz';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
+        {
+            code: "export {'foo'} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 }
+        },
         {
             code: "const {...stuff} = myObject;",
             parserOptions: { ecmaVersion: 2018 }
@@ -380,6 +412,12 @@ ruleTester.run("no-useless-rename", rule, {
             output: "import {foo} from 'foo';",
             errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Import", name: "foo" } }]
         },
+        {
+            code: "import {'foo' as foo} from 'foo';",
+            output: "import {foo} from 'foo';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Import", name: "foo" } }]
+        },
         {
             code: "import {\\u0061 as a} from 'foo';",
             output: "import {a} from 'foo';",
@@ -418,6 +456,42 @@ ruleTester.run("no-useless-rename", rule, {
             output: "var foo = 0; export {foo};",
             errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "foo" } }]
         },
+        {
+            code: "var foo = 0; export {foo as 'foo'};",
+            output: "var foo = 0; export {foo};",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "foo" } }]
+        },
+        {
+            code: "export {foo as 'foo'} from 'bar';",
+            output: "export {foo} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "foo" } }]
+        },
+        {
+            code: "export {'foo' as foo} from 'bar';",
+            output: "export {'foo'} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "foo" } }]
+        },
+        {
+            code: "export {'foo' as 'foo'} from 'bar';",
+            output: "export {'foo'} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "foo" } }]
+        },
+        {
+            code: "export {' 👍 ' as ' 👍 '} from 'bar';",
+            output: "export {' 👍 '} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: " 👍 " } }]
+        },
+        {
+            code: "export {'' as ''} from 'bar';",
+            output: "export {''} from 'bar';",
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [{ messageId: "unnecessarilyRenamed", data: { type: "Export", name: "" } }]
+        },
         {
             code: "var a = 0; export {a as \\u0061};",
             output: "var a = 0; export {a};",
diff --git a/tests/lib/rules/quotes.js b/tests/lib/rules/quotes.js
index faf371301..d1c42b73e 100644
--- a/tests/lib/rules/quotes.js
+++ b/tests/lib/rules/quotes.js
@@ -77,6 +77,16 @@ ruleTester.run("quotes", rule, {
         { code: "import a from \"a\"; import b from 'b';", options: ["backtick"], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
         { code: "export * from \"a\"; export * from 'b';", options: ["backtick"], parserOptions: { ecmaVersion: 6, sourceType: "module" } },
 
+        // `backtick` should not warn module export names.
+        { code: "import { \"a\" as b, 'c' as d } from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "let a, c; export { a as \"b\", c as 'd' };", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\", 'b' } from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { a as \"b\", c as 'd' } from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\" as b, 'c' as d } from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export { \"a\" as \"b\", 'c' as 'd' } from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export * as \"a\" from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+        { code: "export * as 'a' from 'mod';", options: ["backtick"], parserOptions: { ecmaVersion: 2022, sourceType: "module" } },
+
         // `backtick` should not warn property/method names (not computed).
         { code: "var obj = {\"key0\": 0, 'key1': 1};", options: ["backtick"], parserOptions: { ecmaVersion: 6 } },
         { code: "class Foo { 'bar'(){} }", options: ["backtick"], parserOptions: { ecmaVersion: 6 } },
diff --git a/tests/lib/init/config-rule.js b/tests/tools/config-rule.js
similarity index 98%
rename from tests/lib/init/config-rule.js
rename to tests/tools/config-rule.js
index 425317dd2..c91f464c2 100644
--- a/tests/lib/init/config-rule.js
+++ b/tests/tools/config-rule.js
@@ -10,9 +10,9 @@
 //------------------------------------------------------------------------------
 
 const assert = require("chai").assert,
-    ConfigRule = require("../../../lib/init/config-rule"),
-    builtInRules = require("../../../lib/rules"),
-    schema = require("../../fixtures/config-rule/schemas");
+    ConfigRule = require("../../tools/config-rule"),
+    builtInRules = require("../../lib/rules"),
+    schema = require("../fixtures/config-rule/schemas");
 
 //------------------------------------------------------------------------------
 // Tests
diff --git a/tests/tools/eslint-fuzzer.js b/tests/tools/eslint-fuzzer.js
index 4723befa4..1c894b995 100644
--- a/tests/tools/eslint-fuzzer.js
+++ b/tests/tools/eslint-fuzzer.js
@@ -8,7 +8,7 @@ const assert = require("chai").assert;
 const eslint = require("../..");
 const espree = require("espree");
 const sinon = require("sinon");
-const configRule = require("../../lib/init/config-rule");
+const configRule = require("../../tools/config-rule");
 
 //------------------------------------------------------------------------------
 // Tests